I'm assuming that cacheconfig.numLines
, cacheconfig.associativity
, and cacheconfig.lineSize
are unsigned int
. If they are not, you may need a cast somewhere, or you can change them to be unsigned
.
The first step is to arrange these common subexpressions in one place, and thereby define the variables a
and b
:
unsigned int a = log2(cacheconfig.numLines / cacheconfig.associativity);
unsigned int b = log2(cacheconfig.lineSize);
string binario = bitset<256>(address).to_string();
int InicioDado = 256 - b;
string dado = binario.substr(InicioDado, b);
int InicioIndex = InicioDado - a;
string index = binario.substr(InicioIndex, a);
int InicioTag = 256 - cacheconfig.lineSize;
string tag = binario.substr(InicioTag, 256 - InicioTag - b);
long unsigned int Tag = bitset<256>(tag).to_ulong();
long unsigned int Index = bitset<256>(index).to_ulong();
long unsigned int Dado = bitset<256>(dado).to_ulong();
Let's remove the variables of type int
intermediary:
unsigned int a = log2(cacheconfig.numLines / cacheconfig.associativity);
unsigned int b = log2(cacheconfig.lineSize);
string binario = bitset<256>(address).to_string();
string dado = binario.substr(256 - b, b);
string index = binario.substr(256 - b - a, a);
string tag = binario.substr(256 - cacheconfig.lineSize, cacheconfig.lineSize - b);
long unsigned int Tag = bitset<256>(tag).to_ulong();
long unsigned int Index = bitset<256>(index).to_ulong();
long unsigned int Dado = bitset<256>(dado).to_ulong();
Now, let's see what it does. You get address
, convert to a binary string using bitset
, spike that string in some parts, and use bitset
to convert those binary substrings to numbers later. Since this is a numerical calculation, I do not think it is ideal to use strings in it. This seems to be a task for bitwise operators <<
, >>
and &
.
First you get the last b
bits, which are Dado
. The%% of previous bits are a
. The Index
seems strange to me, but it's the last Tag
bits except for the last cacheconfig.lineSize
bits. This is strange because there is an intersection between b
and Tag
.
Well, to get the last Index
bits of a number k
, being x
, we can do this:
x & ((1 << k) - 1)
To discard the last k >= 1
digits, we do this:
x >> k
Let's create some macros to make it easier (adding the parentheses around each parameter and macro as a whole to make them hygienic):
#define OBTER_ULTIMOS_BITS(x, k) ((x) & ((1 << (k)) - 1))
#define DESCARTAR_ULTIMOS_BITS(x, k) ((x) >> (k))
So, your code looks like this:
unsigned int a = log2(cacheconfig.numLines / cacheconfig.associativity);
unsigned int b = log2(cacheconfig.lineSize);
long unsigned int Tag = DESCARTAR_ULTIMOS_BITS(OBTER_ULTIMOS_BITS(address, cacheconfig.lineSize), b);
long unsigned int Index = DESCARTAR_ULTIMOS_BITS(OBTER_ULTIMOS_BITS(address, b + a), b);
long unsigned int Dado = OBTER_ULTIMOS_BITS(address, b);
And this code is the same in both C and C ++.
You may still need a function that (re) defines its k
. Here is a implementation that I copied from this response . Just include it if you can not for some reason use the default implementation:
unsigned int log2(unsigned int x) {
unsigned int resultado = 0;
while (x >>= 1) resultado++;
return resultado;
}