This commit is contained in:
LYC 2024-10-29 17:05:32 +08:00
parent 0d74de5c34
commit 0b1d120fcd
17 changed files with 501 additions and 71 deletions

View File

@ -2,6 +2,7 @@
"files.associations": {
"iomanip": "cpp",
"iosfwd": "cpp",
"vector": "cpp"
"vector": "cpp",
"iostream": "cpp"
}
}

View File

@ -77,7 +77,7 @@ CacheTIO Cache::Address2TIO(uint32_t addr)
void Cache::useCache(uint32_t address, int method)
{
(method == WRITE)?this->StWrite():this->StRead();
(method == WRITE) ? this->StWrite() : this->StRead();
auto addr = this->Address2TIO(address);
auto set = &L1[addr.index];
@ -118,37 +118,80 @@ void Cache::useCache(uint32_t address, int method)
auto toReplace = find_if(
set->block.begin(),
set->block.end(),
[](const Block& b){
[](const Block &b)
{
return !b.valid;
}
);
});
if (toReplace == set->block.end()){
if (toReplace == set->block.end())
{
// Replace
toReplace = min_element(
set->block.begin(),
set->block.end(),
this->replicementPolicy == LRU
?
[](const Block &a, const Block &b){ return a.lastUsed < b.lastUsed; }
:
[](const Block&a, const Block&b){ return a.countBlock < b.countBlock; }
);
? [](const Block &a, const Block &b)
{ return a.lastUsed < b.lastUsed; }
: [](const Block &a, const Block &b)
{ return a.countBlock < b.countBlock; });
}
if (toReplace->dirty) {
if (toReplace->dirty)
{
// Write to the L2 or Disk
this->StWriteBack();
}
set->countSet = toReplace->countBlock;
*toReplace = {addr.tag, set->countSet + 1, lru ++, (bool)method, true};
*toReplace = {addr.tag, set->countSet + 1, lru++, (bool)method, true};
return;
}
void Cache::printResult(){
return ;
double Cache::GetHT()
{
return 0.25 + 2.5 * (size / (512.0 * 1024)) + 0.025 * (blockSize / 16.0) + 0.025 * assoc;
}
double Cache::GetMP()
{
return 20 + 0.5 * (blockSize / 16.0);
}
void Cache::printCache(string filename)
{
cout << " ===== Simulator configuration =====\n";
cout << " L1_BLOCKSIZE:" << setw(22) << this->blockSize << endl;
cout << " L1_SIZE:" << setw(27) << this->size << endl;
cout << " L1_ASSOC:" << setw(26) << this->assoc << endl;
cout << " L1_REPLACEMENT_POLICY:" << setw(13) << this->replicementPolicy << endl;
cout << " L1_WRITE_POLICY:" << setw(19) << this->writePolicy << endl;
cout << " trace_file:" << setw(24) << filename << endl;
cout << " ===================================\n\n";
cout << "===== L1 contents =====" << endl;
for (uint32_t i = 0; i != this->L1.size(); i++)
{
cout << "set" << setw(4) << i << ":";
for (auto &b : this->L1[i].block)
cout << hex << setw(8) << b.tag << ' ' << ((this->writePolicy == WBWA && b.dirty) ? 'D' : ' ');
cout << endl
<< dec;
}
cout << "\n ====== Simulation results (raw) ======\n";
cout << " a. number of L1 reads:" << setw(16) << this->readCount << endl;
cout << " b. number of L1 read misses:" << setw(10) << this->readMiss << endl;
cout << " c. number of L1 writes:" << setw(15) << this->writeCount << endl;
cout << " d. number of L1 write misses:" << setw(9) << this->writeMiss << endl;
double mr = (this->readMiss + this->writeMiss) / (double)(this->readCount + this->writeCount);
cout << " e. L1 miss rate:" << setw(22) << fixed << setprecision(4) << mr << endl;
cout << " f. number of writebacks from L1:" << setw(6) << this->writeBack << endl;
cout << " g. total memory traffic:" << setw(14) << ((this->writePolicy) ? (this->readMiss + this->writeCount) : (this->readMiss + this->writeMiss + this->writeBack));
cout << "\n\n ==== Simulation results (performance) ====\n";
double ht = this->GetHT();
double mp = this->GetMP();
cout << " 1. average access time:" << setw(15) << ht + mr * mp << " ns";
// return cout;
}

View File

@ -20,10 +20,10 @@ struct Block
bool dirty = false; // dirty
bool valid = false; // valid
bool operator<(const Block &t) { return this->countBlock < t.countBlock; }
friend ostream &operator<<(ostream &os, Block &b)
friend ostream &operator<<(ostream &cout, Block &b)
{
os << "{tag:" << b.tag << ", Count-Block:" << b.countBlock << ", Last-Used:" << b.lastUsed << ", Dirty:" << b.dirty << ", Valid:" << b.valid << "}";
return os;
cout << "{tag:" << b.tag << ", Count-Block:" << b.countBlock << ", Last-Used:" << b.lastUsed << ", Dirty:" << b.dirty << ", Valid:" << b.valid << "}";
return cout;
}
};
@ -78,57 +78,13 @@ public:
void StReadMiss();
void StWriteBack();
void writeCache(uint32_t address);
void readCache(uint32_t address);
void useCache(uint32_t address, int method);
void printResult();
double GetHT() {
return 0.25 + 2.5 * (size/ (512.0 * 1024)) + 0.025 * (blockSize/ 16.0) + 0.025 * assoc;
}
double GetHT();
double GetMP();
double GetMP() {
return 20 + 0.5 * (blockSize / 16.0);
}
void printCache(ostream& os, Cache c,string filename){
os << " ===== Simulator configuration =====\n";
os << " L1_BLOCKSIZE:" << setw(22) << c.blockSize << endl;
os << " L1_SIZE:" << setw(27) << c.size << endl;
os << " L1_ASSOC:" << setw(26) << c.assoc << endl;
os << " L1_REPLACEMENT_POLICY:" << setw(13) << c.replicementPolicy << endl;
os << " L1_WRITE_POLICY:" << setw(19) << c.writePolicy << endl;
os << " trace_file:" << setw(24) << filename << endl;
os << " ===================================\n\n";
os << "===== L1 contents =====" << endl;
for (uint32_t i=0;i!=c.L1.size();i++){
os << "set" << setw(4) << i << ":";
for(auto &b:c.L1[i].block)
os << hex << setw(8) << b.tag << ' ' << ((c.writePolicy == WBWA && b.dirty) ? 'D' : ' ');
os << endl << dec;
}
os << "\n ====== Simulation results (raw) ======\n";
os << " a. number of L1 reads:" << setw(16) << c.readCount << endl;
os << " b. number of L1 read misses:" << setw(10) << c.readMiss << endl;
os << " c. number of L1 writes:" << setw(15) << c.writeCount << endl;
os << " d. number of L1 write misses:" << setw(9) << c.writeMiss << endl;
double mr = (c.readMiss + c.writeMiss) / (double)(c.readCount + c.writeCount);
os << " e. L1 miss rate:" << setw(22) << fixed << setprecision(4) << mr << endl;
os << " f. number of writebacks from L1:" << setw(6) << c.writeBack << endl;
os << " g. total memory traffic:" << setw(14) << ((c.writePolicy) ? (c.readMiss + c.writeCount) : (c.readMiss + c.writeMiss + c.writeBack));
os << "\n\n ==== Simulation results (performance) ====\n";
double ht = c.GetHT();
double mp = c.GetMP();
os << " 1. average access time:" << setw(15) << ht + mr * mp << " ns";
//return os;
}
void printCache(string filename);
CacheTIO Address2TIO(uint32_t addr);
};

