Beispiel #1
0
        public void recv_req(Req req)
        {
            //stats
            Stat.procs[pid].read_req_served.Collect();
            Stat.procs[pid].read_avg_latency.Collect(req.latency);

            //free up instruction window and mshr
            inst_wnd.set_ready(req.block_addr);
            mshr.RemoveAll(x => x == req.block_addr);

            //writeback
            Req wb_req = req.wb_req;

            if (wb_req != null)
            {
                bool wb_merge = wb_q.Exists(x => x.block_addr == wb_req.block_addr);
                if (!wb_merge)
                {
                    wb_q.Add(wb_req);
                }
                else
                {
                    RequestPool.enpool(wb_req);
                }
            }

            //destory req
            RequestPool.enpool(req);
            out_read_req--;
        }
Beispiel #2
0
        public void service_cache_queue()
        {
            while (cache_hit_queue.Count != 0)
            {
                if (pid == Sim.highest_rank_proc)
                {
                    high_priority_total_hit_latency++;
                }
                total_hit_latency++;
                Req first_request = cache_hit_queue.First.Value;
                if ((ulong)first_request.ts_departure <= cycles)
                {
                    if (!l1_cache.has_addr(first_request.block_addr, ReqType.RD))
                    {
                        l1_cache.cache_add(first_request.block_addr, first_request.type, (ulong)pid);
                    }

                    cache_hit_queue.RemoveFirst();
                    RequestPool.enpool(first_request);
                    mshr.RemoveAll(x => x.block_addr == first_request.block_addr);
                    inst_wnd.set_ready(first_request.block_addr);
                }
                else
                {
                    return;
                }
            }
        }
Beispiel #3
0
        public void recv_wb_req(Req req)
        {
            //stats
            Stat.procs[pid].write_req_served.Collect();
            Stat.procs[pid].write_avg_latency.Collect(req.latency);

            //destroy req
            RequestPool.enpool(req);
        }
Beispiel #4
0
        public void service_mem_queue()
        {
            while (mem_queue.Count != 0)
            {
                Req first_request = mem_queue.First.Value;
                if ((ulong)first_request.ts_departure <= cycles)
                {
                    Stat.procs[pid].read_req_served.Collect();
                    Stat.procs[pid].read_avg_latency.Collect(first_request.latency);
                    ulong wb_addr = Proc.NULL_ADDRESS;

                    if (!cache.has_addr(first_request.block_addr, first_request.proc_req_type))
                    {
                        wb_addr = cache.cache_add(first_request.block_addr, first_request.proc_req_type, (ulong)pid);
                        if (!l1_cache.has_addr(first_request.block_addr, first_request.type))
                        {
                            l1_cache.cache_add(first_request.block_addr, first_request.type, (ulong)pid);
                        }
                        l1_cache.cache_remove(wb_addr, ReqType.RD);
                    }
                    if (Config.proc.wb == false)
                    {
                        wb_addr = Proc.NULL_ADDRESS;
                    }
                    if (wb_addr != Proc.NULL_ADDRESS)
                    {
                        Req wb_req = RequestPool.depool();
                        wb_req.set(pid, ReqType.WR, ReqType.NULL, wb_addr);
                        bool wb_merge = wb_q.Exists(x => x.block_addr == wb_req.block_addr);
                        if (!wb_merge)
                        {
                            wb_q.Add(wb_req);
                        }
                        else
                        {
                            RequestPool.enpool(wb_req);
                        }
                    }
//
                    mem_queue.RemoveFirst();
                    RequestPool.enpool(first_request);
                    inst_wnd.set_ready(first_request.block_addr);
                }
                else
                {
                    return;
                }
            }
        }
