diff options
Diffstat (limited to 'src/gpgpu-sim/shader.h')
| -rw-r--r-- | src/gpgpu-sim/shader.h | 129 |
1 files changed, 118 insertions, 11 deletions
diff --git a/src/gpgpu-sim/shader.h b/src/gpgpu-sim/shader.h index 31008ec..d8103ac 100644 --- a/src/gpgpu-sim/shader.h +++ b/src/gpgpu-sim/shader.h @@ -223,27 +223,102 @@ class shd_warp_t { assert(slot < IBUFFER_SIZE); m_ibuffer[slot].m_inst = pI; m_ibuffer[slot].m_valid = true; - m_next = 0; + m_ibuffer[slot].m_split_id = (unsigned)-1; + m_ibuffer[slot].m_split_mask.reset(); + if (slot < IBUFFER_HALF_SIZE) m_next = 0; // only reset for primary half + } + void ibuffer_fill(unsigned slot, const warp_inst_t *pI, unsigned split_id, + const active_mask_t &split_mask) { + assert(slot < IBUFFER_SIZE); + m_ibuffer[slot].m_inst = pI; + m_ibuffer[slot].m_valid = true; + m_ibuffer[slot].m_split_id = split_id; + m_ibuffer[slot].m_split_mask = split_mask; + if (slot < IBUFFER_HALF_SIZE) m_next = 0; // only reset for primary half } bool ibuffer_empty() const { for (unsigned i = 0; i < IBUFFER_SIZE; i++) if (m_ibuffer[i].m_valid) return false; return true; } + bool ibuffer_half_empty(unsigned half) const { + unsigned start = half * IBUFFER_HALF_SIZE; + for (unsigned i = start; i < start + IBUFFER_HALF_SIZE; i++) + if (m_ibuffer[i].m_valid) return false; + return true; + } + bool ibuffer_any_half_empty() const { + return ibuffer_half_empty(0) || ibuffer_half_empty(1); + } void ibuffer_flush() { for (unsigned i = 0; i < IBUFFER_SIZE; i++) { + if (m_ibuffer[i].m_valid) { + dec_inst_in_pipeline(); + } + m_ibuffer[i].m_inst = NULL; + m_ibuffer[i].m_valid = false; + m_ibuffer[i].m_split_id = (unsigned)-1; + } + for (unsigned h = 0; h < IBUFFER_NUM_HALVES; h++) + m_ibuffer_halves[h].m_assigned = false; + } + void ibuffer_flush_half(unsigned half) { + unsigned start = half * IBUFFER_HALF_SIZE; + for (unsigned i = start; i < start + IBUFFER_HALF_SIZE; i++) { if (m_ibuffer[i].m_valid) dec_inst_in_pipeline(); m_ibuffer[i].m_inst = NULL; m_ibuffer[i].m_valid = false; + m_ibuffer[i].m_split_id = (unsigned)-1; } + m_ibuffer_halves[half].m_assigned = false; } const warp_inst_t *ibuffer_next_inst() { return m_ibuffer[m_next].m_inst; } bool ibuffer_next_valid() { return m_ibuffer[m_next].m_valid; } + unsigned ibuffer_next_split_id() const { + return m_ibuffer[m_next].m_split_id; + } + const active_mask_t &ibuffer_next_split_mask() const { + return m_ibuffer[m_next].m_split_mask; + } void ibuffer_free() { m_ibuffer[m_next].m_inst = NULL; m_ibuffer[m_next].m_valid = false; } - void ibuffer_step() { m_next = (m_next + 1) % IBUFFER_SIZE; } + void ibuffer_step() { m_next = (m_next + 1) % IBUFFER_HALF_SIZE; } + unsigned get_ibuffer_next() const { return m_next; } + // Direct slot access for co-issue pass + bool ibuffer_slot_valid(unsigned slot) const { + return m_ibuffer[slot].m_valid; + } + const warp_inst_t *ibuffer_slot_inst(unsigned slot) const { + return m_ibuffer[slot].m_inst; + } + unsigned ibuffer_slot_split_id(unsigned slot) const { + return m_ibuffer[slot].m_split_id; + } + const active_mask_t &ibuffer_slot_split_mask(unsigned slot) const { + return m_ibuffer[slot].m_split_mask; + } + void ibuffer_free_slot(unsigned slot) { + m_ibuffer[slot].m_inst = NULL; + m_ibuffer[slot].m_valid = false; + } + // Half assignment tracking + void ibuffer_assign_half(unsigned half, unsigned split_id, + const active_mask_t &mask) { + m_ibuffer_halves[half].m_assigned_split_id = split_id; + m_ibuffer_halves[half].m_assigned_mask = mask; + m_ibuffer_halves[half].m_assigned = true; + } + bool ibuffer_half_assigned(unsigned half) const { + return m_ibuffer_halves[half].m_assigned; + } + unsigned ibuffer_half_split_id(unsigned half) const { + return m_ibuffer_halves[half].m_assigned_split_id; + } + const active_mask_t &ibuffer_half_mask(unsigned half) const { + return m_ibuffer_halves[half].m_assigned_mask; + } bool imiss_pending() const { return m_imiss_pending; } void set_imiss_pending() { m_imiss_pending = true; } @@ -285,7 +360,9 @@ class shd_warp_t { } private: - static const unsigned IBUFFER_SIZE = 2; + static const unsigned IBUFFER_SIZE = 4; + static const unsigned IBUFFER_HALF_SIZE = 2; + static const unsigned IBUFFER_NUM_HALVES = 2; class shader_core_ctx *m_shader; unsigned long long m_streamID; unsigned m_cta_id; @@ -303,13 +380,24 @@ class shd_warp_t { ibuffer_entry() { m_valid = false; m_inst = NULL; + m_split_id = (unsigned)-1; } const warp_inst_t *m_inst; bool m_valid; + unsigned m_split_id; // splits table entry this belongs to + active_mask_t m_split_mask; // the split's active mask at decode time + }; + + struct ibuffer_half_t { + ibuffer_half_t() : m_assigned(false), m_assigned_split_id((unsigned)-1) {} + bool m_assigned; + unsigned m_assigned_split_id; + active_mask_t m_assigned_mask; }; warp_inst_t m_inst_at_barrier; ibuffer_entry m_ibuffer[IBUFFER_SIZE]; + ibuffer_half_t m_ibuffer_halves[IBUFFER_NUM_HALVES]; unsigned m_next; unsigned m_n_atomic; // number of outstanding atomic operations @@ -1150,19 +1238,27 @@ struct insn_latency_info { }; struct ifetch_buffer_t { - ifetch_buffer_t() { m_valid = false; } + ifetch_buffer_t() : m_valid(false), m_ibuffer_half(0), + m_split_id((unsigned)-1) { m_split_mask.reset(); } - ifetch_buffer_t(address_type pc, unsigned nbytes, unsigned warp_id) { - m_valid = true; - m_pc = pc; - m_nbytes = nbytes; - m_warp_id = warp_id; - } + ifetch_buffer_t(address_type pc, unsigned nbytes, unsigned warp_id) + : m_valid(true), m_pc(pc), m_nbytes(nbytes), m_warp_id(warp_id), + m_ibuffer_half(0), m_split_id((unsigned)-1) { m_split_mask.reset(); } + + ifetch_buffer_t(address_type pc, unsigned nbytes, unsigned warp_id, + unsigned ibuffer_half, unsigned split_id, + const active_mask_t &split_mask) + : m_valid(true), m_pc(pc), m_nbytes(nbytes), m_warp_id(warp_id), + m_ibuffer_half(ibuffer_half), m_split_id(split_id), + m_split_mask(split_mask) {} bool m_valid; address_type m_pc; unsigned m_nbytes; unsigned m_warp_id; + unsigned m_ibuffer_half; // which I-Buffer half to fill (0 or 1) + unsigned m_split_id; // splits table entry + active_mask_t m_split_mask; // the split's active mask }; class shader_core_config; @@ -2501,6 +2597,15 @@ class shader_core_ctx : public core_t { bool pending_reconvergence(unsigned wid); bool warp_blocked(unsigned wid); bool warp_valid(unsigned wid); + // SIMD lane partitioning: secondary split access + bool has_secondary_split(unsigned wid); + bool get_secondary_split_info(unsigned wid, unsigned *pc, unsigned *rpc, + unsigned *split_id, simt_mask_t *mask); + bool is_split_valid(unsigned wid, unsigned split_id); + void get_split_info(unsigned wid, unsigned split_id, unsigned *pc, + simt_mask_t *mask); + bool move_split_to_front(unsigned wid, unsigned split_id); + simt_tables *get_simt_tables(unsigned wid) { return m_simt_tables[wid]; } bool push_to_st_response_fifo(unsigned wid, unsigned entry); bool push_to_rt_response_fifo(unsigned wid, unsigned entry); void update_st_size(unsigned n); @@ -2538,7 +2643,8 @@ class shader_core_ctx : public core_t { unsigned warp_id, unsigned sch_id); void co_issue_warp(warp_inst_t *composite, const warp_inst_t *next_inst, const active_mask_t &active_mask, unsigned warp_id, - unsigned sch_id, unsigned start_set = 0); + unsigned sch_id, unsigned start_set = 0, + unsigned split_id = (unsigned)-1); void create_front_pipeline(); void create_schedulers(); @@ -2621,6 +2727,7 @@ class shader_core_ctx : public core_t { std::vector<shd_warp_t *> m_warp; // per warp information array barrier_set_t m_barriers; ifetch_buffer_t m_inst_fetch_buffer; + ifetch_buffer_t m_inst_fetch_buffer_secondary; // for secondary split std::vector<register_set> m_pipeline_reg; Scoreboard *m_scoreboard; opndcoll_rfu_t m_operand_collector; |
