我正在使用gcc作为编译器在linux上用C编写一个缓存模拟程序,并且大部分工作已经完成。只有少数测试用例出错(应击中的数千个联邦地址中有几项缺失)。我在命令行上指定缓存属性。我怀疑代码中的错误与标签有关(如果事情没有实现,那么它们的标签就不应该匹配)。所以我的问题是:我计算标签正确吗?
//setting sizes of bits
int offsetSize = log2(lineSize);
int indexSize = 0;
if (strcmp(associativity,"direct") == 0){//direct associativity
indexSize = log2(numLines);
}else if (assocNum == numLines){//fully associative
indexSize = 0;
}else{//set associative
indexSize = log2(assocNum);
}
address = (int) strtol(readAddress,&eptr,16);
unsigned long long int mask = 0;
//get the offset Bits
mask = (1 << offsetSize) - 1;
offsetBits = address & mask;
//get the index bits
mask = (1 << (indexSize)) - 1;
mask = mask << offsetSize;
indexBits = (address & mask) >> offsetSize;
//get tag bits
tagBits = address >> (offsetSize+indexSize);
要馈送的地址通常为48位,因此变量address和mask的类型为unsigned long long int。我认为我遇到的问题是,当我应该只从大地址中取出一小部分位时,我正在占用地址的所有高位字节。
例如:我在4路组关联缓存中有32个缓存行,块大小为4。
offsetSize = log2(4)= 2
indexSize = log2(4)= 2
无论地址大小如何,我的代码当前都占用地址的高位,减去最后4位。我应该只使用高28位吗? (tagSize =(8 * 4)-3-2)
答案 0 :(得分:1)
无论地址大小如何,我的代码当前都占用地址的高位,减去最后4位。我应该只使用高28位吗?
标签必须包含所有高位,以便可以使用标签来确定它是否是缓存命中。
如果地址是48位并且分为3个字段,则您将有一个2位的“高速缓存行中的偏移量”字段,一个2位的“高速缓存中的索引”字段和一个44位的“高位”字段必须存储在“代码”字段中。如果您仅在标记中存储28位,那么当您应该遇到高速缓存未命中时,您会遇到高速缓存命中(因为高速缓存中的条目恰好包含28位恰好匹配的其他地址的数据)。
请注意,您可以/应该将“关联性”理解为并行运行的高速缓存行的数量(其中直接映射的只是“ associativity = 1”,而完全关联的只是“ associativity = total_cache_size” / cache_line_size”)。关联性对索引大小没有直接影响(仅高速缓存行集的大小与索引大小有关),并且您遇到的问题可能与indexSize = log2(assocNum);
有关(这没有意义)
换句话说:
if( direct_mapped ) {
associativity = 1;
} else {
max_associativity = total_cache_size / cache_line_size;
if( fully_associative || (associativity > max_associativity) ) {
associativity = max_associativity;
}
}
set_size = total_cache_size / associativity;
number_of_lines_in_set = set_size / cache_line_size;
offset_size = log2(cache_line_size);
index_size = log2(number_of_lines_in_set);
tag_size = address_size - index_size - offsetSize;