【发布时间】:2022-01-12 02:30:16
【问题描述】:
我必须使用 C 进一步开发一个模拟器,能够模拟不同的缓存类型(直接、n 路关联、完全关联)。现在我的代码可以模拟直接映射的缓存,但它不能模拟任何其他类型。
我的代码 我的 C 文件:
/*
* CS3375 Computer Architecture
* Course Project
* Cache Simulator Design and Development
* FALL 2017
* By Yong Chen
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <math.h>
#include "cachesim.h"
int main(int argc, char *argv[])
{
char type;
if (argc != 3) {
printf("Usage: %s <direct> <trace file name>\n", argv[0]);
return 1;
}
#ifdef DBG
printf("BLOCK SIZE = %d Bytes\n", BLOCK_SIZE);
printf("%d-WAY\n", WAY_SIZE);
printf("CACHE SIZE = %d Bytes\n", CACHE_SIZE);
printf("NUMBER OF BLOCKS = %d\n", NUM_BLOCKS);
printf("NUMBER OF SETS = %d\n", NUM_SETS);
printf("\n");
#endif
struct direct_mapped_cache d_cache;
char* trace_file_name = argv[2];
char mem_request[20];
uint64_t address;
FILE *fp;
/* Initialization */
for (int i=0; i<NUM_BLOCKS; i++) {
d_cache.valid_field[i] = 0;
d_cache.dirty_field[i] = 0;
d_cache.tag_field[i] = 0;
}
d_cache.hits = 0;
d_cache.misses = 0;
/* Opening the memory trace file */
fp = fopen(trace_file_name, "r");
/*Checks if argument specified direct-mapped cache*/
if (strncmp(argv[1], "direct", 6)==0) { /* Simulating direct-mapped cache */
/* Read the memory request address and access the cache */
while (fgets(mem_request, 20, fp)!= NULL) {
address = convert_address(mem_request);
direct_mapped_cache_access(&d_cache, address);
}
/*Calculate Hit and Miss Rate*/
double hit_rate = ((1.0 * d_cache.hits)/(d_cache.hits + d_cache.misses));
double miss_rate = ((1.0 * d_cache.misses)/(d_cache.hits + d_cache.misses));
/*Print out the results*/
printf("\n==================================\n");
printf("Cache type: Direct-Mapped Cache\n");
printf("==================================\n");
printf("Cache Hits: %d\n", d_cache.hits);
printf("Cache Misses: %d\n", d_cache.misses);
printf("Cache Hit Rate: %f\n", hit_rate);
printf("Cache Miss Rate: %f\n", miss_rate);
printf("\n");
}
fclose(fp);
return 0;
}
uint64_t convert_address(char memory_addr[])
/* Converts the physical 32-bit address in the trace file to the "binary" \\
* (a uint64 that can have bitwise operations on it) */
{
uint64_t binary = 0;
int i = 0;
while (memory_addr[i] != '\n') {
if (memory_addr[i] <= '9' && memory_addr[i] >= '0') {
binary = (binary*16) + (memory_addr[i] - '0');
} else {
if(memory_addr[i] == 'a' || memory_addr[i] == 'A') {
binary = (binary*16) + 10;
}
if(memory_addr[i] == 'b' || memory_addr[i] == 'B') {
binary = (binary*16) + 11;
}
if(memory_addr[i] == 'c' || memory_addr[i] == 'C') {
binary = (binary*16) + 12;
}
if(memory_addr[i] == 'd' || memory_addr[i] == 'D') {
binary = (binary*16) + 13;
}
if(memory_addr[i] == 'e' || memory_addr[i] == 'E') {
binary = (binary*16) + 14;
}
if(memory_addr[i] == 'f' || memory_addr[i] == 'F') {
binary = (binary*16) + 15;
}
}
i++;
}
#ifdef DBG
printf("%s converted to %llu\n", memory_addr, binary);
#endif
return binary;
}
void direct_mapped_cache_access(struct direct_mapped_cache *cache, uint64_t address)
{
uint64_t block_addr = address >> (unsigned)log2(BLOCK_SIZE);
uint64_t index = block_addr % NUM_BLOCKS;
uint64_t tag = block_addr >> (unsigned)log2(NUM_BLOCKS);
#ifdef DBG
printf("Memory address: %llu, Block address: %llu, Index: %llu, Tag: %llu ", address, block_addr, index, tag);
#endif
if (cache->valid_field[index] && cache->tag_field[index] == tag) { /* Cache hit */
cache->hits += 1;
#ifdef DBG
printf("Hit!\n");
#endif
} else {
/* Cache miss */
cache->misses += 1;
#ifdef DBG
printf("Miss!\n");
#endif
if (cache->valid_field[index] && cache->dirty_field[index]) {
/* Write the cache block back to memory */
}
cache->tag_field[index] = tag;
cache->valid_field[index] = 1;
cache->dirty_field[index] = 0;
}
}
我的 .h 文件:
/*
* CS3375 Computer Architecture
* Course Project
* Cache Simulator Design and Development
* FALL 2017
* By Yong Chen
*/
#include <stdio.h>
/* Cache block size (or cache line size) in bytes*/
#define BLOCK_SIZE 64 /*(must be power of 2). 4 Bytes = 1 Word NOTE: MUST CHANGE DEPENDING ON TYPE*/
#define WAY_SIZE 1 /* Associativity; 1-way = direct-mapped MUST CHANGE DEPENDING ON TYPE*/
#define CACHE_SIZE 32768 /* Cache capacity in bytes (must be power of 2) THIS WILL STAY FIXED*/
#define NUM_BLOCKS (CACHE_SIZE / BLOCK_SIZE)
#define NUM_SETS (BLOCK_SIZE/WAY_SIZE)
/*For fully associative, num sets is equal to num blocks because way size is equal to num blocks. */
/*MAY TRY LEAVING THESE VARIABLES UNDEFINED, AND THEY WILL BE SET DEPENDING ON USER INPUT.*/
#define DBG /*Prints debugging information*/
/*The data structure of direct-mapped cache*/
struct direct_mapped_cache {
unsigned valid_field[NUM_BLOCKS]; /* Valid field */
unsigned dirty_field[NUM_BLOCKS]; /* Dirty field; since we don't distinguish writes and \\
reads in this project yet, this field doesn't really matter */
uint64_t tag_field[NUM_BLOCKS]; /* Tag field */
char data_field[NUM_BLOCKS][BLOCK_SIZE]; /* Data field; since we don't really fetch data, \\
this field doesn't really matter */
int hits; /* Hit count */
int misses; /* Miss count */
};
/*Read the memory traces and convert it to binary*/
uint64_t convert_address(char memory[]);
/*Simulate the direct-mapped cache*/
void direct_mapped_cache_access(struct direct_mapped_cache *cache, uint64_t address);
我的尝试 诚然,我是 C 语言的初学者,所以我的解决方案可能比我想象的要简单,但到目前为止我还没有找到任何答案。我考虑过根据参数更改使用“#define”定义缓存变量的位置,但我了解到“#define”是通过预处理运行的,所以这不起作用。
我也尝试为每种需要模拟的缓存类型创建多个结构类,但由于 C 中的结构变量无法在类中初始化,我也无法让它工作。
据我了解,C 中的结构也不能有构造函数,因为我也对此进行了研究。
我们将不胜感激任何帮助或朝着正确方向迈出的一步。
【问题讨论】:
-
结构在编译时声明,不能更改。您可以使用动态分配在每个结构中放置更多或更少的数据。 C 结构不能有构造函数,我不确定如果存在它会有什么帮助。您有一个将十六进制文本转换为整数的部分,您可以使用
sscanf。data_field为每个元素分配 32kb,但未使用。