Beispiel #5
0
        public void recv_req(Req req)
        {
            //stats
            Stat.procs[pid].read_req_served.Collect();
            Stat.procs[pid].read_avg_latency.Collect(req.latency);
            total_read_latency += (ulong)req.latency;

            Req   first_request = req;
            ulong wb_addr       = Proc.NULL_ADDRESS;

            //free up instruction window and mshr
            inst_wnd.set_ready(req.block_addr);
            mshr.RemoveAll(x => x == req.block_addr);

            if (!cache.has_addr(first_request.block_addr, ReqType.RD))
            {
                wb_addr = cache.cache_add(first_request.block_addr, first_request.proc_req_type, (ulong)pid);
                if (!l1_cache.has_addr(first_request.block_addr, first_request.type))
                {
                    l1_cache.cache_add(first_request.block_addr, first_request.proc_req_type, (ulong)pid);
                }
                l1_cache.cache_remove(wb_addr, ReqType.RD);
            }

            //add to cache; returns the address of evicted block; returns null if empty block has been populated
            //if there is an evicted block, writeback; another memory request is generated
            if (Config.proc.wb == false)
            {
                wb_addr = Proc.NULL_ADDRESS;
            }
            if (wb_addr != Proc.NULL_ADDRESS)
            {
                Req wb_req = RequestPool.depool();
                wb_req.set(pid, ReqType.WR, ReqType.NULL, wb_addr);
                bool wb_merge = wb_q.Exists(x => x.block_addr == wb_req.block_addr);
                if (!wb_merge)
                {
                    wb_q.Add(wb_req);
                }
                else
                {
                    RequestPool.enpool(wb_req);
                }
            }

            //destory req
            RequestPool.enpool(req);
            out_read_req--;
        }
Beispiel #6
0
        public void service_cache_queue()
        {
            while (cache_hit_queue.Count != 0)
            {
                Req first_request = cache_hit_queue.First.Value;
                if ((ulong)first_request.ts_departure <= cycles)
                {
                    if (!l1_cache.has_addr(first_request.block_addr, ReqType.RD))
                    {
                        l1_cache.cache_add(first_request.block_addr, first_request.type, (ulong)pid);
                    }


                    cache_hit_queue.RemoveFirst();
                    RequestPool.enpool(first_request);
                    inst_wnd.set_ready(first_request.block_addr);
                }
                else
                {
                    return;
                }
            }
        }
