コード例 #1
0
ファイル: prefetcher.c プロジェクト: RCSL-HKUST/heterosim
/* This function implements the GHB based PC/CS prefetching as described in the
 * 2005 paper by Nesbit and Smith. The index table lookup is based on the PC
 * of the instruction causing the miss. The GHB entries are looked at for finding
 * constant stride accesses. Based on this, prefetching is done. */
static void prefetcher_ghb_pc_cs(struct mod_t *mod, struct mod_stack_t *stack, int it_index)
{
	struct prefetcher_t *pref;
	int chain, stride, i;
	unsigned int prev_addr, cur_addr, prefetch_addr = 0;

	assert(mod->kind == mod_kind_cache && mod->cache != NULL);
	pref = mod->cache->prefetcher;

	chain = pref->index_table[it_index].ptr;

	/* The lookup depth must be at least 2 - which essentially means
	 * two strides have been seen so far, prefetch for the next. 
	 * It doesn't really help to prefetch on a lookup of depth 1.
	 * It is too low an accuracy and leads to lot of illegal and
	 * redundant prefetches. Hence keeping the minimum at 2. */
	assert(pref->lookup_depth >= 2);

	/* The table should've been updated before calling this function. */
	assert(pref->ghb[chain].addr == stack->addr);

	/* If there's only one element in this linked list, nothing to do. */
	if (pref->ghb[chain].next == -1)
		return;

	prev_addr = pref->ghb[chain].addr;
	chain = pref->ghb[chain].next;
	cur_addr = pref->ghb[chain].addr;
	stride = prev_addr - cur_addr;

	for (i = 2; i <= pref->lookup_depth; i++)
	{
		prev_addr = cur_addr;
		chain = pref->ghb[chain].next;

		/* The linked list (history) is smaller than the lookup depth */
		if (chain == -1)
			break;

		cur_addr = pref->ghb[chain].addr;

		/* The stride changed, can't prefetch */
		if (stride != prev_addr - cur_addr)
			break;

		/* If this is the last iteration (we've seen as much history as
		 * the lookup depth specified), then do a prefetch. */
		if (i == pref->lookup_depth)
			prefetch_addr = stack->addr + stride;
	}

	if (prefetch_addr > 0)
		prefetcher_do_prefetch(mod, stack, prefetch_addr);
}
コード例 #2
0
ファイル: prefetcher.c プロジェクト: xianggong/multi2sim42
/* This function implements the GHB based PC/DC prefetching as described in the
 * 2005 paper by Nesbit and Smith. The index table lookup is based on the PC
 * of the instruction causing the miss. The last three accesses are looked at
 * to find the last two strides (deltas). The list is then looked up backwards
 * to see if this pair of strides occurred earlier, if yes, the next stride
 * is obtained from the history there. This stride decides the new
 * prefetch_addr. */
static void prefetcher_ghb_pc_dc(struct mod_t *mod, struct mod_stack_t *stack,
                                 int it_index) {
    struct prefetcher_t *pref;
    int chain, chain2, stride[PREFETCHER_LOOKUP_DEPTH_MAX], i, pref_stride;
    unsigned int prev_addr, cur_addr, prefetch_addr = 0;

    assert(mod->kind == mod_kind_cache && mod->cache != NULL);
    pref = mod->cache->prefetcher;

    chain = pref->index_table[it_index].ptr;

    /* The lookup depth must be at least 2 - which essentially means
     * two strides have been seen so far, predict the next stride. */
    assert(pref->lookup_depth >= 2 &&
           pref->lookup_depth <= PREFETCHER_LOOKUP_DEPTH_MAX);

    /* The table should've been updated before calling this function. */
    assert(pref->ghb[chain].addr == stack->addr);

    /* Collect "lookup_depth" number of strides (deltas).
     * This doesn't really make sense for a depth > 2, but
     * I'll just have the code here for generality. */
    for (i = 0; i < pref->lookup_depth; i++) {
        prev_addr = pref->ghb[chain].addr;
        chain = pref->ghb[chain].next;

        /* The chain isn't long enough */
        if (chain == -1) return;

        cur_addr = pref->ghb[chain].addr;
        stride[i] = prev_addr - cur_addr;
    }

    chain = pref->index_table[it_index].ptr;
    chain = pref->ghb[chain].next;
    assert(chain != -1);

    /* "chain" now points to the second element of the list.
     * Try to match the stride array starting from here. */
    while (chain != -1) {
        /* This really doesn't look realistic to implement in
         * hardware. Too much time consuming I feel. */
        chain2 = chain;
        for (i = 0; i < pref->lookup_depth; i++) {
            prev_addr = pref->ghb[chain2].addr;
            chain2 = pref->ghb[chain2].next;

            /* The chain isn't long enough and we
             * haven't found a match till now. */
            if (chain2 == -1) return;

            cur_addr = pref->ghb[chain2].addr;
            if (stride[i] != prev_addr - cur_addr) break;
        }

        /* If we traversed the above loop full, we have a match. */
        if (i == pref->lookup_depth) {
            cur_addr = pref->ghb[chain].addr;
            assert(pref->ghb[chain].prev != -1 &&
                   pref->ghb[chain].prev_it_ghb == prefetcher_ptr_ghb);
            chain = pref->ghb[chain].prev;
            prev_addr = pref->ghb[chain].addr;
            pref_stride = prev_addr - cur_addr;
            prefetch_addr = stack->addr + pref_stride;
            break;
        }

        chain = pref->ghb[chain].next;
    }

    if (prefetch_addr > 0) prefetcher_do_prefetch(mod, stack, prefetch_addr);
}