Binary file not shown.

View File

@ -29,7 +29,7 @@ int main(int argc, char *argv[])
cache->useCache(addr, op == 'w');
}
trace.close();
cache->printCache(cout, *cache, fileName);
cache->printCache(fileName);
}
catch (const char *e)
{

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,46 @@
CC = g++
#OPT = -O3 -m32
OPT = -g
WARN = -Wall
CFLAGS = $(OPT) $(WARN) $(INC) $(LIB)
# List all your .cc files here (source files, excluding header files)
SIM_SRC = main.cc cache.cc
# List corresponding compiled object files here (.o files)
SIM_OBJ = main.o cache.o
#################################
# default rule
all: sim_cache
@echo "my work is done here..."
# rule for making sim_cache
sim_cache: $(SIM_OBJ)
$(CC) -o sim_cache $(CFLAGS) $(SIM_OBJ) -lm
@echo "-----------DONE WITH SIM_CACHE-----------"
# generic rule for converting any .cc file to any .o file
.cc.o:
$(CC) $(CFLAGS) -c $*.cc
# type "make clean" to remove all .o files plus the sim_cache binary
clean:
rm -f *.o sim_cache
rm -f *.txt *.diff
# type "make clobber" to remove all .o files (leaves sim_cache binary)
clobber:
rm -f *.o

View File

@ -0,0 +1,197 @@
#include "cache.h"
using namespace std;
Cache::Cache(char *argv[])
{
this->blockSize = atoi(argv[1]);
this->size = atoi(argv[2]);
this->assoc = atoi(argv[3]);
this->replicementPolicy = atoi(argv[4]);
this->writePolicy = atoi(argv[5]);
if ((this->blockSize < 0) || !(this->blockSize ^ (this->blockSize - 1)))
{
throw "Para blockSize Err.";
}
if (this->size < 0)
{
throw "Para Size Err.";
}
if (this->assoc < 1)
{
throw "Para assoc Err.";
}
if (this->replicementPolicy != LRU && this->replicementPolicy != LFU)
{
throw "Para replicementPolicy Err.";
}
if (this->writePolicy != WBWA && this->writePolicy != WTNA)
{
throw "Para writePolicy Err.";
}
this->offset = log2_floor(this->blockSize);
this->index = log2_floor(this->size / (this->blockSize * this->assoc));
this->tagBit = 32 - this->offset - this->index;
this->offsetMask = (1 << this->offset) - 1;
this->indexMask = ((1 << this->index) - 1) << this->offset;
this->L1.resize(this->getMaxIndex());
for (auto &s : L1)
s.block.resize(this->getAssoc());
}
Cache::~Cache()
{
}
void Cache::StWrite() { this->writeCount++; }
void Cache::StWriteMiss() { this->writeMiss++; }
void Cache::StRead() { this->readCount++; }
void Cache::StReadMiss() { this->readMiss++; }
void Cache::StWriteBack() { this->writeBack++; }
uint32_t Cache::getMaxIndex()
{
return (1 << this->index);
}
uint32_t Cache::getAssoc()
{
return this->assoc;
}
int Cache::log2_floor(uint32_t x)
{
return x == 0 ? -1 : 31 - __builtin_clz(x);
}
CacheTIO Cache::Address2TIO(uint32_t addr)
{
uint32_t offset = addr & this->offsetMask;
uint32_t index = (addr & this->indexMask) >> this->offset;
uint32_t tag = addr >> (this->offset + this->index);
return {tag, index, offset};
}
void Cache::useCache(uint32_t address, int method)
{
(method == WRITE) ? this->StWrite() : this->StRead();
auto addr = this->Address2TIO(address);
auto set = &L1[addr.index];
auto tag = addr.tag;
auto hit = find_if(
set->block.begin(),
set->block.end(),
[tag](const Block &b)
{
return b.valid && b.tag == tag;
});
if (hit != set->block.end())
{
// Cache Hit!
hit->countBlock++;
hit->lastUsed = this->lru++;
if (method == WRITE && this->writePolicy == WBWA)
{
hit->dirty = true;
}
return;
}
if (method == WRITE)
{
this->StWriteMiss();
}
else
{
this->StReadMiss();
}
if (method == WRITE && this->writePolicy == WTNA)
return;
auto toReplace = find_if(
set->block.begin(),
set->block.end(),
[](const Block &b)
{
return !b.valid;
});
if (toReplace == set->block.end())
{
// Replace
toReplace = min_element(
set->block.begin(),
set->block.end(),
this->replicementPolicy == LRU
? [](const Block &a, const Block &b)
{ return a.lastUsed < b.lastUsed; }
: [](const Block &a, const Block &b)
{ return a.countBlock < b.countBlock; });
}
if (toReplace->dirty)
{
// Write to the L2 or Disk
this->StWriteBack();
}
set->countSet = toReplace->countBlock;
*toReplace = {addr.tag, set->countSet + 1, lru++, (bool)method, true};
return;
}
double Cache::GetHT()
{
return 0.25 + 2.5 * (size / (512.0 * 1024)) + 0.025 * (blockSize / 16.0) + 0.025 * assoc;
}
double Cache::GetMP()
{
return 20 + 0.5 * (blockSize / 16.0);
}
void Cache::printCache(string filename)
{
cout << " ===== Simulator configuration =====\n";
cout << " L1_BLOCKSIZE:" << setw(22) << this->blockSize << endl;
cout << " L1_SIZE:" << setw(27) << this->size << endl;
cout << " L1_ASSOC:" << setw(26) << this->assoc << endl;
cout << " L1_REPLACEMENT_POLICY:" << setw(13) << this->replicementPolicy << endl;
cout << " L1_WRITE_POLICY:" << setw(19) << this->writePolicy << endl;
cout << " trace_file:" << setw(24) << filename << endl;
cout << " ===================================\n\n";
cout << "===== L1 contents =====" << endl;
for (uint32_t i = 0; i != this->L1.size(); i++)
{
cout << "set" << setw(4) << i << ":";
for (auto &b : this->L1[i].block)
cout << hex << setw(8) << b.tag << ' ' << ((this->writePolicy == WBWA && b.dirty) ? 'D' : ' ');
cout << endl
<< dec;
}
cout << "\n ====== Simulation results (raw) ======\n";
cout << " a. number of L1 reads:" << setw(16) << this->readCount << endl;
cout << " b. number of L1 read misses:" << setw(10) << this->readMiss << endl;
cout << " c. number of L1 writes:" << setw(15) << this->writeCount << endl;
cout << " d. number of L1 write misses:" << setw(9) << this->writeMiss << endl;
double mr = (this->readMiss + this->writeMiss) / (double)(this->readCount + this->writeCount);
cout << " e. L1 miss rate:" << setw(22) << fixed << setprecision(4) << mr << endl;
cout << " f. number of writebacks from L1:" << setw(6) << this->writeBack << endl;
cout << " g. total memory traffic:" << setw(14) << ((this->writePolicy) ? (this->readMiss + this->writeCount) : (this->readMiss + this->writeMiss + this->writeBack));
cout << "\n\n ==== Simulation results (performance) ====\n";
double ht = this->GetHT();
double mp = this->GetMP();
cout << " 1. average access time:" << setw(15) << ht + mr * mp << " ns";
// return cout;
}

View File

@ -0,0 +1,91 @@
#pragma once
#include "public.h"
#include <iostream>
#include <ostream>
#include <vector>
#include <iomanip>
using namespace std;
struct CacheTIO
{
uint32_t tag, index, offset;
};
struct Block
{
uint32_t lru = 0;
uint32_t tag = 0; // tag
uint32_t countBlock = 0; // count block
uint32_t lastUsed = 0; // Last Used
bool dirty = false; // dirty
bool valid = false; // valid
bool operator<(const Block &t) { return this->countBlock < t.countBlock; }
friend ostream &operator<<(ostream &cout, Block &b)
{
cout << "{tag:" << b.tag << ", Count-Block:" << b.countBlock << ", Last-Used:" << b.lastUsed << ", Dirty:" << b.dirty << ", Valid:" << b.valid << "}";
return cout;
}
};
struct Set
{
uint32_t countSet = 0; // count set
vector<Block> block; // Blocks
};
class Cache
{
private:
// Param
int blockSize; // Block Size
int size; // Size
int assoc; // Assoc
int replicementPolicy; // Replicement Policy
int writePolicy; // Write Policy: 1 -> WTNA, 0 ->
int tagBit; // tag bit
int index; // index
int offset; // offset
uint32_t offsetMask; // offset mask
uint32_t indexMask; // index mask
// Statistic
int readCount = 0; // Read Count
int readMiss = 0; // Read Miss
int writeCount = 0; // Write Count
int writeMiss = 0; // Write Miss
int writeBack = 0; // Write Back
uint32_t lru = 0; // LRU Global Counter
// main cache
vector<Set> L1;
// L2 cache
Cache *L2;
public:
Cache(char *argv[]);
~Cache();
uint32_t getMaxIndex();
uint32_t getAssoc();
int log2_floor(uint32_t x);
void StWrite();
void StWriteMiss();
void StRead();
void StReadMiss();
void StWriteBack();
void useCache(uint32_t address, int method);
void printResult();
double GetHT();
double GetMP();
void printCache(string filename);
CacheTIO Address2TIO(uint32_t addr);
};

Binary file not shown.

View File

@ -0,0 +1,38 @@
#include "cache.h"
#include "public.h"
using namespace std;
int main(int argc, char *argv[])
{
try
{
if (argc != 7)
{
throw "Para Err.";
}
auto fileName = std::string(argv[6]);
struct stat buffer;
if (stat(("../traces/" + fileName).c_str(), &buffer))
{
throw "traces file Err.";
}
auto cache = new Cache(argv);
ifstream trace("../traces/" + fileName);
string line;
char op;
unsigned addr;
while (getline(trace, line) && (istringstream(line) >> op >> hex >> addr))
{
cache->useCache(addr, op == 'w');
}
trace.close();
cache->printCache(fileName);
}
catch (const char *e)
{
std::cerr << "Caught exception: " << e << std::endl;
}
}

Binary file not shown.

View File

@ -0,0 +1,22 @@
#pragma once
#define LRU 0
#define LFU 1
#define WBWA 0
#define WTNA 1
#define WRITE 1
#define READ 0
#include <algorithm>
#include <cstdint>
#include <exception>
#include <fstream>
#include <iostream>
#include <cstdlib>
#include <sstream>
#include <stdexcept>
#include <stdlib.h>
#include <stdio.h>
#include <sys/stat.h>

Binary file not shown.

View File

@ -0,0 +1,22 @@
make clean
make
./sim_cache 16 16384 1 0 0 gcc_trace.txt > ../output/test1.txt
./sim_cache 128 2048 8 0 1 go_trace.txt > ../output/test2.txt
./sim_cache 32 4096 4 0 1 perl_trace.txt > ../output/test3.txt
./sim_cache 64 8192 2 1 0 gcc_trace.txt > ../output/test4.txt
./sim_cache 32 1024 4 1 1 go_trace.txt > ../output/test5.txt
echo "Comparing 1 :"
diff -iw ../output/test1.txt ../validation/ValidationRun1.txt
echo "Comparing 2 :"
diff -iw ../output/test2.txt ../validation/ValidationRun2.txt
echo "Comparing 3 :"
diff -iw ../output/test3.txt ../validation/ValidationRun3.txt
echo "Comparing 4 :"
diff -iw ../output/test4.txt ../validation/ValidationRun4.txt
echo "Comparing 5 :"
diff -iw ../output/test5.txt ../validation/ValidationRun5.txt

View File

@ -0,0 +1,14 @@
1. Download all the source files (.cc, .h) plus the Makefile to your own directory. (To download, click on the link with your right mouse button and select "Save Link As...".)
2. "make" (this will create the binary, sim_cache)
3. Try running "sim_cache" with any number of arguments. It will simply print "Hello World!" and then echo all the arguments back to you. For example, try this example from the Project 1 spec:
./sim_cache 32 8192 4 0 1 gcc_trace.txt
4. "make clean" (this will remove all .o files and the binary sim_cache)
5. "make" (build again)
6. "make clobber" (this will remove only .o files, leaving the binary sim_cache)
---------------------------------------------------------------------
You only need the Makefile from this directory. (The other bogus .cc/.h files are merely there as an example.)
What you need to modify in the Makefile for your own needs:
1. In the Makefile, replace all the .cc filenames with your .cc filenames, on the line labeled SIM_SRC. You can use as few or as many .cc files as you want.
2. Likewise, update the names of .o files in the Makefile, on the line labeled SIM_OBJ. There must be a corresponding .o file for every .cc file.
----------------------------------------------------------------------
If you are using a different language/compiler, replace CC with your preferred compiler. You may also need to modify the default CFLAGS, depending on what other arguments your compiler requires. Also, if you use a different language, then you may need to change the .cc extensions to something else.