MESI Caching work start (was Re: caching and userapi)

Antonio Vargas wind at cocodriloo.com
Sat Jul 19 20:27:55 PDT 2003


On Sat, Jul 19, 2003 at 01:20:18PM -0700, Matthew Dillon wrote:
> 
> :Matt, looking by my books, I've found out references to MESI protocol
> :on the PowerPC 604 manual (page 3-11), which it uses for it's caches.


[ snip ]

I've been coding a bit of this MESI protocol. Unfinished test code attached.

Greets, Antonio.

-- 

1. Dado un programa, siempre tiene al menos un fallo.
2. Dadas varias lineas de codigo, siempre se pueden acortar a menos lineas.
3. Por induccion, todos los programas se pueden
   reducir a una linea que no funciona.


#include <stdio.h>


#define NCPU 8
#define NMEM 10
#define NBUS 50


#define STATE_MODIFIED   0
#define STATE_EXCLUSIVE  1
#define STATE_SHARED     2
#define STATE_INVALID    3


#define BUS_READ       0
#define BUS_READW      1
#define BUS_INVALIDATE 2
#define BUS_PUSH       3


#define PROC_READ           0
#define PROC_READW          1
#define PROC_WRITE          2
#define PROC_INVALIDATE     3
#define PROC_COUNT          4


struct busentry{
	int addr;
	int data;
	int status;
};


struct busentry bus[NBUS];
struct busentry cache[NCPU][NMEM];

int readp[NCPU];
int writep;

int rnddata[3];


int rnd(void)
{
	int a,b,c;

	a = rnddata[0];
	rnddata[0] = b = rnddata[1];
	rnddata[1] = c = rnddata[2];
	rnddata[2] = a + b;

	return a * b + c;
}


void init(void)
{
	struct busentry *b;
	int i,j;

	for(i = 0 ; i < NCPU ; i++){

		readp[i] = -1;

		for(j = 0 ; j < NMEM ; j++){
			b = &cache[i][j];
			b->addr   = j;
			b->data   = i ? 999           : j;
			b->status = i ? STATE_INVALID : STATE_EXCLUSIVE;
		}
	}

	writep = 0;

	rnddata[0] = 2;
	rnddata[1] = 5;
	rnddata[2] = 9;
}


void dump(void)
{
	char a;
	int i,j;
	char s1[3 * NCPU + 1];
	char s2[3 * NCPU + 1];
	struct busentry *b;

	for(j = 0 ; j < NMEM ; j++){

		for(i = 0 ; i < NCPU ; i++){

			b = &cache[i][j];

			switch(b->status){
			case STATE_MODIFIED:  a = 'm'; break;
			case STATE_EXCLUSIVE: a = 'e'; break;
			case STATE_SHARED:    a = 's'; break;
			case STATE_INVALID:   a = 'i'; break;
			}

			sprintf(&s1[i],   "%c",    a);
			sprintf(&s2[i*3], " %02d", b->data);

		}

		s1[i] = 0;
		s2[i*3 - 2] = 0;
		printf("dump: %s %s %02d\n", s1, s2);
	}
}


void bus_process(int cpu)
{
	struct busentry *b,*c;
	int i,j;

	if(cpu >= NCPU) return;

	b = &bus[++readp[cpu]];
	c = &cache[cpu][b->addr];

	bus_process(cpu + 1);
}


void bus_send(int addr, int data, int status)
{
	struct busentry *b = &bus[writep];

	b->addr   = addr;
	b->data   = data;
	b->status = status;

	++writep;

	bus_process(0);
}


void bus_read_invalid(struct busentry *b, int addr){};
void bus_readw_shared(struct busentry *b, int addr){};
void bus_readw_invalid(struct busentry *b, int addr){};
void bus_write_shared(struct busentry *b, int addr, int data){};
void bus_write_invalid(struct busentry *b, int addr, int data){};
void bus_invalidate_modified(struct busentry *b, int addr){};
void bus_invalidate_exclusive(struct busentry *b, int addr){};
void bus_invalidate_shared(struct busentry *b, int addr){};

void proc(int cpu, struct busentry *b)
{
	struct busentry *c = &cache[cpu][b->addr];

	int cc = c->status;
	int addr = b->addr;
	int data = b->data;

	switch(b->status){
	case PROC_READ:
		switch(cc){
		case STATE_MODIFIED:                             break;
		case STATE_EXCLUSIVE:                            break;
		case STATE_SHARED:                               break;
		case STATE_INVALID:   bus_read_invalid(c, addr); break;
		}
		break;

	case PROC_READW:
		switch(cc){
		case STATE_MODIFIED:                              break;
		case STATE_EXCLUSIVE:                             break;
		case STATE_SHARED:    bus_readw_shared(c, addr);  break;
		case STATE_INVALID:   bus_readw_invalid(c, addr); break;
		}
		break;

	case PROC_WRITE:
		switch(cc){
		case STATE_MODIFIED:                                    break;
		case STATE_EXCLUSIVE: c->status = STATE_MODIFIED;       break;
		case STATE_SHARED:    bus_write_shared(c, addr, data);  break;
		case STATE_INVALID:   bus_write_invalid(c, addr, data); break;
		}
		break;

	case PROC_INVALIDATE:
		switch(cc){
		case STATE_MODIFIED:  bus_invalidate_modified(c, addr);  break;
		case STATE_EXCLUSIVE: bus_invalidate_exclusive(c, addr); break;
		case STATE_SHARED:    bus_invalidate_shared(c, addr);    break;
		case STATE_INVALID:                                      break;
		}
		break;
	}
}


int main(int argc, char **argv)
{
	int cpu;
	struct busentry b;

	init();
	dump();

	cpu      = rnd() % NCPU;
	b.addr   = rnd() % NMEM;
	b.data   = rnd() % (NCPU * NMEM % 99);
	b.status = rnd() % PROC_COUNT;

	proc(cpu, &b);

	return 0;
}






More information about the Kernel mailing list