Beispiel #7
0
        public void issue_insts(bool issued_rd_req)
        {
            //issue instructions
            for (int i = 0; i < Config.proc.ipc; i++)
            {
                if (inst_wnd.is_full())
                {
                    if (i == 0)
                    {
                        Stat.procs[pid].stall_inst_wnd.Collect();
                    }
                    return;
                }

                //cpu instructions
                if (curr_cpu_inst_cnt > 0)
                {
                    curr_cpu_inst_cnt--;
                    inst_wnd.add(0, false, true, 0);
                    continue;
                }

                //only one memory instruction can be issued per cycle
                if (issued_rd_req)
                {
                    return;
                }

                //check if true miss
                bool false_miss = inst_wnd.is_duplicate(curr_rd_req.block_addr);
                if (false_miss)
                {
                    bool get_ready     = inst_wnd.get_ready_status(curr_rd_req.block_addr);
                    bool get_alone_hit = inst_wnd.get_alone_hit_status(curr_rd_req.block_addr);
                    inst_wnd.add(curr_rd_req.block_addr, true, get_ready, get_alone_hit, curr_rd_req.pc);
                    Dbg.Assert(curr_rd_req.wb_req == null);
                    RequestPool.enpool(curr_rd_req);
                    curr_rd_req = get_req();
                    continue;
                }

                if (!Config.is_cache_filtered)
                {
                    bool is_in_l1_cache = false;
                    is_in_l1_cache = l1_cache.has_addr(curr_rd_req.block_addr, curr_rd_req.proc_req_type);
                    if (is_in_l1_cache)
                    {
                        if (pid == Sim.highest_rank_proc)
                        {
                            Sim.cache_controller.count_l1_hits(pid, true);
                        }
                        Sim.cache_controller.count_l1_hits(pid, false);
                        Stat.procs[pid].l1_cache_hit_count.Collect();
                        inst_wnd.add(curr_rd_req.block_addr, true, true, true, curr_rd_req.pc);
                        RequestPool.enpool(curr_rd_req);
                        curr_rd_req = get_req();
                        continue;
                    }
                    bool mshr_ok = insert_mshr(curr_rd_req);
                    if (!mshr_ok)
                    {
                        mshr_retry = true;
                        return;
                    }
                    Stat.procs[pid].l1_cache_miss_count.Collect();
                    if (pid == Sim.highest_rank_proc)
                    {
                        Sim.cache_controller.count_l1_misses(pid, true);
                    }
                    Sim.cache_controller.count_l1_misses(pid, false);
                }

                is_in_cache  = false;
                is_alone_hit = false;

                if (!Config.is_cache_filtered)
                {
                    int way_sampled_set = cache.has_addr_sampled_set(curr_rd_req.block_addr, curr_rd_req.proc_req_type);
                    is_in_cache = cache.has_addr(curr_rd_req.block_addr, curr_rd_req.proc_req_type);
                    //Count high-priority and non-high-priority hits and misses in the sampled sets
                    if (!is_in_cache)
                    {
                        Sim.cache_controller.count_misses(pid, way_sampled_set, false);
                    }
                    if (!is_in_cache && (pid == Sim.highest_rank_proc))
                    {
                        Sim.cache_controller.count_misses(pid, way_sampled_set, true);
                    }
                    if (is_in_cache && (pid == Sim.highest_rank_proc))
                    {
                        Sim.cache_controller.count_current_hits(pid, way_sampled_set, true);
                    }
                    if (is_in_cache)
                    {
                        Sim.cache_controller.count_current_hits(pid, way_sampled_set, false);
                    }

                    //Count high-priority and non-high-priority hits and misses in all sets
                    if (!is_in_cache)
                    {
                        Sim.cache_controller.count_all_misses(pid, false);
                    }
                    if (!is_in_cache && (pid == Sim.highest_rank_proc))
                    {
                        Sim.cache_controller.count_all_misses(pid, true);
                    }
                    if (is_in_cache && (pid == Sim.highest_rank_proc))
                    {
                        Sim.cache_controller.count_all_hits(pid, true);
                    }
                    if (is_in_cache)
                    {
                        Sim.cache_controller.count_all_hits(pid, false);
                    }

                    if (Config.aux_cache)
                    {
                        way_sampled_set = aux_cache.has_addr_sampled_set(curr_rd_req.block_addr, curr_rd_req.proc_req_type);
                        is_alone_hit    = aux_cache.has_addr(curr_rd_req.block_addr, curr_rd_req.proc_req_type);
                        //count aux tag store hits in sampled sets
                        if (pid == Sim.highest_rank_proc)
                        {
                            Sim.cache_controller.count_aux_hits_alone(pid, way_sampled_set);
                        }
                        Sim.cache_controller.count_aux_hits(pid, way_sampled_set);
                    }
                    if (Config.fst)
                    {
                        if (Config.poll_filter)
                        {
                            is_alone_hit = pollution_vector.check_filter(curr_rd_req.block_addr);
                        }
                        else if (Config.aux_cache)
                        {
                            is_alone_hit = aux_cache.has_addr(curr_rd_req.block_addr, curr_rd_req.proc_req_type);
                        }
                    }
                }
                if (Config.fst)
                {
                    if (is_alone_hit)
                    {
                        curr_rd_req.alone_counter_tracker = (int)Config.mem_latency;
                        setting_counter++;
                        interference_bit = true;
                        if (Config.poll_filter)
                        {
                            interference_bit_core = pollution_vector.get_interfering_core(curr_rd_req.block_addr);
                        }
                        interference_bit_set_addr = curr_rd_req.block_addr;
                    }
                }
                if (is_alone_hit)
                {
                    curr_rd_req.is_alone_hit = true;
                }

//                if (Config.stride_prefetcher_on) stride_prefetcher.process_request(pid, curr_rd_req.block_addr, curr_rd_req.pc);

                //check if already in cache
                if (!Config.is_cache_filtered)
                {
                    if (is_in_cache)
                    {
                        Stat.procs[pid].l2_cache_hit_count.Collect();
                        add_to_cache_queue(curr_rd_req);
//                      RequestPool.enpool(curr_rd_req);
                        curr_rd_req = get_req();
                        continue;
                    }
                }

                if (Config.stride_prefetcher_on)
                {
                    stride_prefetcher.process_request(pid, curr_rd_req.block_addr, curr_rd_req.pc);
                }

                inst_wnd.add(curr_rd_req.block_addr, true, false, curr_rd_req.is_alone_hit, curr_rd_req.pc);

                if (Config.model_memory)
                {
                    //try memory controller
                    bool mctrl_ok = insert_mctrl(curr_rd_req);
                    if (!mctrl_ok)
                    {
                        mctrl_retry = true;
                        return;
                    }
                }
                else
                {
                    add_to_mem_queue(curr_rd_req);
                }
                Stat.procs[pid].l2_cache_miss_count.Collect();

                //issued memory request
                issued_rd_req = true;

                //get new read request
                curr_rd_req = get_req();
            }
        }
