我有一个实现 FIFO 方法的缓存模拟,这里是关于缓存本身的详细信息:
• The cache has two levels • A cache block is 16 bytes. • Each address is accessing 1 bytes of data. • The L1 cache is a 64 Bytes, 2-way set associative cache. • The L2 cache is a 256 Bytes, 4-way set associative cache. • The cache is inclusive, which mean that data in L1 cache will also remain in the L2 cache. In other word, the data in L1 is a subset of the data in L2 (This assumption simplify your design). • The cache is using a first-in-first-out cache replacement policy. Note that this is simpler to implement than the LRU policy
这是我的实现:
#include "cacheSim.h"
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
unsigned int helper_L1(u_int32_t address, int a, char *fff);
unsigned int helper_L2(u_int32_t address, int b, char *fff);
// In this question, we will assume DRAM will take a 4-byte values starting from 0 to
void init_DRAM()
{
unsigned int i=0;
DRAM = malloc(sizeof(char) * DRAM_SIZE);
for(i=0;i<DRAM_SIZE/4;i++)
{
*((unsigned int*)DRAM+i) = i;
}
}
void printCache()
{
int i,j,k;
printf("===== L1 Cache Content =====\n");
for(i=0;i<2;i++)
{
printf("Set %d :", i);
for(j=0;j<2;j++)
{
printf(" {(TAG: 0x%x)", (unsigned int)(L1_cache[i][j].tag));
for(k=0;k<16;k++)
printf(" 0x%x,", (unsigned int)(L1_cache[i][j].data[k]));
printf(" |");
}
printf("\n");
}
printf("===== L2 Cache Content =====\n");
for(i=0;i<4;i++)
{
printf("Set %d :", i);
for(j=0;j<4;j++)
{
printf(" {(TAG: 0x%x)", (unsigned int)(L2_cache[i][j].tag));
for(k=0;k<16;k++)
printf(" 0x%x,", (unsigned int)(L2_cache[i][j].data[k]));
printf(" |");
}
printf("\n");
}
}
u_int32_t read_fifo(u_int32_t address)
{
u_int32_t setID = getL1SetID(address);
u_int32_t tag = getL1Tag(address);
for (int i = 0; i < 2; i++) {
if (L1_cache[setID][i].tag == tag) {
return L1_cache[setID][i].data[address & 0xF];
}
}
if (L2lookup(address)) {
u_int32_t l2SetID = getL2SetID(address);
for (int i = 0; i < 4; i++) {
if (L2_cache[l2SetID][i].tag == tag) {
cacheBlock temp = L1_cache[setID][0];
L1_cache[setID][0] = L2_cache[l2SetID][i];
L2_cache[l2SetID][i] = temp;
return L1_cache[setID][0].data[address & 0xF];
}
}
}
u_int32_t l2SetID = getL2SetID(address);
u_int32_t l2Tag = getL2Tag(address);
cacheBlock newBlock;
newBlock.tag = l2Tag;
memcpy(newBlock.data, DRAM + (address & 0xFFFFFFF0), 16);
cacheBlock temp = L2_cache[l2SetID][0];
L2_cache[l2SetID][0] = newBlock;
newBlock = temp;
temp = L1_cache[setID][0];
L1_cache[setID][0] = L2_cache[l2SetID][0];
L2_cache[l2SetID][0] = temp;
return L1_cache[setID][0].data[address & 0xF];
}
unsigned int getL1SetID(u_int32_t address)
{
unsigned int setID = (address >> 4) & 1;
return setID;
}
unsigned int getL1Tag(u_int32_t address)
{
unsigned int tag = address >> 5;
return tag;
}
unsigned int getL2SetID(u_int32_t address)
{
unsigned int setID = ((address >> 4) & 3);
return setID;
}
unsigned int getL2Tag(u_int32_t address)
{
unsigned int tag = address >> 6;
return tag;
}
int L1lookup(u_int32_t address)
{
unsigned int setID = getL1SetID(address);
unsigned int tag = getL1Tag(address);
for(int i=0; i<2; i++)
{
if(L1_cache[setID][i].tag == getL1Tag(address)){
return 1;
}
}
return 0;
}
int L2lookup(u_int32_t address)
{
unsigned int setID = getL2SetID(address);
unsigned int tag = getL2Tag(address);
for(int i=0; i<4; i++)
{
if(L2_cache[setID][i].tag == getL2Tag(address))
return 1;
}
return 0;
}
//Below are the three helper functions I've talked about
unsigned int helper_L1(u_int32_t address, int a, char *fff){
memcpy(L1_cache[getL1SetID(address)][a].data, fff,16);
L1_cache[getL1SetID(address)][a].tag = getL1Tag(address);
L1_cache[getL1SetID(address)][a].timeStamp = cycles;
}
unsigned int helper_L2(u_int32_t address, int b, char *fff){
memcpy(L2_cache[getL2SetID(address)][b].data, fff,16);
L2_cache[getL2SetID(address)][b].tag = getL2Tag(address);
L2_cache[getL2SetID(address)][b].timeStamp = cycles;
}
unsigned int helper_L1look(u_int32_t address, int a, int j){
memcpy(L1_cache[getL1SetID(address)][a].data, L2_cache[getL2SetID(address)][j].data, 16);
L1_cache[getL1SetID(address)][a].tag = getL1Tag(address);
L1_cache[getL1SetID(address)][a].timeStamp = cycles;
}
//end of the three helper functions
//below here is the write function
void write(u_int32_t address, u_int32_t data) {
int byt = 15;
int a = 0;
int i = 0;
do {
if (L1_cache[getL1SetID(address)][a].timeStamp > L1_cache[getL1SetID(address)][i].timeStamp) {
a = i;
}
if ((getL1Tag(address) ^ L1_cache[getL1SetID(address)][i].tag) != 1) {
L1_cache[getL1SetID(address)][i].data[address & byt] = data;
}
i++;
} while (i < 2);
int b = 0;
int j = 0;
do {
if (L2_cache[getL2SetID(address)][j].timeStamp < L2_cache[getL2SetID(address)][b].timeStamp) {
b = j;
}
if ((getL2Tag(address) ^ L2_cache[getL2SetID(address)][j].tag) != 1) {
L2_cache[getL2SetID(address)][j].data[address & byt] = data;
if ((L1lookup(address)) == false) {
helper_L1look(address, a, j);
}
}
j++;
} while (j < 4);
int byte = 16;
unsigned char fff[byte];
int gf = address % byte;
int r = 0;
while (r < byte) {
fff[r] = DRAM[gf++];
r++;
}
fff[address & 15] = data;
if (L1lookup(address) != true) {
helper_L1(address, a, fff);
}
if (L2lookup(address) != true) {
helper_L2(address, b, fff);
}
return;
}
问题是我在实现下面的 3 个
unsigned int helper
函数时遇到了麻烦,最终是 void_write()
,因为我希望它们返回一个 unsigned int 但我不知道返回什么或如何返回,或者是否更改它作废与否。
如果您认为我应该更改功能,请告诉我如何更改。
重要:
void_write()
应该假设为直写缓存,它对所有缓存级别执行写入(即,如果有对地址addr的写入,这个新值应该是
针对所有缓存级别以及 DRAM 进行了更新)。
这里是上面代码中使用的所有结构的结构:
#include<stdlib.h>
#include<stdio.h>
#define DRAM_SIZE 1048576
typedef struct cb_struct {
unsigned char data[16]; // One cache block is 16 bytes.
u_int32_t tag;
u_int32_t timeStamp; /// This is used to determine what to evict. You can update the timestamp using cycles.
}cacheBlock;
typedef struct access {
int readWrite; // 0 for read, 1 for write
u_int32_t address;
u_int32_t data; // If this is a read access, value here is 0
}cacheAccess;
// This is our dummy DRAM. You can initialize this in anyway you want to test.
unsigned char * DRAM;
cacheBlock L1_cache[2][2]; // Our 2-way, 64 byte cache
cacheBlock L2_cache[4][4]; // Our 4-way, 256 byte cache
// Trace points to a series of cache accesses.
FILE *trace;
long cycles;
void init_DRAM();
// This function print the content of the cache in the following format for an N-way cache with M Sets
// Set 0 : CB1 | CB2 | CB 3 | ... | CB N
// Set 1 : CB1 | CB2 | CB 3 | ... | CB N
// ...
// Set M-1 : CB1 | CB2 | CB 3 | ... | CB N
void printCache();