summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/gpgpu-sim/Makefile7
-rw-r--r--src/gpgpu-sim/addrdec.cc39
-rw-r--r--src/gpgpu-sim/addrdec.h7
-rw-r--r--src/gpgpu-sim/dram.cc7
-rw-r--r--src/gpgpu-sim/dram.h3
-rw-r--r--src/gpgpu-sim/gpu-sim.cc47
-rw-r--r--src/gpgpu-sim/gpu-sim.h26
-rw-r--r--src/gpgpu-sim/l2cache.cc340
-rw-r--r--src/gpgpu-sim/l2cache.h131
-rw-r--r--src/gpgpu-sim/l2cache_trace.h55
-rw-r--r--src/gpgpu-sim/mem_fetch.h1
-rw-r--r--src/gpgpu-sim/shader.cc2
-rw-r--r--src/trace.cc1
-rw-r--r--src/trace.h1
-rw-r--r--src/trace_streams.tup1
15 files changed, 516 insertions, 152 deletions
diff --git a/src/gpgpu-sim/Makefile b/src/gpgpu-sim/Makefile
index e355b59..bead38a 100644
--- a/src/gpgpu-sim/Makefile
+++ b/src/gpgpu-sim/Makefile
@@ -33,10 +33,8 @@ TRACE?=0
ifeq ($(DEBUG),1)
CXXFLAGS = -Wall -DDEBUG
- CXXFLAGS_L2CACHE = -Wall -DDEBUG
else
CXXFLAGS = -Wall
- CXXFLAGS_L2CACHE = -Wall
endif
ifeq ($(TRACE),1)
@@ -47,13 +45,11 @@ include ../../version_detection.mk
ifeq ($(GNUC_CPP0X), 1)
CXXFLAGS += -std=c++0x
- CXXFLAGS_L2CACHE += -std=c++0x
endif
ifneq ($(DEBUG),1)
OPTFLAGS += -O3
else
- CXXFLAGS_L2CACHE +=
CXXFLAGS +=
endif
@@ -90,9 +86,6 @@ depend:
touch $(OUTPUT_DIR)/Makefile.makedepend
makedepend -f$(OUTPUT_DIR)/Makefile.makedepend -p$(OUTPUT_DIR)/ $(CSRCS) 2> /dev/null
-$(OUTPUT_DIR)/l2cache.$(OEXT): l2cache.cc
- $(CPP) $(OPTFLAGS) $(CXXFLAGS_L2CACHE) -o $*.$(OEXT) -c l2cache.cc
-
$(OUTPUT_DIR)/%.$(OEXT): %.cc
$(CPP) $(OPTFLAGS) $(CXXFLAGS) $(POWER_FLAGS) -o $(OUTPUT_DIR)/$*.$(OEXT) -c $*.cc
diff --git a/src/gpgpu-sim/addrdec.cc b/src/gpgpu-sim/addrdec.cc
index 9b2f339..c1fa6e5 100644
--- a/src/gpgpu-sim/addrdec.cc
+++ b/src/gpgpu-sim/addrdec.cc
@@ -71,7 +71,7 @@ new_addr_type linear_to_raw_address_translation::partition_address( new_addr_typ
} else {
// see addrdec_tlx for explanation
unsigned long long int partition_addr;
- partition_addr = ( (addr>>ADDR_CHIP_S) / Nchips) << ADDR_CHIP_S;
+ partition_addr = ( (addr>>ADDR_CHIP_S) / m_n_channel) << ADDR_CHIP_S;
partition_addr |= addr & ((1 << ADDR_CHIP_S) - 1);
return partition_addr;
}
@@ -90,8 +90,8 @@ void linear_to_raw_address_translation::addrdec_tlx(new_addr_type addr, addrdec_
// Split the given address at ADDR_CHIP_S into (MSBs,LSBs)
// - extract chip address using modulus of MSBs
// - recreate the rest of the address by stitching the quotient of MSBs and the LSBs
- addr_for_chip = (addr>>ADDR_CHIP_S) % Nchips;
- rest_of_addr = ( (addr>>ADDR_CHIP_S) / Nchips) << ADDR_CHIP_S;
+ addr_for_chip = (addr>>ADDR_CHIP_S) % m_n_channel;
+ rest_of_addr = ( (addr>>ADDR_CHIP_S) / m_n_channel) << ADDR_CHIP_S;
rest_of_addr |= addr & ((1 << ADDR_CHIP_S) - 1);
tlx->chip = addr_for_chip;
@@ -100,6 +100,11 @@ void linear_to_raw_address_translation::addrdec_tlx(new_addr_type addr, addrdec_
tlx->col = addrdec_packbits(addrdec_mask[COL], rest_of_addr, addrdec_mkhigh[COL], addrdec_mklow[COL]);
tlx->burst= addrdec_packbits(addrdec_mask[BURST], rest_of_addr, addrdec_mkhigh[BURST], addrdec_mklow[BURST]);
}
+
+ // combine the chip address and the lower bits of DRAM bank address to form the subpartition ID
+ unsigned sub_partition_addr_mask = m_n_sub_partition_in_channel - 1;
+ tlx->sub_partition = tlx->chip * m_n_sub_partition_in_channel
+ + (tlx->bk & sub_partition_addr_mask);
}
void linear_to_raw_address_translation::addrdec_parseoption(const char *option)
@@ -152,14 +157,15 @@ void linear_to_raw_address_translation::addrdec_parseoption(const char *option)
}
}
-void linear_to_raw_address_translation::init(unsigned int nchips)
+void linear_to_raw_address_translation::init(unsigned int n_channel, unsigned int n_sub_partition_in_channel)
{
unsigned i;
unsigned long long int mask;
- unsigned int nchipbits = ::LOGB2_32(nchips);
- Nchips = nchips;
+ unsigned int nchipbits = ::LOGB2_32(n_channel);
+ m_n_channel = n_channel;
+ m_n_sub_partition_in_channel = n_sub_partition_in_channel;
- gap = (nchips - ::powli(2,nchipbits));
+ gap = (n_channel - ::powli(2,nchipbits));
if (gap) {
nchipbits++;
}
@@ -280,9 +286,11 @@ void linear_to_raw_address_translation::init(unsigned int nchips)
}
} // otherwise, no need to change the masks
} else {
- // make sure nchips is power of two when explicit dram id mask is used
- assert((nchips & (nchips - 1)) == 0);
+ // make sure n_channel is power of two when explicit dram id mask is used
+ assert((n_channel & (n_channel - 1)) == 0);
}
+ // make sure m_n_sub_partition_in_channel is power of two
+ assert((m_n_sub_partition_in_channel & (m_n_sub_partition_in_channel - 1)) == 0);
addrdec_getmasklimit(addrdec_mask[CHIP], &addrdec_mkhigh[CHIP], &addrdec_mklow[CHIP] );
addrdec_getmasklimit(addrdec_mask[BK], &addrdec_mkhigh[BK], &addrdec_mklow[BK] );
@@ -348,7 +356,7 @@ void linear_to_raw_address_translation::sweep_test() const
printf("[AddrDec] ** Error: address decoding mapping aliases two addresses to same partition with same intra-partition address: %llx %llx\n", h->second, raw_addr);
abort();
} else {
- assert((int)tlx.chip < Nchips);
+ assert((int)tlx.chip < m_n_channel);
// ensure that partition_address() returns the concatenated address
if ((ADDR_CHIP_S != -1 and raw_addr >= (1ULL << ADDR_CHIP_S)) or
(ADDR_CHIP_S == -1 and raw_addr >= (1ULL << addrdec_mklow[CHIP]))) {
@@ -363,11 +371,12 @@ void linear_to_raw_address_translation::sweep_test() const
void addrdec_t::print( FILE *fp ) const
{
- if (chip) fprintf(fp,"\tchip:%x ", chip);
- if (row) fprintf(fp,"\trow:%x ", row);
- if (col) fprintf(fp,"\tcol:%x ", col);
- if (bk) fprintf(fp,"\tbk:%x ", bk);
- if (burst) fprintf(fp,"\tburst:%x ", burst);
+ fprintf(fp,"\tchip:%x ", chip);
+ fprintf(fp,"\trow:%x ", row);
+ fprintf(fp,"\tcol:%x ", col);
+ fprintf(fp,"\tbk:%x ", bk);
+ fprintf(fp,"\tburst:%x ", burst);
+ fprintf(fp,"\tsub_partition:%x ", sub_partition);
}
diff --git a/src/gpgpu-sim/addrdec.h b/src/gpgpu-sim/addrdec.h
index 94b113a..f16c9b1 100644
--- a/src/gpgpu-sim/addrdec.h
+++ b/src/gpgpu-sim/addrdec.h
@@ -43,13 +43,15 @@ struct addrdec_t {
unsigned row;
unsigned col;
unsigned burst;
+
+ unsigned sub_partition;
};
class linear_to_raw_address_translation {
public:
linear_to_raw_address_translation();
void addrdec_setoption(option_parser_t opp);
- void init(unsigned int nchips);
+ void init(unsigned int n_channel, unsigned int n_sub_partition_in_channel);
// accessors
void addrdec_tlx(new_addr_type addr, addrdec_t *tlx) const;
@@ -78,7 +80,8 @@ private:
new_addr_type addrdec_mask[N_ADDRDEC];
unsigned int gap;
- int Nchips;
+ int m_n_channel;
+ int m_n_sub_partition_in_channel;
};
#endif
diff --git a/src/gpgpu-sim/dram.cc b/src/gpgpu-sim/dram.cc
index f28db2f..92c9727 100644
--- a/src/gpgpu-sim/dram.cc
+++ b/src/gpgpu-sim/dram.cc
@@ -421,11 +421,16 @@ void dram_t::cycle()
}
//if mrq is being serviced by dram, gets popped after CL latency fulfilled
-class mem_fetch* dram_t::pop()
+class mem_fetch* dram_t::return_queue_pop()
{
return returnq->pop();
}
+class mem_fetch* dram_t::return_queue_top()
+{
+ return returnq->top();
+}
+
void dram_t::print( FILE* simFile) const
{
unsigned i;
diff --git a/src/gpgpu-sim/dram.h b/src/gpgpu-sim/dram.h
index 8c0a2b8..a8bff14 100644
--- a/src/gpgpu-sim/dram.h
+++ b/src/gpgpu-sim/dram.h
@@ -104,7 +104,8 @@ public:
unsigned int queue_limit() const;
void visualizer_print( gzFile visualizer_file );
- class mem_fetch* pop();
+ class mem_fetch* return_queue_pop();
+ class mem_fetch* return_queue_top();
void push( class mem_fetch *data );
void cycle();
void dram_log (int task);
diff --git a/src/gpgpu-sim/gpu-sim.cc b/src/gpgpu-sim/gpu-sim.cc
index 5fa487a..475833f 100644
--- a/src/gpgpu-sim/gpu-sim.cc
+++ b/src/gpgpu-sim/gpu-sim.cc
@@ -159,6 +159,9 @@ void memory_config::reg_options(class OptionParser * opp)
option_parser_register(opp, "-gpgpu_n_mem", OPT_UINT32, &m_n_mem,
"number of memory modules (e.g. memory controllers) in gpu",
"8");
+ option_parser_register(opp, "-gpgpu_n_sub_partition_per_mchannel", OPT_UINT32, &m_n_sub_partition_per_memory_channel,
+ "number of memory subpartition in each memory module",
+ "1");
option_parser_register(opp, "-gpgpu_n_mem_per_ctrlr", OPT_UINT32, &gpu_n_mem_per_ctrlr,
"number of memory chips per memory controller",
"1");
@@ -429,6 +432,9 @@ void gpgpu_sim_config::reg_options(option_parser_t opp)
option_parser_register(opp, "-trace_sampling_core", OPT_INT32,
&Trace::sampling_core, "The core which is printed using CORE_DPRINTF. Default 0",
"0");
+ option_parser_register(opp, "-trace_sampling_memory_partition", OPT_INT32,
+ &Trace::sampling_memory_partition, "The memory partition which is printed using MEMPART_DPRINTF. Default -1 (i.e. all)",
+ "-1");
ptx_file_line_stats_options(opp);
}
@@ -564,10 +570,16 @@ gpgpu_sim::gpgpu_sim( const gpgpu_sim_config &config )
m_cluster[i] = new simt_core_cluster(this,i,m_shader_config,m_memory_config,m_shader_stats,m_memory_stats);
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_sub_partition = new memory_sub_partition*[m_memory_config->m_n_mem_sub_partition];
+ 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);
+ for (unsigned p = 0; p < m_memory_config->m_n_sub_partition_per_memory_channel; p++) {
+ unsigned submpid = i * m_memory_config->m_n_sub_partition_per_memory_channel + p;
+ m_memory_sub_partition[submpid] = m_memory_partition_unit[i]->get_sub_partition(p);
+ }
+ }
- icnt_init(m_shader_config->n_simt_clusters,m_memory_config->m_n_mem);
+ icnt_init(m_shader_config->n_simt_clusters,m_memory_config->m_n_mem_sub_partition);
time_vector_create(NUM_MEM_REQ_STAT);
fprintf(stdout, "GPGPU-Sim uArch: performance model initialization complete.\n");
@@ -926,9 +938,9 @@ void gpgpu_sim::gpu_print_stat()
total_l2_css.clear();
printf("\n========= L2 cache stats =========\n");
- for (unsigned i=0;i<m_memory_config->m_n_mem;i++){
- m_memory_partition_unit[i]->accumulate_L2cache_stats(l2_stats);
- m_memory_partition_unit[i]->get_L2cache_sub_stats(l2_css);
+ for (unsigned i=0;i<m_memory_config->m_n_mem_sub_partition;i++){
+ m_memory_sub_partition[i]->accumulate_L2cache_stats(l2_stats);
+ m_memory_sub_partition[i]->get_L2cache_sub_stats(l2_css);
fprintf( stdout, "L2_cache_bank[%d]: Access = %u, Miss = %u, Miss_rate = %.3lf, Pending_hits = %u, Reservation_fails = %u\n",
i, l2_css.accesses, l2_css.misses, (double)l2_css.misses / (double)l2_css.accesses, l2_css.pending_hits, l2_css.res_fails);
@@ -1150,8 +1162,8 @@ void gpgpu_sim::cycle()
}
if (clock_mask & ICNT) {
// pop from memory controller to interconnect
- for (unsigned i=0;i<m_memory_config->m_n_mem;i++) {
- mem_fetch* mf = m_memory_partition_unit[i]->top();
+ for (unsigned i=0;i<m_memory_config->m_n_mem_sub_partition;i++) {
+ mem_fetch* mf = m_memory_sub_partition[i]->top();
if (mf) {
unsigned response_size = mf->get_is_write()?mf->get_ctrl_size():mf->size();
if ( ::icnt_has_buffer( m_shader_config->mem2device(i), response_size ) ) {
@@ -1159,12 +1171,12 @@ void gpgpu_sim::cycle()
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();
+ m_memory_sub_partition[i]->pop();
} else {
gpu_stall_icnt2sh++;
}
} else {
- m_memory_partition_unit[i]->pop();
+ m_memory_sub_partition[i]->pop();
}
}
}
@@ -1182,17 +1194,17 @@ void gpgpu_sim::cycle()
// L2 operations follow L2 clock domain
if (clock_mask & L2) {
m_power_stats->pwr_mem_stat->l2_cache_stats[CURRENT_STAT_IDX].clear();
- for (unsigned i=0;i<m_memory_config->m_n_mem;i++) {
+ for (unsigned i=0;i<m_memory_config->m_n_mem_sub_partition;i++) {
//move memory request from interconnect into memory partition (if not backed up)
//Note:This needs to be called in DRAM clock domain if there is no L2 cache in the system
- if ( m_memory_partition_unit[i]->full() ) {
+ if ( m_memory_sub_partition[i]->full() ) {
gpu_stall_dramfull++;
} else {
mem_fetch* mf = (mem_fetch*) icnt_pop( m_shader_config->mem2device(i) );
- m_memory_partition_unit[i]->push( mf, gpu_sim_cycle + gpu_tot_sim_cycle );
+ m_memory_sub_partition[i]->push( mf, gpu_sim_cycle + gpu_tot_sim_cycle );
}
- m_memory_partition_unit[i]->cache_cycle(gpu_sim_cycle+gpu_tot_sim_cycle);
- m_memory_partition_unit[i]->accumulate_L2cache_stats(m_power_stats->pwr_mem_stat->l2_cache_stats[CURRENT_STAT_IDX]);
+ m_memory_sub_partition[i]->cache_cycle(gpu_sim_cycle+gpu_tot_sim_cycle);
+ m_memory_sub_partition[i]->accumulate_L2cache_stats(m_power_stats->pwr_mem_stat->l2_cache_stats[CURRENT_STAT_IDX]);
}
}
@@ -1263,7 +1275,7 @@ void gpgpu_sim::cycle()
if (m_memory_config->m_L2_config.get_num_lines()) {
int dlc = 0;
for (unsigned i=0;i<m_memory_config->m_n_mem;i++) {
- dlc = m_memory_partition_unit[i]->flushL2();
+ dlc = m_memory_sub_partition[i]->flushL2();
assert (dlc == 0); // need to model actual writes to DRAM here
printf("Dirty lines flushed from L2 %d is %d\n", i, dlc );
}
@@ -1386,8 +1398,3 @@ simt_core_cluster * gpgpu_sim::getSIMTCluster()
return *m_cluster;
}
-void memory_partition_unit::visualizer_print( gzFile visualizer_file )
-{
- m_dram->visualizer_print(visualizer_file);
-}
-
diff --git a/src/gpgpu-sim/gpu-sim.h b/src/gpgpu-sim/gpu-sim.h
index 03f9bf2..4e6b7a5 100644
--- a/src/gpgpu-sim/gpu-sim.h
+++ b/src/gpgpu-sim/gpu-sim.h
@@ -190,20 +190,28 @@ struct memory_config {
option_parser_destroy(dram_opp);
}
- int nbkt = nbk/nbkgrp;
- unsigned i;
- for (i=0; nbkt>0; i++) {
- nbkt = nbkt>>1;
- }
- bk_tag_length = i;
+ int nbkt = nbk/nbkgrp;
+ unsigned i;
+ for (i=0; nbkt>0; i++) {
+ nbkt = nbkt>>1;
+ }
+ bk_tag_length = i;
assert(nbkgrp>0 && "Number of bank groups cannot be zero");
tRCDWR = tRCD-(WL+1);
tRTW = (CL+(BL/data_command_freq_ratio)+2-WL);
tWTR = (WL+(BL/data_command_freq_ratio)+tCDLR);
tWTP = (WL+(BL/data_command_freq_ratio)+tWR);
dram_atom_size = BL * busW * gpu_n_mem_per_ctrlr; // burst length x bus width x # chips per partition
- m_address_mapping.init(m_n_mem);
+
+ assert( m_n_sub_partition_per_memory_channel > 0 );
+ assert( (nbk % m_n_sub_partition_per_memory_channel == 0)
+ && "Number of DRAM banks must be a perfect multiple of memory sub partition");
+ m_n_mem_sub_partition = m_n_mem * m_n_sub_partition_per_memory_channel;
+ fprintf(stdout, "Total number of memory sub partition = %u\n", m_n_mem_sub_partition);
+
+ m_address_mapping.init(m_n_mem, m_n_sub_partition_per_memory_channel);
m_L2_config.init(&m_address_mapping);
+
m_valid = true;
icnt_flit_size = 32; // Default 32
}
@@ -221,6 +229,8 @@ struct memory_config {
enum dram_ctrl_t scheduler_type;
bool gpgpu_memlatency_stat;
unsigned m_n_mem;
+ unsigned m_n_sub_partition_per_memory_channel;
+ unsigned m_n_mem_sub_partition;
unsigned gpu_n_mem_per_ctrlr;
unsigned rop_latency;
@@ -416,7 +426,6 @@ private:
int next_clock_domain(void);
void issue_block2core();
void print_dram_stats(FILE *fout) const;
- void L2c_print_cache_stat() const;
void shader_print_runtime_stat( FILE *fout );
void shader_print_l1_miss_stat( FILE *fout ) const;
void shader_print_cache_stats( FILE *fout ) const;
@@ -430,6 +439,7 @@ private:
class simt_core_cluster **m_cluster;
class memory_partition_unit **m_memory_partition_unit;
+ class memory_sub_partition **m_memory_sub_partition;
std::vector<kernel_info_t*> m_running_kernels;
unsigned m_last_issued_kernel;
diff --git a/src/gpgpu-sim/l2cache.cc b/src/gpgpu-sim/l2cache.cc
index a661b4b..d667fd7 100644
--- a/src/gpgpu-sim/l2cache.cc
+++ b/src/gpgpu-sim/l2cache.cc
@@ -43,6 +43,7 @@
#include "gpu-sim.h"
#include "shader.h"
#include "mem_latency_stat.h"
+#include "l2cache_trace.h"
mem_fetch * partition_mf_allocator::alloc(new_addr_type addr, mem_access_type type, unsigned size, bool wr ) const
@@ -62,11 +63,234 @@ mem_fetch * partition_mf_allocator::alloc(new_addr_type addr, mem_access_type ty
memory_partition_unit::memory_partition_unit( unsigned partition_id,
const struct memory_config *config,
class memory_stats_t *stats )
+: m_id(partition_id), m_config(config), m_stats(stats), m_arbitration_metadata(config)
{
- m_id = partition_id;
+ m_dram = new dram_t(m_id,m_config,m_stats,this);
+
+ m_sub_partition = new memory_sub_partition*[m_config->m_n_sub_partition_per_memory_channel];
+ for (unsigned p = 0; p < m_config->m_n_sub_partition_per_memory_channel; p++) {
+ unsigned sub_partition_id = m_id * m_config->m_n_sub_partition_per_memory_channel + p;
+ m_sub_partition[p] = new memory_sub_partition(sub_partition_id, m_config, stats);
+ }
+}
+
+memory_partition_unit::~memory_partition_unit()
+{
+ delete m_dram;
+ for (unsigned p = 0; p < m_config->m_n_sub_partition_per_memory_channel; p++) {
+ delete m_sub_partition[p];
+ }
+ delete[] m_sub_partition;
+}
+
+memory_partition_unit::arbitration_metadata::arbitration_metadata(const struct memory_config *config)
+: m_last_borrower(config->m_n_sub_partition_per_memory_channel - 1),
+ m_private_credit(config->m_n_sub_partition_per_memory_channel, 0),
+ m_shared_credit(0)
+{
+ // each sub partition get at least 1 credit for forward progress
+ // the rest is shared among with other partitions
+ m_private_credit_limit = 1;
+ m_shared_credit_limit = config->gpgpu_frfcfs_dram_sched_queue_size
+ + config->gpgpu_dram_return_queue_size
+ - (config->m_n_sub_partition_per_memory_channel - 1);
+ if (config->gpgpu_frfcfs_dram_sched_queue_size == 0
+ or config->gpgpu_dram_return_queue_size == 0)
+ {
+ m_shared_credit_limit = 0; // no limit if either of the queue has no limit in size
+ }
+ assert(m_shared_credit_limit >= 0);
+}
+
+bool memory_partition_unit::arbitration_metadata::has_credits(int inner_sub_partition_id) const
+{
+ int spid = inner_sub_partition_id;
+ if (m_private_credit[spid] < m_private_credit_limit) {
+ return true;
+ } else if (m_shared_credit_limit == 0 || m_shared_credit < m_shared_credit_limit) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void memory_partition_unit::arbitration_metadata::borrow_credit(int inner_sub_partition_id)
+{
+ int spid = inner_sub_partition_id;
+ if (m_private_credit[spid] < m_private_credit_limit) {
+ m_private_credit[spid] += 1;
+ } else if (m_shared_credit_limit == 0 || m_shared_credit < m_shared_credit_limit) {
+ m_shared_credit += 1;
+ } else {
+ assert(0 && "DRAM arbitration error: Borrowing from depleted credit!");
+ }
+ m_last_borrower = spid;
+}
+
+void memory_partition_unit::arbitration_metadata::return_credit(int inner_sub_partition_id)
+{
+ int spid = inner_sub_partition_id;
+ if (m_private_credit[spid] > 0) {
+ m_private_credit[spid] -= 1;
+ } else {
+ m_shared_credit -= 1;
+ }
+ assert((m_shared_credit >= 0) && "DRAM arbitration error: Returning more than available credits!");
+}
+
+void memory_partition_unit::arbitration_metadata::print( FILE *fp ) const
+{
+ fprintf(fp, "private_credit = ");
+ for (unsigned p = 0; p < m_private_credit.size(); p++) {
+ fprintf(fp, "%d ", m_private_credit[p]);
+ }
+ fprintf(fp, "(limit = %d)\n", m_private_credit_limit);
+ fprintf(fp, "shared_credit = %d (limit = %d)\n", m_shared_credit, m_shared_credit_limit);
+}
+
+bool memory_partition_unit::busy() const
+{
+ bool busy = false;
+ for (unsigned p = 0; p < m_config->m_n_sub_partition_per_memory_channel; p++) {
+ if (m_sub_partition[p]->busy()) {
+ busy = true;
+ }
+ }
+ return busy;
+}
+
+void memory_partition_unit::cache_cycle(unsigned cycle)
+{
+ for (unsigned p = 0; p < m_config->m_n_sub_partition_per_memory_channel; p++) {
+ m_sub_partition[p]->cache_cycle(cycle);
+ }
+}
+
+void memory_partition_unit::visualizer_print( gzFile visualizer_file ) const
+{
+ m_dram->visualizer_print(visualizer_file);
+ for (unsigned p = 0; p < m_config->m_n_sub_partition_per_memory_channel; p++) {
+ m_sub_partition[p]->visualizer_print(visualizer_file);
+ }
+}
+
+// determine whether a given subpartition can issue to DRAM
+bool memory_partition_unit::can_issue_to_dram(int inner_sub_partition_id)
+{
+ int spid = inner_sub_partition_id;
+ bool sub_partition_contention = m_sub_partition[spid]->dram_L2_queue_full();
+ bool has_dram_resource = m_arbitration_metadata.has_credits(spid);
+
+ MEMPART_DPRINTF("sub partition %d sub_partition_contention=%c has_dram_resource=%c\n",
+ spid, (sub_partition_contention)? 'T':'F', (has_dram_resource)? 'T':'F');
+
+ return (has_dram_resource && !sub_partition_contention);
+}
+
+int memory_partition_unit::global_sub_partition_id_to_local_id(int global_sub_partition_id) const
+{
+ return (global_sub_partition_id - m_id * m_config->m_n_sub_partition_per_memory_channel);
+}
+
+void memory_partition_unit::dram_cycle()
+{
+ // pop completed memory request from dram and push it to dram-to-L2 queue
+ // of the original sub partition
+ mem_fetch* mf_return = m_dram->return_queue_top();
+ if (mf_return) {
+ unsigned dest_global_spid = mf_return->get_sub_partition_id();
+ int dest_spid = global_sub_partition_id_to_local_id(dest_global_spid);
+ assert(m_sub_partition[dest_spid]->get_id() == dest_global_spid);
+ if (!m_sub_partition[dest_spid]->dram_L2_queue_full()) {
+ if( mf_return->get_access_type() == L1_WRBK_ACC ) {
+ m_sub_partition[dest_spid]->set_done(mf_return);
+ delete mf_return;
+ } else {
+ m_sub_partition[dest_spid]->dram_L2_queue_push(mf_return);
+ mf_return->set_status(IN_PARTITION_DRAM_TO_L2_QUEUE,gpu_sim_cycle+gpu_tot_sim_cycle);
+ m_arbitration_metadata.return_credit(dest_spid);
+ MEMPART_DPRINTF("mem_fetch request %p return from dram to sub partition %d\n", mf_return, dest_spid);
+ }
+ m_dram->return_queue_pop();
+ }
+ } else {
+ m_dram->return_queue_pop();
+ }
+
+ m_dram->cycle();
+ m_dram->dram_log(SAMPLELOG);
+
+ if( !m_dram->full() ) {
+ // L2->DRAM queue to DRAM latency queue
+ // Arbitrate among multiple L2 subpartitions
+ int last_issued_partition = m_arbitration_metadata.last_borrower();
+ for (unsigned p = 0; p < m_config->m_n_sub_partition_per_memory_channel; p++) {
+ int spid = (p + last_issued_partition + 1) % m_config->m_n_sub_partition_per_memory_channel;
+ if (!m_sub_partition[spid]->L2_dram_queue_empty() && can_issue_to_dram(spid)) {
+ mem_fetch *mf = m_sub_partition[spid]->L2_dram_queue_top();
+ m_sub_partition[spid]->L2_dram_queue_pop();
+ MEMPART_DPRINTF("Issue mem_fetch request %p from sub partition %d to dram\n", mf, spid);
+ dram_delay_t d;
+ d.req = mf;
+ d.ready_cycle = gpu_sim_cycle+gpu_tot_sim_cycle + m_config->dram_latency;
+ m_dram_latency_queue.push(d);
+ mf->set_status(IN_PARTITION_DRAM_LATENCY_QUEUE,gpu_sim_cycle+gpu_tot_sim_cycle);
+ m_arbitration_metadata.borrow_credit(spid);
+ break; // the DRAM should only accept one request per cycle
+ }
+ }
+ }
+
+ // DRAM latency queue
+ if( !m_dram_latency_queue.empty() && ( (gpu_sim_cycle+gpu_tot_sim_cycle) >= m_dram_latency_queue.front().ready_cycle ) && !m_dram->full() ) {
+ mem_fetch* mf = m_dram_latency_queue.front().req;
+ m_dram_latency_queue.pop();
+ m_dram->push(mf);
+ }
+}
+
+void memory_partition_unit::set_done( mem_fetch *mf )
+{
+ unsigned global_spid = mf->get_sub_partition_id();
+ int spid = global_sub_partition_id_to_local_id(global_spid);
+ assert(m_sub_partition[spid]->get_id() == global_spid);
+ if (mf->get_access_type() == L1_WRBK_ACC || mf->get_access_type() == L2_WRBK_ACC) {
+ m_arbitration_metadata.return_credit(spid);
+ MEMPART_DPRINTF("mem_fetch request %p return from dram to sub partition %d\n", mf, spid);
+ }
+ m_sub_partition[spid]->set_done(mf);
+}
+
+void memory_partition_unit::set_dram_power_stats(unsigned &n_cmd,
+ unsigned &n_activity,
+ unsigned &n_nop,
+ unsigned &n_act,
+ unsigned &n_pre,
+ unsigned &n_rd,
+ unsigned &n_wr,
+ unsigned &n_req) const
+{
+ m_dram->set_dram_power_stats(n_cmd, n_activity, n_nop, n_act, n_pre, n_rd, n_wr, n_req);
+}
+
+void memory_partition_unit::print( FILE *fp ) const
+{
+ fprintf(fp, "Memory Partition %u: \n", m_id);
+ for (unsigned p = 0; p < m_config->m_n_sub_partition_per_memory_channel; p++) {
+ m_sub_partition[p]->print(fp);
+ }
+ m_dram->print(fp);
+}
+
+memory_sub_partition::memory_sub_partition( unsigned sub_partition_id,
+ const struct memory_config *config,
+ class memory_stats_t *stats )
+{
+ m_id = sub_partition_id;
m_config=config;
m_stats=stats;
- m_dram = new dram_t(m_id,m_config,m_stats,this);
+
+ assert(m_id < m_config->m_n_mem_sub_partition);
char L2c_name[32];
snprintf(L2c_name, 32, "L2_bank_%03d", m_id);
@@ -88,7 +312,7 @@ memory_partition_unit::memory_partition_unit( unsigned partition_id,
wb_addr=-1;
}
-memory_partition_unit::~memory_partition_unit()
+memory_sub_partition::~memory_sub_partition()
{
delete m_icnt_L2_queue;
delete m_L2_dram_queue;
@@ -98,7 +322,7 @@ memory_partition_unit::~memory_partition_unit()
delete m_L2interface;
}
-void memory_partition_unit::cache_cycle( unsigned cycle )
+void memory_sub_partition::cache_cycle( unsigned cycle )
{
// L2 fill responses
if( !m_config->m_L2_config.disabled()) {
@@ -189,22 +413,47 @@ void memory_partition_unit::cache_cycle( unsigned cycle )
}
}
-bool memory_partition_unit::full() const
+bool memory_sub_partition::full() const
{
return m_icnt_L2_queue->full();
}
-void memory_partition_unit::print_cache_stat(unsigned &accesses, unsigned &misses) const
+bool memory_sub_partition::L2_dram_queue_empty() const
+{
+ return m_L2_dram_queue->empty();
+}
+
+class mem_fetch* memory_sub_partition::L2_dram_queue_top() const
+{
+ return m_L2_dram_queue->top();
+}
+
+void memory_sub_partition::L2_dram_queue_pop()
+{
+ m_L2_dram_queue->pop();
+}
+
+bool memory_sub_partition::dram_L2_queue_full() const
+{
+ return m_dram_L2_queue->full();
+}
+
+void memory_sub_partition::dram_L2_queue_push( class mem_fetch* mf )
+{
+ m_dram_L2_queue->push(mf);
+}
+
+void memory_sub_partition::print_cache_stat(unsigned &accesses, unsigned &misses) const
{
FILE *fp = stdout;
if( !m_config->m_L2_config.disabled() )
m_L2cache->print(fp,accesses,misses);
}
-void memory_partition_unit::print( FILE *fp ) const
+void memory_sub_partition::print( FILE *fp ) const
{
if ( !m_request_tracker.empty() ) {
- fprintf(fp,"Memory Parition %u: pending memory requests:\n", m_id);
+ fprintf(fp,"Memory Sub 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 )
@@ -215,7 +464,6 @@ void memory_partition_unit::print( FILE *fp ) const
}
if( !m_config->m_L2_config.disabled() )
m_L2cache->display_state(fp);
- m_dram->print(fp);
}
void memory_stats_t::visualizer_print( gzFile visualizer_file )
@@ -264,26 +512,19 @@ void gpgpu_sim::print_dram_stats(FILE *fout) const
fprintf(fout,"gpgpu_n_dram_precharges = %d\n",tot_pre );
fprintf(fout,"gpgpu_n_dram_requests = %d\n",tot_req );
}
-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]->print_cache_stat(k,j);
- printf("L2 Cache Total Miss Rate = %0.3f\n", (float)j/k);
-}
-unsigned memory_partition_unit::flushL2()
+unsigned memory_sub_partition::flushL2()
{
m_L2cache->flush();
return 0; // L2 is read only in this version
}
-bool memory_partition_unit::busy() const
+bool memory_sub_partition::busy() const
{
return !m_request_tracker.empty();
}
-void memory_partition_unit::push( mem_fetch* req, unsigned long long cycle )
+void memory_sub_partition::push( mem_fetch* req, unsigned long long cycle )
{
if (req) {
m_request_tracker.insert(req);
@@ -301,7 +542,7 @@ void memory_partition_unit::push( mem_fetch* req, unsigned long long cycle )
}
}
-mem_fetch* memory_partition_unit::pop()
+mem_fetch* memory_sub_partition::pop()
{
mem_fetch* mf = m_L2_icnt_queue->pop();
m_request_tracker.erase(mf);
@@ -314,7 +555,7 @@ mem_fetch* memory_partition_unit::pop()
return mf;
}
-mem_fetch* memory_partition_unit::top()
+mem_fetch* memory_sub_partition::top()
{
mem_fetch *mf = m_L2_icnt_queue->top();
if( mf && (mf->get_access_type() == L2_WRBK_ACC || mf->get_access_type() == L1_WRBK_ACC) ) {
@@ -326,62 +567,21 @@ mem_fetch* memory_partition_unit::top()
return mf;
}
-void memory_partition_unit::set_done( mem_fetch *mf )
+void memory_sub_partition::set_done( mem_fetch *mf )
{
m_request_tracker.erase(mf);
}
-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) {
- if( mf->get_access_type() == L1_WRBK_ACC ) {
- m_request_tracker.erase(mf);
- delete mf;
- } else {
- 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() ) {
- // L2->DRAM queue to DRAM latency queue
- mem_fetch *mf = m_L2_dram_queue->pop();
- dram_delay_t d;
- d.req = mf;
- d.ready_cycle = gpu_sim_cycle+gpu_tot_sim_cycle + m_config->dram_latency;
- m_dram_latency_queue.push(d);
- mf->set_status(IN_PARTITION_DRAM_LATENCY_QUEUE,gpu_sim_cycle+gpu_tot_sim_cycle);
- }
-
- // DRAM latency queue
- if( !m_dram_latency_queue.empty() && ( (gpu_sim_cycle+gpu_tot_sim_cycle) >= m_dram_latency_queue.front().ready_cycle ) && !m_dram->full() ) {
- mem_fetch* mf = m_dram_latency_queue.front().req;
- m_dram_latency_queue.pop();
- m_dram->push(mf);
- }
+void memory_sub_partition::accumulate_L2cache_stats(class cache_stats &l2_stats) const {
+ l2_stats += m_L2cache->get_stats();
}
-void memory_partition_unit::set_dram_power_stats(unsigned &n_cmd,
- unsigned &n_activity,
- unsigned &n_nop,
- unsigned &n_act,
- unsigned &n_pre,
- unsigned &n_rd,
- unsigned &n_wr,
- unsigned &n_req) const{
- m_dram->set_dram_power_stats(n_cmd, n_activity, n_nop, n_act, n_pre, n_rd, n_wr, n_req);
+void memory_sub_partition::get_L2cache_sub_stats(struct cache_sub_stats &css) const{
+ m_L2cache->get_sub_stats(css);
}
-void memory_partition_unit::accumulate_L2cache_stats(class cache_stats &l2_stats) const {
- l2_stats += m_L2cache->get_stats();
+void memory_sub_partition::visualizer_print( gzFile visualizer_file )
+{
+ // TODO: Add visualizer stats for L2 cache
}
-void memory_partition_unit::get_L2cache_sub_stats(struct cache_sub_stats &css) const{
- m_L2cache->get_sub_stats(css);
-}
diff --git a/src/gpgpu-sim/l2cache.h b/src/gpgpu-sim/l2cache.h
index 6ef00a7..07e37ca 100644
--- a/src/gpgpu-sim/l2cache.h
+++ b/src/gpgpu-sim/l2cache.h
@@ -52,9 +52,12 @@ private:
const memory_config *m_memory_config;
};
-class memory_partition_unit
+// Memory partition unit contains all the units assolcated with a single DRAM channel.
+// - It arbitrates the DRAM channel among multiple sub partitions.
+// - It does not connect directly with the interconnection network.
+class memory_partition_unit
{
-public:
+public:
memory_partition_unit( unsigned partition_id, const struct memory_config *config, class memory_stats_t *stats );
~memory_partition_unit();
@@ -63,6 +66,93 @@ public:
void cache_cycle( unsigned cycle );
void dram_cycle();
+ void set_done( mem_fetch *mf );
+
+ void visualizer_print( gzFile visualizer_file ) const;
+ void print_stat( FILE *fp ) { m_dram->print_stat(fp); }
+ void visualize() const { m_dram->visualize(); }
+ void print( FILE *fp ) const;
+
+ class memory_sub_partition * get_sub_partition(int sub_partition_id)
+ {
+ return m_sub_partition[sub_partition_id];
+ }
+
+ // Power model
+ void set_dram_power_stats(unsigned &n_cmd,
+ unsigned &n_activity,
+ unsigned &n_nop,
+ unsigned &n_act,
+ unsigned &n_pre,
+ unsigned &n_rd,
+ unsigned &n_wr,
+ unsigned &n_req) const;
+
+ int global_sub_partition_id_to_local_id(int global_sub_partition_id) const;
+
+ unsigned get_mpid() const { return m_id; }
+
+private:
+
+ unsigned m_id;
+ const struct memory_config *m_config;
+ class memory_stats_t *m_stats;
+ class memory_sub_partition **m_sub_partition;
+ class dram_t *m_dram;
+
+ class arbitration_metadata
+ {
+ public:
+ arbitration_metadata(const struct memory_config *config);
+
+ // check if a subpartition still has credit
+ bool has_credits(int inner_sub_partition_id) const;
+ // borrow a credit for a subpartition
+ void borrow_credit(int inner_sub_partition_id);
+ // return a credit from a subpartition
+ void return_credit(int inner_sub_partition_id);
+
+ // return the last subpartition that borrowed credit
+ int last_borrower() const { return m_last_borrower; }
+
+ void print( FILE *fp ) const;
+ private:
+ // id of the last subpartition that borrowed credit
+ int m_last_borrower;
+
+ int m_shared_credit_limit;
+ int m_private_credit_limit;
+
+ // credits borrowed by the subpartitions
+ std::vector<int> m_private_credit;
+ int m_shared_credit;
+ };
+ arbitration_metadata m_arbitration_metadata;
+
+ // determine wheither a given subpartition can issue to DRAM
+ bool can_issue_to_dram(int inner_sub_partition_id);
+
+ // model DRAM access scheduler latency (fixed latency between L2 and DRAM)
+ struct dram_delay_t
+ {
+ unsigned long long ready_cycle;
+ class mem_fetch* req;
+ };
+ std::queue<dram_delay_t> m_dram_latency_queue;
+};
+
+class memory_sub_partition
+{
+public:
+ memory_sub_partition( unsigned sub_partition_id, const struct memory_config *config, class memory_stats_t *stats );
+ ~memory_sub_partition();
+
+ unsigned get_id() const { return m_id; }
+
+ bool busy() const;
+
+ void cache_cycle( unsigned cycle );
+
bool full() const;
void push( class mem_fetch* mf, unsigned long long clock_cycle );
class mem_fetch* pop();
@@ -71,31 +161,26 @@ public:
unsigned flushL2();
+ // interface to L2_dram_queue
+ bool L2_dram_queue_empty() const;
+ class mem_fetch* L2_dram_queue_top() const;
+ void L2_dram_queue_pop();
+
+ // interface to dram_L2_queue
+ bool dram_L2_queue_full() const;
+ void dram_L2_queue_push( class mem_fetch* mf );
+
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(); }
void print( FILE *fp ) const;
-
- // Power model
- void set_dram_power_stats(unsigned &n_cmd,
- unsigned &n_activity,
- unsigned &n_nop,
- unsigned &n_act,
- unsigned &n_pre,
- unsigned &n_rd,
- unsigned &n_wr,
- unsigned &n_req) const;
-
void accumulate_L2cache_stats(class cache_stats &l2_stats) const;
void get_L2cache_sub_stats(struct cache_sub_stats &css) const;
private:
// data
- unsigned m_id;
+ unsigned m_id; //< the global sub partition ID
const struct memory_config *m_config;
- class dram_t *m_dram;
class l2_cache *m_L2cache;
class L2interface *m_L2interface;
partition_mf_allocator *m_mf_allocator;
@@ -108,14 +193,6 @@ private:
};
std::queue<rop_delay_t> m_rop;
- // model DRAM access scheduler latency (fixed latency between L2 and DRAM)
- struct dram_delay_t
- {
- unsigned long long ready_cycle;
- class mem_fetch* req;
- };
- std::queue<dram_delay_t> m_dram_latency_queue;
-
// these are various FIFOs between units within a memory partition
fifo_pipeline<mem_fetch> *m_icnt_L2_queue;
fifo_pipeline<mem_fetch> *m_L2_dram_queue;
@@ -134,7 +211,7 @@ private:
class L2interface : public mem_fetch_interface {
public:
- L2interface( memory_partition_unit *unit ) { m_unit=unit; }
+ L2interface( memory_sub_partition *unit ) { m_unit=unit; }
virtual ~L2interface() {}
virtual bool full( unsigned size, bool write) const
{
@@ -147,7 +224,7 @@ public:
m_unit->m_L2_dram_queue->push(mf);
}
private:
- memory_partition_unit *m_unit;
+ memory_sub_partition *m_unit;
};
#endif
diff --git a/src/gpgpu-sim/l2cache_trace.h b/src/gpgpu-sim/l2cache_trace.h
new file mode 100644
index 0000000..3dac87d
--- /dev/null
+++ b/src/gpgpu-sim/l2cache_trace.h
@@ -0,0 +1,55 @@
+// Copyright (c) 2009-2011, Tor M. Aamodt, Tim Rogers, Wilson W. L. Fung
+// The University of British Columbia
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+// Redistributions in binary form must reproduce the above copyright notice, this
+// list of conditions and the following disclaimer in the documentation and/or
+// other materials provided with the distribution.
+// Neither the name of The University of British Columbia nor the names of its
+// contributors may be used to endorse or promote products derived from this
+// software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#pragma once
+
+#include "../trace.h"
+
+#if TRACING_ON
+
+#define MEMPART_PRINT_STR SIM_PRINT_STR " %d - "
+#define MEMPART_DTRACE(x) ( DTRACE(x) && (Trace::sampling_memory_partition == -1 || Trace::sampling_memory_partition == (int)get_mpid()) )
+
+// Intended to be called from inside components of a memory partition
+// Depends on a get_mpid() function
+#define MEMPART_DPRINTF(...) do {\
+ if (MEMPART_DTRACE(MEMORY_PARTITION_UNIT)) {\
+ printf( MEMPART_PRINT_STR,\
+ gpu_sim_cycle + gpu_tot_sim_cycle,\
+ Trace::trace_streams_str[Trace::MEMORY_PARTITION_UNIT],\
+ get_mpid() );\
+ printf(__VA_ARGS__);\
+ }\
+} while (0)
+
+#else
+
+#define MEMPART_DTRACE(x) (false)
+#define MEMPART_DPRINTF(x, ...) do {} while (0)
+
+#endif
+
diff --git a/src/gpgpu-sim/mem_fetch.h b/src/gpgpu-sim/mem_fetch.h
index c4ba0dc..f788c2b 100644
--- a/src/gpgpu-sim/mem_fetch.h
+++ b/src/gpgpu-sim/mem_fetch.h
@@ -83,6 +83,7 @@ public:
void set_addr(new_addr_type addr) { m_access.set_addr(addr); }
new_addr_type get_addr() const { return m_access.get_addr(); }
new_addr_type get_partition_addr() const { return m_partition_addr; }
+ unsigned get_sub_partition_id() const { return m_raw_addr.sub_partition; }
bool get_is_write() const { return m_access.is_write(); }
unsigned get_request_uid() const { return m_request_uid; }
unsigned get_sid() const { return m_sid; }
diff --git a/src/gpgpu-sim/shader.cc b/src/gpgpu-sim/shader.cc
index 87e59ed..73a8a62 100644
--- a/src/gpgpu-sim/shader.cc
+++ b/src/gpgpu-sim/shader.cc
@@ -3184,7 +3184,7 @@ void simt_core_cluster::icnt_inject_request_packet(class mem_fetch *mf)
packet_size = mf->get_ctrl_size();
}
m_stats->m_outgoing_traffic_stats->record_traffic(mf, packet_size);
- unsigned destination = mf->get_tlx_addr().chip;
+ unsigned destination = mf->get_sub_partition_id();
mf->set_status(IN_ICNT_TO_MEM,gpu_sim_cycle+gpu_tot_sim_cycle);
if (!mf->get_is_write() && !mf->isatomic())
::icnt_push(m_cluster_id, m_config->mem2device(destination), (void*)mf, mf->get_ctrl_size() );
diff --git a/src/trace.cc b/src/trace.cc
index 05b9d6b..5171e46 100644
--- a/src/trace.cc
+++ b/src/trace.cc
@@ -41,6 +41,7 @@ namespace Trace {
bool enabled = false;
int sampling_core = 0;
+ int sampling_memory_partition = -1;
bool trace_streams_enabled[NUM_TRACE_STREAMS] = {false};
const char* config_str;
diff --git a/src/trace.h b/src/trace.h
index c7b389e..a79b4a0 100644
--- a/src/trace.h
+++ b/src/trace.h
@@ -46,6 +46,7 @@ namespace Trace {
extern bool enabled;
extern int sampling_core;
+ extern int sampling_memory_partition;
extern const char* trace_streams_str[];
extern bool trace_streams_enabled[NUM_TRACE_STREAMS];
extern const char* config_str;
diff --git a/src/trace_streams.tup b/src/trace_streams.tup
index fa6fd1e..c41690e 100644
--- a/src/trace_streams.tup
+++ b/src/trace_streams.tup
@@ -28,5 +28,6 @@
TS_TUP_BEGIN( trace_streams_type )
TS_TUP( WARP_SCHEDULER ),
TS_TUP( SCOREBOARD ),
+ TS_TUP( MEMORY_PARTITION_UNIT ),
TS_TUP( NUM_TRACE_STREAMS )
TS_TUP_END( trace_streams_type )