Beispiel #8
0
        public void recv_req(Req req)
        {
            //stats
            Stat.procs[pid].read_req_served.Collect();
            Stat.procs[pid].read_avg_latency.Collect(req.latency);
            total_read_latency += (ulong)req.latency;
            if (pid == Sim.highest_rank_proc)
            {
                high_priority_total_misses += 1;
            }


            inflight_mem_requests--;
            Req   first_request = req;
            ulong wb_addr       = Proc.NULL_ADDRESS;

            //free up instruction window and mshr
            inst_wnd.set_ready(req.block_addr);
            mshr.RemoveAll(x => x.block_addr == req.block_addr);
            if (Config.fst)
            {
                if ((req.block_addr == interference_bit_set_addr) && (interference_bit == true))
                {
                    interference_bit      = false;
                    interference_bit_core = Config.N;
                }
            }

            if (!cache.has_addr(first_request.block_addr, ReqType.RD))
            {
                wb_addr = cache.cache_add(first_request.block_addr, first_request.proc_req_type, (ulong)pid);
                if (!l1_cache.has_addr(first_request.block_addr, ReqType.RD) && !first_request.is_prefetch)
                {
                    l1_cache.cache_add(first_request.block_addr, first_request.proc_req_type, (ulong)pid);
                }
                l1_cache.cache_remove(wb_addr, ReqType.RD);
            }

            if (Config.aux_cache)
            {
                if (!aux_cache.has_addr(first_request.block_addr, ReqType.RD))
                {
                    aux_cache.cache_add(first_request.block_addr, first_request.proc_req_type, (ulong)pid);
                }
            }

            if (Config.proc.wb == false)
            {
                wb_addr = Proc.NULL_ADDRESS;
            }

            if (wb_addr != Proc.NULL_ADDRESS)
            {
                Req wb_req = RequestPool.depool();
                wb_req.set(pid, ReqType.WR, ReqType.NULL, wb_addr);
                bool wb_merge = wb_q.Exists(x => x.block_addr == wb_req.block_addr);
                if (!wb_merge)
                {
                    wb_q.Add(wb_req);
                }
                else
                {
                    RequestPool.enpool(wb_req);
                }
            }

            //destory req
            RequestPool.enpool(req);
            out_read_req--;
        }
