summaryrefslogtreecommitdiff
path: root/src/gpgpu-sim/l2cache.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/gpgpu-sim/l2cache.cc')
-rw-r--r--src/gpgpu-sim/l2cache.cc164
1 files changed, 141 insertions, 23 deletions
diff --git a/src/gpgpu-sim/l2cache.cc b/src/gpgpu-sim/l2cache.cc
index c5fc44e..25da107 100644
--- a/src/gpgpu-sim/l2cache.cc
+++ b/src/gpgpu-sim/l2cache.cc
@@ -74,6 +74,15 @@ memory_partition_unit::memory_partition_unit( unsigned partition_id,
}
}
+void memory_partition_unit::handle_memcpy_to_gpu( size_t addr, unsigned global_subpart_id, mem_access_sector_mask_t mask )
+{
+ unsigned p = global_sub_partition_id_to_local_id(global_subpart_id);
+ std::string mystring =
+ mask.to_string<char,std::string::traits_type,std::string::allocator_type>();
+ MEMPART_DPRINTF("Copy Engine Request Received For Address=%llx, local_subpart=%u, global_subpart=%u, sector_mask=%s \n", addr, p, global_subpart_id, mystring.c_str());
+ m_sub_partition[p]->force_l2_tag_update(addr,gpu_sim_cycle+gpu_tot_sim_cycle, mask);
+}
+
memory_partition_unit::~memory_partition_unit()
{
delete m_dram;
@@ -93,7 +102,9 @@ memory_partition_unit::arbitration_metadata::arbitration_metadata(const struct m
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);
+ - (config->m_n_sub_partition_per_memory_channel - 1);
+ if(config->seperate_write_queue_enabled )
+ m_shared_credit_limit += config->gpgpu_frfcfs_dram_write_queue_size;
if (config->gpgpu_frfcfs_dram_sched_queue_size == 0
or config->gpgpu_dram_return_queue_size == 0)
{
@@ -220,7 +231,8 @@ void memory_partition_unit::dram_cycle()
m_dram->cycle();
m_dram->dram_log(SAMPLELOG);
- if( !m_dram->full() ) {
+ // mem_fetch *mf = m_sub_partition[spid]->L2_dram_queue_top();
+ //if( !m_dram->full(mf->is_write()) ) {
// L2->DRAM queue to DRAM latency queue
// Arbitrate among multiple L2 subpartitions
int last_issued_partition = m_arbitration_metadata.last_borrower();
@@ -228,6 +240,9 @@ void memory_partition_unit::dram_cycle()
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();
+ if(m_dram->full(mf->is_write()) )
+ break;
+
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;
@@ -239,12 +254,13 @@ void memory_partition_unit::dram_cycle()
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_front();
+
+ if( !m_dram_latency_queue.empty() && ( (gpu_sim_cycle+gpu_tot_sim_cycle) >= m_dram_latency_queue.front().ready_cycle ) && !m_dram->full(m_dram_latency_queue.front().req->is_write()) ) {
+ mem_fetch* mf = m_dram_latency_queue.front().req;
+ m_dram_latency_queue.pop_front();
m_dram->push(mf);
}
}
@@ -299,6 +315,7 @@ memory_sub_partition::memory_sub_partition( unsigned sub_partition_id,
m_id = sub_partition_id;
m_config=config;
m_stats=stats;
+ m_memcpy_cycle_offset = 0;
assert(m_id < m_config->m_n_mem_sub_partition);
@@ -343,6 +360,14 @@ void memory_sub_partition::cache_cycle( unsigned cycle )
mf->set_status(IN_PARTITION_L2_TO_ICNT_QUEUE,gpu_sim_cycle+gpu_tot_sim_cycle);
m_L2_icnt_queue->push(mf);
}else{
+ if(m_config->m_L2_config.m_write_alloc_policy == FETCH_ON_WRITE)
+ {
+ mem_fetch* original_wr_mf = mf->get_original_wr_mf();
+ assert(original_wr_mf);
+ original_wr_mf->set_reply();
+ original_wr_mf->set_status(IN_PARTITION_L2_TO_ICNT_QUEUE,gpu_sim_cycle+gpu_tot_sim_cycle);
+ m_L2_icnt_queue->push(original_wr_mf);
+ }
m_request_tracker.erase(mf);
delete mf;
}
@@ -355,10 +380,11 @@ void memory_sub_partition::cache_cycle( unsigned cycle )
if ( !m_config->m_L2_config.disabled() && m_L2cache->waiting_for_fill(mf) ) {
if (m_L2cache->fill_port_free()) {
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_L2cache->fill(mf,gpu_sim_cycle+gpu_tot_sim_cycle+m_memcpy_cycle_offset);
m_dram_L2_queue->pop();
}
} else if ( !m_L2_icnt_queue->full() ) {
+ if(mf->is_write() && mf->get_type() == WRITE_ACK)
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();
@@ -380,9 +406,10 @@ void memory_sub_partition::cache_cycle( unsigned cycle )
bool port_free = m_L2cache->data_port_free();
if ( !output_full && port_free ) {
std::list<cache_event> events;
- enum cache_request_status status = m_L2cache->access(mf->get_addr(),mf,gpu_sim_cycle+gpu_tot_sim_cycle,events);
+ enum cache_request_status status = m_L2cache->access(mf->get_addr(),mf,gpu_sim_cycle+gpu_tot_sim_cycle+m_memcpy_cycle_offset,events);
bool write_sent = was_write_sent(events);
bool read_sent = was_read_sent(events);
+ MEM_SUBPART_DPRINTF("Probing L2 cache Address=%llx, status=%u\n", mf->get_addr(), status);
if ( status == HIT ) {
if( !write_sent ) {
@@ -402,6 +429,11 @@ void memory_sub_partition::cache_cycle( unsigned cycle )
m_icnt_L2_queue->pop();
}
} else if ( status != RESERVATION_FAIL ) {
+ if(mf->is_write() && (m_config->m_L2_config.m_write_alloc_policy == FETCH_ON_WRITE || m_config->m_L2_config.m_write_alloc_policy == LAZY_FETCH_ON_READ) && !was_writeallocate_sent(events)) {
+ mf->set_reply();
+ mf->set_status(IN_PARTITION_L2_TO_ICNT_QUEUE,gpu_sim_cycle+gpu_tot_sim_cycle);
+ m_L2_icnt_queue->push(mf);
+ }
// L2 cache accepted request
m_icnt_L2_queue->pop();
} else {
@@ -432,6 +464,11 @@ bool memory_sub_partition::full() const
return m_icnt_L2_queue->full();
}
+bool memory_sub_partition::full(unsigned size) const
+{
+ return m_icnt_L2_queue->is_avilable_size(size);
+}
+
bool memory_sub_partition::L2_dram_queue_empty() const
{
return m_L2_dram_queue->empty();
@@ -532,7 +569,15 @@ unsigned memory_sub_partition::flushL2()
if (!m_config->m_L2_config.disabled()) {
m_L2cache->flush();
}
- return 0; // L2 is read only in this version
+ return 0; //TODO: write the flushed data to the main memory
+}
+
+unsigned memory_sub_partition::invalidateL2()
+{
+ if (!m_config->m_L2_config.disabled()) {
+ m_L2cache->invalidate();
+ }
+ return 0;
}
bool memory_sub_partition::busy() const
@@ -540,21 +585,94 @@ bool memory_sub_partition::busy() const
return !m_request_tracker.empty();
}
-void memory_sub_partition::push( mem_fetch* req, unsigned long long cycle )
+std::vector<mem_fetch*> memory_sub_partition::breakdown_request_to_sector_requests(mem_fetch* mf)
{
- if (req) {
- m_request_tracker.insert(req);
- m_stats->memlatstat_icnt2mem_pop(req);
- if( req->istexture() ) {
- m_icnt_L2_queue->push(req);
- req->set_status(IN_PARTITION_ICNT_TO_L2_QUEUE,gpu_sim_cycle+gpu_tot_sim_cycle);
- } else {
- rop_delay_t r;
- r.req = req;
- r.ready_cycle = cycle + m_config->rop_latency;
- m_rop.push(r);
- req->set_status(IN_PARTITION_ROP_DELAY,gpu_sim_cycle+gpu_tot_sim_cycle);
- }
+ std::vector<mem_fetch*> result;
+
+ if(mf->get_data_size() == SECTOR_SIZE && mf->get_access_sector_mask().count() == 1) {
+ result.push_back(mf);
+ } else if (mf->get_data_size() == 128 || mf->get_data_size() == 64) {
+ //We only accept 32, 64 and 128 bytes reqs
+ unsigned start=0, end=0;
+ if(mf->get_data_size() == 128) {
+ start=0; end=3;
+ } else if (mf->get_data_size() == 64 && mf->get_access_sector_mask().to_string() == "1100") {
+ start=2; end=3;
+ } else if (mf->get_data_size() == 64 && mf->get_access_sector_mask().to_string() == "0011") {
+ start=0; end=1;
+ } else if (mf->get_data_size() == 64 && (mf->get_access_sector_mask().to_string() == "1111" || mf->get_access_sector_mask().to_string() == "0000")) {
+ if(mf->get_addr() % 128 == 0) {
+ start=0; end=1;
+ } else {
+ start=2; end=3;
+ }
+ } else
+ {
+ printf("Invalid sector received, address = 0x%06x, sector mask = %s, data size = %d",
+ mf->get_addr(), mf->get_access_sector_mask(), mf->get_data_size());
+ assert(0 && "Undefined sector mask is received");
+ }
+
+ std::bitset<SECTOR_SIZE*SECTOR_CHUNCK_SIZE> byte_sector_mask;
+ byte_sector_mask.reset();
+ for(unsigned k=start*SECTOR_SIZE; k< SECTOR_SIZE; ++k)
+ byte_sector_mask.set(k);
+
+ for(unsigned j=start, i=0; j<= end ; ++j, ++i){
+
+ const mem_access_t *ma = new mem_access_t( mf->get_access_type(),
+ mf->get_addr() + SECTOR_SIZE*i,
+ SECTOR_SIZE,
+ mf->is_write(),
+ mf->get_access_warp_mask(),
+ mf->get_access_byte_mask() & byte_sector_mask,
+ std::bitset<SECTOR_CHUNCK_SIZE>().set(j));
+
+ mem_fetch *n_mf = new mem_fetch( *ma,
+ NULL,
+ mf->get_ctrl_size(),
+ mf->get_wid(),
+ mf->get_sid(),
+ mf->get_tpc(),
+ mf->get_mem_config(),
+ mf);
+
+ result.push_back(n_mf);
+ byte_sector_mask <<= SECTOR_SIZE;
+ }
+ } else {
+ printf("Invalid sector received, address = 0x%06x, sector mask = %d, byte mask = , data size = %d",
+ mf->get_addr(), mf->get_access_sector_mask().count(), mf->get_data_size());
+ assert(0 && "Undefined data size is received");
+ }
+
+ return result;
+}
+
+void memory_sub_partition::push( mem_fetch* m_req, unsigned long long cycle )
+{
+ if (m_req) {
+ m_stats->memlatstat_icnt2mem_pop(m_req);
+ std::vector<mem_fetch*> reqs;
+ if(m_config->m_L2_config.m_cache_type == SECTOR)
+ reqs = breakdown_request_to_sector_requests(m_req);
+ else
+ reqs.push_back(m_req);
+
+ for(unsigned i=0; i<reqs.size(); ++i) {
+ mem_fetch* req = reqs[i];
+ m_request_tracker.insert(req);
+ if( req->istexture() ) {
+ m_icnt_L2_queue->push(req);
+ req->set_status(IN_PARTITION_ICNT_TO_L2_QUEUE,gpu_sim_cycle+gpu_tot_sim_cycle);
+ } else {
+ rop_delay_t r;
+ r.req = req;
+ r.ready_cycle = cycle + m_config->rop_latency;
+ m_rop.push(r);
+ req->set_status(IN_PARTITION_ROP_DELAY,gpu_sim_cycle+gpu_tot_sim_cycle);
+ }
+ }
}
}