public boolean access(long addr, long[] wb_tag, boolean isLoad) {
	
	// FIX ME for question 8
    accessTime++;
	
	long addr_tag = getTag(addr);
	int addr_index = getIndex(addr);
	long addr_block = getBlockAddress(addr);
		
	
	boolean[] hit = new boolean[this.associativity];
	int touchedWay = -1;
	boolean hit_f = false;
	for (int i = 0; i < this.associativity; i++)
	{
		hit[i] = cacheTags[addr_index][i] == addr_tag;
		if (hit[i] == true) {
			hit_f = true;
			touchedWay = i;
			break;
		}
	}
	// this is a miss
	if (touchedWay < 0)
	{
		touchedWay = getLRU(addr_index);
	}
	
	boolean dirty = dirtyBits[addr_index][touchedWay];
	dirtyEvic_f = dirty;
	long wb = ((cacheTags[addr_index][touchedWay] << this.nIndexBits) | addr_index) << this.nOffsetBits; // tag + addr_index + touchedWay

	// this is for store
	if (!isLoad) {
		if (!hit_f && dirty) {
			// we need to write back
			this.dirtyCount++;
			wb_tag[0] = wb;
		} 
		dirtyBits[addr_index][touchedWay] = true;
	}
	// this is for load 
	else {
		if (!hit_f) {
            loadCount++;
			dirtyBits[addr_index][touchedWay] = false;
			if (dirty) {
				// we need to write back
				this.dirtyCount++;;
				wb_tag[0] = wb;
			}
		}
	}
	if (victim_f == false) {
	   cacheTags[addr_index][touchedWay] = addr_tag;
	   updateLRU(addr_index, touchedWay);
    }   
	return hit_f;
    }