Beispiel #9
0
        public void process_request(int pid, ulong block_addr, ulong input_pc)
        {
            if (!pc_present(input_pc))
            {
                StrideEntry new_stride_entry = new StrideEntry();
                new_stride_entry.block_addr = block_addr;
                new_stride_entry.trained    = false;
                new_stride_entry.stride     = 0;
                new_stride_entry.train_hits = 0;

                insert_entry(input_pc, new_stride_entry);
                return;
            }
            int hit_position   = entry_position(input_pc);
            int current_stride = (int)(block_addr - stride_entries[hit_position].block_addr);

            if (current_stride != stride_entries[hit_position].stride)
            {
                stride_entries[hit_position].stride     = current_stride;
                stride_entries[hit_position].trained    = false;
                stride_entries[hit_position].train_hits = 0;
            }

            stride_entries[hit_position].block_addr = block_addr;

            if (!stride_entries[hit_position].trained)
            {
                stride_entries[hit_position].train_hits++;
                stride_entries[hit_position].prefetch_block_addr = block_addr;
            }


            if (stride_entries[hit_position].train_hits >= num_trains)
            {
                stride_entries[hit_position].trained = true;
            }

            if (stride_entries[hit_position].stride == 0)
            {
                return;
            }

            if (stride_entries[hit_position].trained == true)
            {
                ulong max_block_address = stride_entries[hit_position].block_addr + (ulong)((distance + 1) * stride_entries[hit_position].stride);
                int   max_prefetches    = (int)(((int)max_block_address - (int)stride_entries[hit_position].prefetch_block_addr) / stride_entries[hit_position].stride);
                int   num_prefetches    = (max_prefetches > degree) ? degree : max_prefetches;


                for (int i = 0; i < num_prefetches; i++)
                {
                    stride_entries[hit_position].prefetch_block_addr += (ulong)stride_entries[hit_position].stride;
                    Req new_prefetch = create_new_prefetch_req(pid, stride_entries[hit_position].prefetch_block_addr);

                    bool mctrl_ok = insert_mctrl(new_prefetch);
                    if (!mctrl_ok)
                    {
                        RequestPool.enpool(new_prefetch);
                    }
                    else
                    {
                        Stat.procs[new_prefetch.pid].num_prefetches.Collect();
                    };
                }
            }

            return;
        }
        public void __dequeue_req(Req req)
        {
            req.ts_departure = cycles;
            Dbg.Assert(req.ts_departure - req.ts_arrival > 0);


            if (!req.migrated_request)
            {
                if (Config.proc.cache_insertion_policy == "PFA")
                {
                    RowStat.UpdateMLP(RowStat.NVMDict, req);
                    Measurement.mem_num_dec(req);
//                    Measurement.NVMServiceTimeUpdate (req);
//                    Measurement.NVMCoreReqNumDec (req);
                    Row_Migration_Policies.target     = true;
                    Row_Migration_Policies.target_req = req;
                }
                else if (Config.proc.cache_insertion_policy == "RBLA")
                {
                    Row_Migration_Policies.target     = true;
                    Row_Migration_Policies.target_req = req;
                }
            }
            if (Config.proc.cache_insertion_policy == "PFA")
            {
                Measurement.NVMCoreReqNumDec(req);
            }

/*            if (Config.proc.cache_insertion_policy == "PFA")
 *          {
 *                 Measurement.NVMSetCorePrevRowid (req);
 *          }
 */
            //sched
            meta_mctrl.dequeue_req(req);

            //load stat management
            if (!req.cache_wb)
            {
                if (req.type == ReqType.RD)
                {
                    rload--;
                    rload_per_proc[req.pid]--;
                    rload_per_procrankbank[req.pid, req.addr.rid, req.addr.bid]--;
                    Dbg.Assert(rload >= 0);
                    Dbg.Assert(rload_per_proc[req.pid] >= 0);
                    Dbg.Assert(rload_per_procrankbank[req.pid, req.addr.rid, req.addr.bid] >= 0);
                }
                else
                {
                    wload--;
                    wload_per_proc[req.pid]--;
                    wload_per_procrankbank[req.pid, req.addr.rid, req.addr.bid]--;
                    Dbg.Assert(wload >= 0);
                    Dbg.Assert(wload_per_proc[req.pid] >= 0);
                    Dbg.Assert(wload_per_procrankbank[req.pid, req.addr.rid, req.addr.bid] >= 0);
                }
            }
            else
            {
                if (req.type == ReqType.RD)
                {
                    rload--;
                }
                else
                {
                    wload--;
                }
            }

/*           //dequeue proper
 *         if (req.type == ReqType.RD) {
 *              //traverse crossbar
 *            Sim.xbar.enqueue(req);
 *
 *              //cache
 *             Sim.caches[Sim.get_cache(req.pid)].meta_insert(req);
 *          }
 *          else {
 *              bool removeok = mctrl_writeq.Remove(req);
 *              Dbg.Assert(removeok);
 *              req.latency = (int)(req.ts_departure - req.ts_arrival);
 *
 *              Callback cb = req.callback;
 *              cb(req);
 *
 *              if (!req.cache_wb) {
 *                  //cache
 *                  switch (Config.proc.cache_write_policy) {
 *                      case "WriteThrough":
 *                          // do nothing
 *                          break;
 *                      case "WriteBack":
 *                            Sim.caches[Sim.get_cache(req.pid)].meta_insert(req);
 *                          break;
 *                  }
 *              }
 *              else
 *                  RequestPool.enpool(req);
 *          }
 */


            if (req.type == ReqType.RD)
            {
                if (!Sim.caches[Sim.get_cache(req.pid)].is_cached(req))
                {
                    Sim.caches[Sim.get_cache(req.pid)].meta_insert(req);
                }
                //      if (req.callback != null)
                Sim.xbar.enqueue(req);
                //      else
                //           RequestPool.enpool(req);
            }
            else
            {
                bool removeok = mctrl_writeq.Remove(req);
                Dbg.Assert(removeok);
                req.latency = (int)(req.ts_departure - req.ts_arrival);
                Callback cb = req.callback;
                if (!req.cache_wb)
                {
                    switch (Config.proc.cache_write_policy)
                    {
                    case "WriteThrough":
                        break;

                    case "WriteBack":
                        if (!Sim.caches[Sim.get_cache(req.pid)].is_cached(req))
                        {
                            Sim.caches[Sim.get_cache(req.pid)].meta_insert(req);
                        }
                        break;
                    }
                    if (cb != null)
                    {
                        cb(req);
                    }
                    //           else
                    //             RequestPool.enpool(req);
                }
                else
                {
                    RequestPool.enpool(req);
                }
            }
        }
