summaryrefslogtreecommitdiff
path: root/src/gpgpu-sim/shader.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/gpgpu-sim/shader.cc')
-rw-r--r--src/gpgpu-sim/shader.cc362
1 files changed, 250 insertions, 112 deletions
diff --git a/src/gpgpu-sim/shader.cc b/src/gpgpu-sim/shader.cc
index c6e7b8f..bcfda18 100644
--- a/src/gpgpu-sim/shader.cc
+++ b/src/gpgpu-sim/shader.cc
@@ -61,6 +61,20 @@ mem_fetch *shader_core_mem_fetch_allocator::alloc(
m_core_id, m_cluster_id, m_memory_config, cycle);
return mf;
}
+
+mem_fetch *shader_core_mem_fetch_allocator::alloc(
+ new_addr_type addr, mem_access_type type, const active_mask_t &active_mask,
+ const mem_access_byte_mask_t &byte_mask,
+ const mem_access_sector_mask_t &sector_mask, unsigned size, bool wr,
+ unsigned long long cycle, unsigned wid, unsigned sid, unsigned tpc,
+ mem_fetch *original_mf) const {
+ mem_access_t access(type, addr, size, wr, active_mask, byte_mask, sector_mask,
+ m_memory_config->gpgpu_ctx);
+ mem_fetch *mf = new mem_fetch(
+ access, NULL, wr ? WRITE_PACKET_SIZE : READ_PACKET_SIZE, wid, m_core_id,
+ m_cluster_id, m_memory_config, cycle, original_mf);
+ return mf;
+}
/////////////////////////////////////////////////////////////////////////////
std::list<unsigned> shader_core_ctx::get_regs_written(const inst_t &fvt) const {
@@ -108,7 +122,7 @@ void shader_core_ctx::create_front_pipeline() {
if (m_config->sub_core_model) {
// in subcore model, each scheduler should has its own issue register, so
- // num scheduler = reg width
+ // ensure num scheduler = reg width
assert(m_config->gpgpu_num_sched_per_core ==
m_pipeline_reg[ID_OC_SP].get_size());
assert(m_config->gpgpu_num_sched_per_core ==
@@ -124,6 +138,11 @@ void shader_core_ctx::create_front_pipeline() {
if (m_config->gpgpu_num_int_units > 0)
assert(m_config->gpgpu_num_sched_per_core ==
m_pipeline_reg[ID_OC_INT].get_size());
+ for (int j = 0; j < m_config->m_specialized_unit.size(); j++) {
+ if (m_config->m_specialized_unit[j].num_units > 0)
+ assert(m_config->gpgpu_num_sched_per_core ==
+ m_config->m_specialized_unit[j].id_oc_spec_reg_width);
+ }
}
m_threadState = (thread_ctx_t *)calloc(sizeof(thread_ctx_t),
@@ -172,6 +191,8 @@ void shader_core_ctx::create_schedulers() {
? CONCRETE_SCHEDULER_TWO_LEVEL_ACTIVE
: sched_config.find("gto") != std::string::npos
? CONCRETE_SCHEDULER_GTO
+ : sched_config.find("rrr") != std::string::npos
+ ? CONCRETE_SCHEDULER_RRR
: sched_config.find("old") != std::string::npos
? CONCRETE_SCHEDULER_OLDEST_FIRST
: sched_config.find("warp_limiting") !=
@@ -206,6 +227,14 @@ void shader_core_ctx::create_schedulers() {
&m_pipeline_reg[ID_OC_TENSOR_CORE], m_specilized_dispatch_reg,
&m_pipeline_reg[ID_OC_MEM], i));
break;
+ case CONCRETE_SCHEDULER_RRR:
+ schedulers.push_back(new rrr_scheduler(
+ m_stats, this, m_scoreboard, m_simt_stack, &m_warp,
+ &m_pipeline_reg[ID_OC_SP], &m_pipeline_reg[ID_OC_DP],
+ &m_pipeline_reg[ID_OC_SFU], &m_pipeline_reg[ID_OC_INT],
+ &m_pipeline_reg[ID_OC_TENSOR_CORE], m_specilized_dispatch_reg,
+ &m_pipeline_reg[ID_OC_MEM], i));
+ break;
case CONCRETE_SCHEDULER_OLDEST_FIRST:
schedulers.push_back(new oldest_scheduler(
m_stats, this, m_scoreboard, m_simt_stack, &m_warp,
@@ -377,41 +406,41 @@ void shader_core_ctx::create_exec_pipeline() {
// m_fu = new simd_function_unit*[m_num_function_units];
- for (int k = 0; k < m_config->gpgpu_num_sp_units; k++) {
- m_fu.push_back(new sp_unit(&m_pipeline_reg[EX_WB], m_config, this));
+ for (unsigned k = 0; k < m_config->gpgpu_num_sp_units; k++) {
+ m_fu.push_back(new sp_unit(&m_pipeline_reg[EX_WB], m_config, this, k));
m_dispatch_port.push_back(ID_OC_SP);
m_issue_port.push_back(OC_EX_SP);
}
- for (int k = 0; k < m_config->gpgpu_num_dp_units; k++) {
- m_fu.push_back(new dp_unit(&m_pipeline_reg[EX_WB], m_config, this));
+ for (unsigned k = 0; k < m_config->gpgpu_num_dp_units; k++) {
+ m_fu.push_back(new dp_unit(&m_pipeline_reg[EX_WB], m_config, this, k));
m_dispatch_port.push_back(ID_OC_DP);
m_issue_port.push_back(OC_EX_DP);
}
- for (int k = 0; k < m_config->gpgpu_num_int_units; k++) {
- m_fu.push_back(new int_unit(&m_pipeline_reg[EX_WB], m_config, this));
+ for (unsigned k = 0; k < m_config->gpgpu_num_int_units; k++) {
+ m_fu.push_back(new int_unit(&m_pipeline_reg[EX_WB], m_config, this, k));
m_dispatch_port.push_back(ID_OC_INT);
m_issue_port.push_back(OC_EX_INT);
}
- for (int k = 0; k < m_config->gpgpu_num_sfu_units; k++) {
- m_fu.push_back(new sfu(&m_pipeline_reg[EX_WB], m_config, this));
+ for (unsigned k = 0; k < m_config->gpgpu_num_sfu_units; k++) {
+ m_fu.push_back(new sfu(&m_pipeline_reg[EX_WB], m_config, this, k));
m_dispatch_port.push_back(ID_OC_SFU);
m_issue_port.push_back(OC_EX_SFU);
}
- for (int k = 0; k < m_config->gpgpu_num_tensor_core_units; k++) {
- m_fu.push_back(new tensor_core(&m_pipeline_reg[EX_WB], m_config, this));
+ for (unsigned k = 0; k < m_config->gpgpu_num_tensor_core_units; k++) {
+ m_fu.push_back(new tensor_core(&m_pipeline_reg[EX_WB], m_config, this, k));
m_dispatch_port.push_back(ID_OC_TENSOR_CORE);
m_issue_port.push_back(OC_EX_TENSOR_CORE);
}
- for (int j = 0; j < m_config->m_specialized_unit.size(); j++) {
+ for (unsigned j = 0; j < m_config->m_specialized_unit.size(); j++) {
for (unsigned k = 0; k < m_config->m_specialized_unit[j].num_units; k++) {
m_fu.push_back(new specialized_unit(
&m_pipeline_reg[EX_WB], m_config, this, SPEC_UNIT_START_ID + j,
m_config->m_specialized_unit[j].name,
- m_config->m_specialized_unit[j].latency));
+ m_config->m_specialized_unit[j].latency, k));
m_dispatch_port.push_back(m_config->m_specialized_unit[j].ID_OC_SPEC_ID);
m_issue_port.push_back(m_config->m_specialized_unit[j].OC_EX_SPEC_ID);
}
@@ -1082,6 +1111,33 @@ void scheduler_unit::order_lrr(
}
}
+template <class T>
+void scheduler_unit::order_rrr(
+ std::vector<T> &result_list, const typename std::vector<T> &input_list,
+ const typename std::vector<T>::const_iterator &last_issued_from_input,
+ unsigned num_warps_to_add) {
+ result_list.clear();
+
+ if (m_num_issued_last_cycle > 0 || warp(m_current_turn_warp).done_exit() ||
+ warp(m_current_turn_warp).waiting()) {
+ std::vector<shd_warp_t *>::const_iterator iter =
+ (last_issued_from_input == input_list.end()) ?
+ input_list.begin() : last_issued_from_input + 1;
+ for (unsigned count = 0; count < num_warps_to_add; ++iter, ++count) {
+ if (iter == input_list.end()) {
+ iter = input_list.begin();
+ }
+ unsigned warp_id = (*iter)->get_warp_id();
+ if (!(*iter)->done_exit() && !(*iter)->waiting()) {
+ result_list.push_back(*iter);
+ m_current_turn_warp = warp_id;
+ break;
+ }
+ }
+ } else {
+ result_list.push_back(&warp(m_current_turn_warp));
+ }
+}
/**
* A general function to order things in an priority-based way.
* The core usage of the function is similar to order_lrr.
@@ -1228,29 +1284,21 @@ void scheduler_unit::cycle() {
previous_issued_inst_exec_type = exec_unit_type_t::MEM;
}
} else {
- bool sp_pipe_avail =
- (m_shader->m_config->gpgpu_num_sp_units > 0) &&
- m_sp_out->has_free(m_shader->m_config->sub_core_model, m_id);
- bool sfu_pipe_avail =
- (m_shader->m_config->gpgpu_num_sfu_units > 0) &&
- m_sfu_out->has_free(m_shader->m_config->sub_core_model, m_id);
- bool tensor_core_pipe_avail =
- (m_shader->m_config->gpgpu_num_tensor_core_units > 0) &&
- m_tensor_core_out->has_free(
- m_shader->m_config->sub_core_model, m_id);
- bool dp_pipe_avail =
- (m_shader->m_config->gpgpu_num_dp_units > 0) &&
- m_dp_out->has_free(m_shader->m_config->sub_core_model, m_id);
- bool int_pipe_avail =
- (m_shader->m_config->gpgpu_num_int_units > 0) &&
- m_int_out->has_free(m_shader->m_config->sub_core_model, m_id);
-
// This code need to be refactored
if (pI->op != TENSOR_CORE_OP && pI->op != SFU_OP &&
pI->op != DP_OP && !(pI->op >= SPEC_UNIT_START_ID)) {
bool execute_on_SP = false;
bool execute_on_INT = false;
+ bool sp_pipe_avail =
+ (m_shader->m_config->gpgpu_num_sp_units > 0) &&
+ m_sp_out->has_free(m_shader->m_config->sub_core_model,
+ m_id);
+ bool int_pipe_avail =
+ (m_shader->m_config->gpgpu_num_int_units > 0) &&
+ m_int_out->has_free(m_shader->m_config->sub_core_model,
+ m_id);
+
// if INT unit pipline exist, then execute ALU and INT
// operations on INT unit and SP-FPU on SP unit (like in Volta)
// if INT unit pipline does not exist, then execute all ALU, INT
@@ -1311,6 +1359,11 @@ void scheduler_unit::cycle() {
(pI->op == DP_OP) &&
!(diff_exec_units && previous_issued_inst_exec_type ==
exec_unit_type_t::DP)) {
+ bool dp_pipe_avail =
+ (m_shader->m_config->gpgpu_num_dp_units > 0) &&
+ m_dp_out->has_free(m_shader->m_config->sub_core_model,
+ m_id);
+
if (dp_pipe_avail) {
m_shader->issue_warp(*m_dp_out, pI, active_mask, warp_id,
m_id);
@@ -1326,6 +1379,11 @@ void scheduler_unit::cycle() {
(pI->op == SFU_OP) || (pI->op == ALU_SFU_OP)) &&
!(diff_exec_units && previous_issued_inst_exec_type ==
exec_unit_type_t::SFU)) {
+ bool sfu_pipe_avail =
+ (m_shader->m_config->gpgpu_num_sfu_units > 0) &&
+ m_sfu_out->has_free(m_shader->m_config->sub_core_model,
+ m_id);
+
if (sfu_pipe_avail) {
m_shader->issue_warp(*m_sfu_out, pI, active_mask, warp_id,
m_id);
@@ -1337,6 +1395,11 @@ void scheduler_unit::cycle() {
} else if ((pI->op == TENSOR_CORE_OP) &&
!(diff_exec_units && previous_issued_inst_exec_type ==
exec_unit_type_t::TENSOR)) {
+ bool tensor_core_pipe_avail =
+ (m_shader->m_config->gpgpu_num_tensor_core_units > 0) &&
+ m_tensor_core_out->has_free(
+ m_shader->m_config->sub_core_model, m_id);
+
if (tensor_core_pipe_avail) {
m_shader->issue_warp(*m_tensor_core_out, pI, active_mask,
warp_id, m_id);
@@ -1407,7 +1470,7 @@ void scheduler_unit::cycle() {
m_last_supervised_issued = supervised_iter;
}
}
-
+ m_num_issued_last_cycle = issued;
if (issued == 1)
m_stats->single_issue_nums[m_id]++;
else if (issued > 1)
@@ -1456,6 +1519,10 @@ void lrr_scheduler::order_warps() {
order_lrr(m_next_cycle_prioritized_warps, m_supervised_warps,
m_last_supervised_issued, m_supervised_warps.size());
}
+void rrr_scheduler::order_warps() {
+ order_rrr(m_next_cycle_prioritized_warps, m_supervised_warps,
+ m_last_supervised_issued, m_supervised_warps.size());
+}
void gto_scheduler::order_warps() {
order_by_priority(m_next_cycle_prioritized_warps, m_supervised_warps,
@@ -1569,7 +1636,10 @@ void swl_scheduler::order_warps() {
}
}
-void shader_core_ctx::read_operands() {}
+void shader_core_ctx::read_operands() {
+ for (int i = 0; i < m_config->reg_file_port_throughput; ++i)
+ m_operand_collector.step();
+}
address_type coalesced_segment(address_type addr,
unsigned segment_size_lg2bytes) {
@@ -1669,8 +1739,15 @@ void shader_core_ctx::execute() {
m_fu[n]->active_lanes_in_pipeline();
unsigned issue_port = m_issue_port[n];
register_set &issue_inst = m_pipeline_reg[issue_port];
- warp_inst_t **ready_reg = issue_inst.get_ready();
- if (issue_inst.has_ready() && m_fu[n]->can_issue(**ready_reg)) {
+ unsigned reg_id;
+ bool partition_issue =
+ m_config->sub_core_model && m_fu[n]->is_issue_partitioned();
+ if (partition_issue) {
+ reg_id = m_fu[n]->get_issue_reg_id();
+ }
+ warp_inst_t **ready_reg = issue_inst.get_ready(partition_issue, reg_id);
+ if (issue_inst.has_ready(partition_issue, reg_id) &&
+ m_fu[n]->can_issue(**ready_reg)) {
bool schedule_wb_now = !m_fu[n]->stallable();
int resbus = -1;
if (schedule_wb_now &&
@@ -1970,6 +2047,21 @@ void ldst_unit::L1_latency_queue_cycle() {
} else {
assert(status == MISS || status == HIT_RESERVED);
l1_latency_queue[j][0] = NULL;
+ if (m_config->m_L1D_config.get_write_policy() != WRITE_THROUGH &&
+ mf_next->get_inst().is_store() &&
+ (m_config->m_L1D_config.get_write_allocate_policy() ==
+ FETCH_ON_WRITE ||
+ m_config->m_L1D_config.get_write_allocate_policy() ==
+ LAZY_FETCH_ON_READ) &&
+ !was_writeallocate_sent(events)) {
+ unsigned dec_ack =
+ (m_config->m_L1D_config.get_mshr_type() == SECTOR_ASSOC)
+ ? (mf_next->get_data_size() / SECTOR_SIZE)
+ : 1;
+ mf_next->set_reply();
+ for (unsigned i = 0; i < dec_ack; ++i) m_core->store_ack(mf_next);
+ if (!write_sent && !read_sent) delete mf_next;
+ }
}
}
@@ -2112,22 +2204,32 @@ simd_function_unit::simd_function_unit(const shader_core_config *config) {
m_dispatch_reg = new warp_inst_t(config);
}
+void simd_function_unit::issue(register_set &source_reg) {
+ bool partition_issue =
+ m_config->sub_core_model && this->is_issue_partitioned();
+ source_reg.move_out_to(partition_issue, this->get_issue_reg_id(),
+ m_dispatch_reg);
+ occupied.set(m_dispatch_reg->latency);
+}
+
sfu::sfu(register_set *result_port, const shader_core_config *config,
- shader_core_ctx *core)
- : pipelined_simd_unit(result_port, config, config->max_sfu_latency, core) {
+ shader_core_ctx *core, unsigned issue_reg_id)
+ : pipelined_simd_unit(result_port, config, config->max_sfu_latency, core,
+ issue_reg_id) {
m_name = "SFU";
}
tensor_core::tensor_core(register_set *result_port,
const shader_core_config *config,
- shader_core_ctx *core)
+ shader_core_ctx *core, unsigned issue_reg_id)
: pipelined_simd_unit(result_port, config, config->max_tensor_core_latency,
- core) {
+ core, issue_reg_id) {
m_name = "TENSOR_CORE";
}
void sfu::issue(register_set &source_reg) {
- warp_inst_t **ready_reg = source_reg.get_ready();
+ warp_inst_t **ready_reg =
+ source_reg.get_ready(m_config->sub_core_model, m_issue_reg_id);
// m_core->incexecstat((*ready_reg));
(*ready_reg)->op_pipe = SFU__OP;
@@ -2136,7 +2238,8 @@ void sfu::issue(register_set &source_reg) {
}
void tensor_core::issue(register_set &source_reg) {
- warp_inst_t **ready_reg = source_reg.get_ready();
+ warp_inst_t **ready_reg =
+ source_reg.get_ready(m_config->sub_core_model, m_issue_reg_id);
// m_core->incexecstat((*ready_reg));
(*ready_reg)->op_pipe = TENSOR_CORE__OP;
@@ -2208,34 +2311,39 @@ void tensor_core::active_lanes_in_pipeline() {
}
sp_unit::sp_unit(register_set *result_port, const shader_core_config *config,
- shader_core_ctx *core)
- : pipelined_simd_unit(result_port, config, config->max_sp_latency, core) {
+ shader_core_ctx *core, unsigned issue_reg_id)
+ : pipelined_simd_unit(result_port, config, config->max_sp_latency, core,
+ issue_reg_id) {
m_name = "SP ";
}
specialized_unit::specialized_unit(register_set *result_port,
const shader_core_config *config,
shader_core_ctx *core, unsigned supported_op,
- char *unit_name, unsigned latency)
- : pipelined_simd_unit(result_port, config, latency, core) {
+ char *unit_name, unsigned latency,
+ unsigned issue_reg_id)
+ : pipelined_simd_unit(result_port, config, latency, core, issue_reg_id) {
m_name = unit_name;
m_supported_op = supported_op;
}
dp_unit::dp_unit(register_set *result_port, const shader_core_config *config,
- shader_core_ctx *core)
- : pipelined_simd_unit(result_port, config, config->max_dp_latency, core) {
+ shader_core_ctx *core, unsigned issue_reg_id)
+ : pipelined_simd_unit(result_port, config, config->max_dp_latency, core,
+ issue_reg_id) {
m_name = "DP ";
}
int_unit::int_unit(register_set *result_port, const shader_core_config *config,
- shader_core_ctx *core)
- : pipelined_simd_unit(result_port, config, config->max_int_latency, core) {
+ shader_core_ctx *core, unsigned issue_reg_id)
+ : pipelined_simd_unit(result_port, config, config->max_int_latency, core,
+ issue_reg_id) {
m_name = "INT ";
}
void sp_unit ::issue(register_set &source_reg) {
- warp_inst_t **ready_reg = source_reg.get_ready();
+ warp_inst_t **ready_reg =
+ source_reg.get_ready(m_config->sub_core_model, m_issue_reg_id);
// m_core->incexecstat((*ready_reg));
(*ready_reg)->op_pipe = SP__OP;
m_core->incsp_stat(m_core->get_config()->warp_size, (*ready_reg)->latency);
@@ -2243,7 +2351,8 @@ void sp_unit ::issue(register_set &source_reg) {
}
void dp_unit ::issue(register_set &source_reg) {
- warp_inst_t **ready_reg = source_reg.get_ready();
+ warp_inst_t **ready_reg =
+ source_reg.get_ready(m_config->sub_core_model, m_issue_reg_id);
// m_core->incexecstat((*ready_reg));
(*ready_reg)->op_pipe = DP__OP;
m_core->incsp_stat(m_core->get_config()->warp_size, (*ready_reg)->latency);
@@ -2251,7 +2360,8 @@ void dp_unit ::issue(register_set &source_reg) {
}
void specialized_unit ::issue(register_set &source_reg) {
- warp_inst_t **ready_reg = source_reg.get_ready();
+ warp_inst_t **ready_reg =
+ source_reg.get_ready(m_config->sub_core_model, m_issue_reg_id);
// m_core->incexecstat((*ready_reg));
(*ready_reg)->op_pipe = SPECIALIZED__OP;
m_core->incsp_stat(m_core->get_config()->warp_size, (*ready_reg)->latency);
@@ -2259,7 +2369,8 @@ void specialized_unit ::issue(register_set &source_reg) {
}
void int_unit ::issue(register_set &source_reg) {
- warp_inst_t **ready_reg = source_reg.get_ready();
+ warp_inst_t **ready_reg =
+ source_reg.get_ready(m_config->sub_core_model, m_issue_reg_id);
// m_core->incexecstat((*ready_reg));
(*ready_reg)->op_pipe = INTP__OP;
m_core->incsp_stat(m_core->get_config()->warp_size, (*ready_reg)->latency);
@@ -2269,7 +2380,8 @@ void int_unit ::issue(register_set &source_reg) {
pipelined_simd_unit::pipelined_simd_unit(register_set *result_port,
const shader_core_config *config,
unsigned max_latency,
- shader_core_ctx *core)
+ shader_core_ctx *core,
+ unsigned issue_reg_id)
: simd_function_unit(config) {
m_result_port = result_port;
m_pipeline_depth = max_latency;
@@ -2277,6 +2389,7 @@ pipelined_simd_unit::pipelined_simd_unit(register_set *result_port,
for (unsigned i = 0; i < m_pipeline_depth; i++)
m_pipeline_reg[i] = new warp_inst_t(config);
m_core = core;
+ m_issue_reg_id = issue_reg_id;
active_insts_in_pipeline = 0;
}
@@ -2303,7 +2416,10 @@ void pipelined_simd_unit::cycle() {
void pipelined_simd_unit::issue(register_set &source_reg) {
// move_warp(m_dispatch_reg,source_reg);
- warp_inst_t **ready_reg = source_reg.get_ready();
+ bool partition_issue =
+ m_config->sub_core_model && this->is_issue_partitioned();
+ warp_inst_t **ready_reg =
+ source_reg.get_ready(partition_issue, m_issue_reg_id);
m_core->incexecstat((*ready_reg));
// source_reg.move_out_to(m_dispatch_reg);
simd_function_unit::issue(source_reg);
@@ -2360,7 +2476,7 @@ ldst_unit::ldst_unit(mem_fetch_interface *icnt,
Scoreboard *scoreboard, const shader_core_config *config,
const memory_config *mem_config, shader_core_stats *stats,
unsigned sid, unsigned tpc)
- : pipelined_simd_unit(NULL, config, config->smem_latency, core),
+ : pipelined_simd_unit(NULL, config, config->smem_latency, core, 0),
m_next_wb(config) {
assert(config->smem_latency > 1);
init(icnt, mf_allocator, core, operand_collector, scoreboard, config,
@@ -2388,7 +2504,7 @@ ldst_unit::ldst_unit(mem_fetch_interface *icnt,
Scoreboard *scoreboard, const shader_core_config *config,
const memory_config *mem_config, shader_core_stats *stats,
unsigned sid, unsigned tpc, l1_cache *new_l1d_cache)
- : pipelined_simd_unit(NULL, config, 3, core),
+ : pipelined_simd_unit(NULL, config, 3, core, 0),
m_L1D(new_l1d_cache),
m_next_wb(config) {
init(icnt, mf_allocator, core, operand_collector, scoreboard, config,
@@ -2550,8 +2666,7 @@ inst->space.get_type() != shared_space) { unsigned warp_id = inst->warp_id();
*/
void ldst_unit::cycle() {
writeback();
- for (int i = 0; i < m_config->reg_file_port_throughput; ++i)
- m_operand_collector->step();
+
for (unsigned stage = 0; (stage + 1) < m_pipeline_depth; stage++)
if (m_pipeline_reg[stage]->empty() && !m_pipeline_reg[stage + 1]->empty())
move_warp(m_pipeline_reg[stage], m_pipeline_reg[stage + 1]);
@@ -3264,49 +3379,46 @@ unsigned int shader_core_config::max_cta(const kernel_info_t &k) const {
if (adaptive_cache_config && !k.cache_config_set) {
// For more info about adaptive cache, see
// https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#shared-memory-7-x
- unsigned total_shmed = kernel_info->smem * result;
- assert(total_shmed >= 0 && total_shmed <= gpgpu_shmem_size);
- // assert(gpgpu_shmem_size == 98304); //Volta has 96 KB shared
- // assert(m_L1D_config.get_nset() == 4); //Volta L1 has four sets
- if (total_shmed < gpgpu_shmem_size) {
- switch (adaptive_cache_config) {
- case FIXED:
- break;
- case ADAPTIVE_VOLTA: {
- // For Volta, we assign the remaining shared memory to L1 cache
- // For more info about adaptive cache, see
- // https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#shared-memory-7-x
- // assert(gpgpu_shmem_size == 98304); //Volta has 96 KB shared
+ unsigned total_shmem = kernel_info->smem * result;
+ assert(total_shmem >= 0 && total_shmem <= shmem_opt_list.back());
- // To Do: make it flexible and not tuned to 9KB share memory
- unsigned max_assoc = m_L1D_config.get_max_assoc();
- if (total_shmed == 0)
- m_L1D_config.set_assoc(max_assoc); // L1 is 128KB and shd=0
- else if (total_shmed > 0 && total_shmed <= 8192)
- m_L1D_config.set_assoc(0.9375 *
- max_assoc); // L1 is 120KB and shd=8KB
- else if (total_shmed > 8192 && total_shmed <= 16384)
- m_L1D_config.set_assoc(0.875 *
- max_assoc); // L1 is 112KB and shd=16KB
- else if (total_shmed > 16384 && total_shmed <= 32768)
- m_L1D_config.set_assoc(0.75 * max_assoc); // L1 is 96KB and
- // shd=32KB
- else if (total_shmed > 32768 && total_shmed <= 65536)
- m_L1D_config.set_assoc(0.5 * max_assoc); // L1 is 64KB and shd=64KB
- else if (total_shmed > 65536 && total_shmed <= gpgpu_shmem_size)
- m_L1D_config.set_assoc(0.25 * max_assoc); // L1 is 32KB and
- // shd=96KB
- else
- assert(0);
- break;
- }
- default:
- assert(0);
+ // Unified cache config is in KB. Converting to B
+ unsigned total_unified = m_L1D_config.m_unified_cache_size * 1024;
+
+ bool l1d_configured = false;
+ unsigned max_assoc = m_L1D_config.get_max_assoc();
+
+ for (std::vector<unsigned>::const_iterator it = shmem_opt_list.begin();
+ it < shmem_opt_list.end(); it++) {
+ if (total_shmem <= *it) {
+ float l1_ratio = 1 - ((float)*(it) / total_unified);
+ // make sure the ratio is between 0 and 1
+ assert(0 <= l1_ratio && l1_ratio <= 1);
+ // round to nearest instead of round down
+ m_L1D_config.set_assoc(max_assoc * l1_ratio + 0.5f);
+ l1d_configured = true;
+ break;
}
+ }
- printf("GPGPU-Sim: Reconfigure L1 cache to %uKB\n",
- m_L1D_config.get_total_size_inKB());
+ assert(l1d_configured && "no shared memory option found");
+
+ if (m_L1D_config.is_streaming()) {
+ // for streaming cache, if the whole memory is allocated
+ // to the L1 cache, then make the allocation to be on_MISS
+ // otherwise, make it ON_FILL to eliminate line allocation fails
+ // i.e. MSHR throughput is the same, independent on the L1 cache
+ // size/associativity
+ if (total_shmem == 0) {
+ m_L1D_config.set_allocation_policy(ON_MISS);
+ printf("GPGPU-Sim: Reconfigure L1 allocation to ON_MISS\n");
+ } else {
+ m_L1D_config.set_allocation_policy(ON_FILL);
+ printf("GPGPU-Sim: Reconfigure L1 allocation to ON_FILL\n");
+ }
}
+ printf("GPGPU-Sim: Reconfigure L1 cache to %uKB\n",
+ m_L1D_config.get_total_size_inKB());
k.cache_config_set = true;
}
@@ -3867,15 +3979,26 @@ void opndcoll_rfu_t::init(unsigned num_banks, shader_core_ctx *shader) {
assert((m_bank_warp_shift == 5) || (m_warp_size != 32));
sub_core_model = shader->get_config()->sub_core_model;
- m_num_warp_sceds = shader->get_config()->gpgpu_num_sched_per_core;
- if (sub_core_model)
+ m_num_warp_scheds = shader->get_config()->gpgpu_num_sched_per_core;
+ unsigned reg_id;
+ if (sub_core_model) {
assert(num_banks % shader->get_config()->gpgpu_num_sched_per_core == 0);
+ assert(m_num_warp_scheds <= m_cu.size() &&
+ m_cu.size() % m_num_warp_scheds == 0);
+ }
m_num_banks_per_sched =
num_banks / shader->get_config()->gpgpu_num_sched_per_core;
for (unsigned j = 0; j < m_cu.size(); j++) {
+ if (sub_core_model) {
+ unsigned cusPerSched = m_cu.size() / m_num_warp_scheds;
+ reg_id = j / cusPerSched;
+ }
m_cu[j]->init(j, num_banks, m_bank_warp_shift, shader->get_config(), this,
- sub_core_model, m_num_banks_per_sched);
+ sub_core_model, reg_id, m_num_banks_per_sched);
+ }
+ for (unsigned j = 0; j < m_dispatch_units.size(); j++) {
+ m_dispatch_units[j].init(sub_core_model,m_num_warp_scheds);
}
m_initialized = true;
}
@@ -3974,7 +4097,22 @@ void opndcoll_rfu_t::allocate_cu(unsigned port_num) {
for (unsigned j = 0; j < inp.m_cu_sets.size(); j++) {
std::vector<collector_unit_t> &cu_set = m_cus[inp.m_cu_sets[j]];
bool allocated = false;
- for (unsigned k = 0; k < cu_set.size(); k++) {
+ unsigned cuLowerBound = 0;
+ unsigned cuUpperBound = cu_set.size();
+ unsigned schd_id;
+ if (sub_core_model) {
+ // Sub core model only allocates on the subset of CUs assigned to the
+ // scheduler that issued
+ unsigned reg_id = (*inp.m_in[i]).get_ready_reg_id();
+ schd_id = (*inp.m_in[i]).get_schd_id(reg_id);
+ assert(cu_set.size() % m_num_warp_scheds == 0 &&
+ cu_set.size() >= m_num_warp_scheds);
+ unsigned cusPerSched = cu_set.size() / m_num_warp_scheds;
+ cuLowerBound = schd_id * cusPerSched;
+ cuUpperBound = cuLowerBound + cusPerSched;
+ assert(0 <= cuLowerBound && cuUpperBound <= cu_set.size());
+ }
+ for (unsigned k = cuLowerBound; k < cuUpperBound; k++) {
if (cu_set[k].is_free()) {
collector_unit_t *cu = &cu_set[k];
allocated = cu->allocate(inp.m_in[i], inp.m_out[i]);
@@ -3984,8 +4122,9 @@ void opndcoll_rfu_t::allocate_cu(unsigned port_num) {
}
if (allocated) break; // cu has been allocated, no need to search more.
}
- break; // can only service a single input, if it failed it will fail for
- // others.
+ // break; // can only service a single input, if it failed it will fail
+ // for
+ // others.
}
}
}
@@ -4032,7 +4171,8 @@ void opndcoll_rfu_t::allocate_reads() {
}
bool opndcoll_rfu_t::collector_unit_t::ready() const {
- return (!m_free) && m_not_ready.none() && (*m_output_register).has_free();
+ return (!m_free) && m_not_ready.none() &&
+ (*m_output_register).has_free(m_sub_core_model, m_reg_id);
}
void opndcoll_rfu_t::collector_unit_t::dump(
@@ -4050,12 +4190,10 @@ void opndcoll_rfu_t::collector_unit_t::dump(
}
}
-void opndcoll_rfu_t::collector_unit_t::init(unsigned n, unsigned num_banks,
- unsigned log2_warp_size,
- const core_config *config,
- opndcoll_rfu_t *rfu,
- bool sub_core_model,
- unsigned banks_per_sched) {
+void opndcoll_rfu_t::collector_unit_t::init(
+ unsigned n, unsigned num_banks, unsigned log2_warp_size,
+ const core_config *config, opndcoll_rfu_t *rfu, bool sub_core_model,
+ unsigned reg_id, unsigned banks_per_sched) {
m_rfu = rfu;
m_cuid = n;
m_num_banks = num_banks;
@@ -4063,6 +4201,7 @@ void opndcoll_rfu_t::collector_unit_t::init(unsigned n, unsigned num_banks,
m_warp = new warp_inst_t(config);
m_bank_warp_shift = log2_warp_size;
m_sub_core_model = sub_core_model;
+ m_reg_id = reg_id;
m_num_banks_per_sched = banks_per_sched;
}
@@ -4097,8 +4236,7 @@ bool opndcoll_rfu_t::collector_unit_t::allocate(register_set *pipeline_reg_set,
void opndcoll_rfu_t::collector_unit_t::dispatch() {
assert(m_not_ready.none());
- // move_warp(*m_output_register,m_warp);
- m_output_register->move_in(m_warp);
+ m_output_register->move_in(m_sub_core_model, m_reg_id, m_warp);
m_free = true;
m_output_register = NULL;
for (unsigned i = 0; i < MAX_REG_OPERANDS * 2; i++) m_src_op[i].reset();