Beispiel #11
0
        public void issue_insts(bool issued_rd_req)
        {
            //issue instructions
            for (int i = 0; i < Config.proc.ipc; i++)
            {
                if (inst_wnd.is_full())
                {
                    if (i == 0)
                    {
                        Stat.procs[pid].stall_inst_wnd.Collect();
//                        Measurement.core_stall_cycles[pid] += 1;
                    }
                    return;
                }

                //cpu instructions
                if (curr_cpu_inst_cnt > 0)
                {
                    curr_cpu_inst_cnt--;
                    inst_wnd.add(0, false, true);
                    continue;
                }

                //only one memory instruction can be issued per cycle
                if (issued_rd_req)
                {
                    return;
                }

                //memory instruction (only AFTER checking for one memory instruction per cycle)
                inst_wnd.add(curr_rd_req.block_addr, true, false);

                //check if true miss
                bool false_miss = inst_wnd.is_duplicate(curr_rd_req.block_addr);
                if (false_miss)
                {
                    Dbg.Assert(curr_rd_req.wb_req == null);
                    RequestPool.enpool(curr_rd_req);
                    curr_rd_req = get_req();
                    continue;
                }

                //try mshr
                bool mshr_ok = insert_mshr(curr_rd_req);
                if (!mshr_ok)
                {
                    mshr_retry = true;
                    return;
                }

                //try memory controller
                bool mctrl_ok = insert_mctrl(curr_rd_req);
                if (!mctrl_ok)
                {
                    mctrl_retry = true;
                    return;
                }

                //issued memory request
                issued_rd_req = true;

                //get new read request
                curr_rd_req = get_req();
            }
        }
Beispiel #12
0
        public void issue_insts(bool issued_rd_req)
        {
            //issue instructions
            for (int i = 0; i < Config.proc.ipc; i++)
            {
                if (inst_wnd.is_full())
                {
                    if (i == 0)
                    {
                        Stat.procs[pid].stall_inst_wnd.Collect();
                    }
                    return;
                }

//                Console.Write(" i - " + i + " Proc IPC - " + Config.proc.ipc + "\n");
                //cpu instructions
                if (curr_cpu_inst_cnt > 0)
                {
                    curr_cpu_inst_cnt--;
                    inst_wnd.add(0, false, true, 0);
                    continue;
                }

                //only one memory instruction can be issued per cycle
                if (issued_rd_req)
                {
                    return;
                }


                //check if true miss
                bool false_miss = inst_wnd.is_duplicate(curr_rd_req.block_addr);
                if (false_miss)
                {
                    Dbg.Assert(curr_rd_req.wb_req == null);
                    RequestPool.enpool(curr_rd_req);
                    curr_rd_req = get_req();
                    continue;
                }

                if (!Config.is_cache_filtered)
                {
                    bool is_in_l1_cache = false;
                    is_in_l1_cache = l1_cache.has_addr(curr_rd_req.block_addr, curr_rd_req.proc_req_type);
                    if (is_in_l1_cache)
                    {
                        Stat.procs[pid].l1_cache_hit_count.Collect();
                        RequestPool.enpool(curr_rd_req);
                        curr_rd_req = get_req();
                        inst_wnd.add(curr_rd_req.block_addr, true, true, curr_rd_req.pc);
                        continue;
                    }
                    Stat.procs[pid].l1_cache_miss_count.Collect();
                }



                is_in_cache  = false;
                is_cache_hit = false;

                if (!Config.is_cache_filtered)
                {
                    is_in_cache = cache.has_addr(curr_rd_req.block_addr, curr_rd_req.proc_req_type);
                }

                //check if already in cache
                if (!Config.is_cache_filtered)
                {
                    if (is_in_cache)
                    {
                        Stat.procs[pid].l2_cache_hit_count.Collect();
                        add_to_cache_queue(curr_rd_req);
                        curr_rd_req = get_req();
                        continue;
                    }
                }

                inst_wnd.add(curr_rd_req.block_addr, true, false, false, curr_rd_req.pc);

                if (Config.model_memory)
                {
                    //try mshr
                    bool mshr_ok = insert_mshr(curr_rd_req);
                    if (!mshr_ok)
                    {
                        mshr_retry = true;
                        return;
                    }

                    //try memory controller
                    bool mctrl_ok = insert_mctrl(curr_rd_req);
                    if (!mctrl_ok)
                    {
                        mctrl_retry = true;
                        return;
                    }
                }
                else
                {
                    add_to_mem_queue(curr_rd_req);
                }
                Stat.procs[pid].l2_cache_miss_count.Collect();
                misses++;

                //issued memory request
                issued_rd_req = true;

                //get new read request
                curr_rd_req = get_req();
            }
        }