⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cache.c

📁 skyeye的开源代码
💻 C
字号:
#include "armdefs.h"/* mmu cache init * * @cache_t :cache_t to init * @width	:cache line width in byte * @way		:way of each cache set * @set		:cache set num * * $ -1: error * 	 0: sucess */intmmu_cache_init (cache_t * cache_t, int width, int way, int set, int w_mode){	int i, j;	cache_set_t *sets;	cache_line_t *lines;	/*alloc cache set */	sets = NULL;	lines = NULL;	//fprintf(stderr, "mmu_cache_init: mallloc beg size %d,sets 0x%x\n", sizeof(cache_set_t) * set,sets);	//exit(-1);	sets = (cache_set_t *) malloc (sizeof (cache_set_t) * set);	if (sets == NULL) {		err_msg ("set malloc size %d\n", sizeof (cache_set_t) * set);		goto sets_error;	}	//fprintf(stderr, "mmu_cache_init: mallloc end sets 0x%x\n", sets);	cache_t->sets = sets;	/*init cache set */	for (i = 0; i < set; i++) {		/*alloc cache line */		lines = (cache_line_t *) malloc (sizeof (cache_line_t) * way);		if (lines == NULL) {			err_msg ("line malloc size %d\n",				 sizeof (cache_line_t) * way);			goto lines_error;		}		/*init cache line */		for (j = 0; j < way; j++) {			lines[j].tag = 0;	//invalid			lines[j].data = (ARMword *) malloc (width);			if (lines[j].data == NULL) {				err_msg ("data alloc size %d\n", width);				goto data_error;			}		}		sets[i].lines = lines;		sets[i].cycle = 0;	}	cache_t->width = width;	cache_t->set = set;	cache_t->way = way;	cache_t->w_mode = w_mode;	return 0;      data_error:	/*free data */	while (j-- > 0)		free (lines[j].data);	/*free data error line */	free (lines);      lines_error:	/*free lines already alloced */	while (i-- > 0) {		for (j = 0; j < way; j++)			free (sets[i].lines[j].data);		free (sets[i].lines);	}	/*free sets */	free (sets);      sets_error:	return -1;};/* free a cache_t's inner data, the ptr self is not freed, * when needed do like below: * 		mmu_cache_exit(cache); * 		free(cache_t); * * @cache_t : the cache_t to free */voidmmu_cache_exit (cache_t * cache_t){	int i, j;	cache_set_t *sets, *set;	cache_line_t *lines, *line;	/*free all set */	sets = cache_t->sets;	for (set = sets, i = 0; i < cache_t->set; i++, set++) {		/*free all line */		lines = set->lines;		for (line = lines, j = 0; j < cache_t->way; j++, line++)			free (line->data);		free (lines);	}	free (sets);}/* mmu cache search * * @state	:ARMul_State * @cache_t	:cache_t to search * @va		:virtual address * * $	NULL:	no cache match * 		cache	:cache matched */cache_line_t *mmu_cache_search (ARMul_State * state, cache_t * cache_t, ARMword va){	int i;	int set = va_cache_set (va, cache_t);	ARMword tag = va_cache_align (va, cache_t);	cache_line_t *cache;	cache_set_t *cache_set = cache_t->sets + set;	for (i = 0, cache = cache_set->lines; i < cache_t->way; i++, cache++) {		if ((cache->tag & TAG_VALID_FLAG)		    && (tag == va_cache_align (cache->tag, cache_t)))			return cache;	}	return NULL;}/* mmu cache search by set/index * * @state	:ARMul_State * @cache_t	:cache_t to search * @index	:set/index value.  * * $	NULL:	no cache match * 		cache	:cache matched */cache_line_t *mmu_cache_search_by_index (ARMul_State * state, cache_t * cache_t,			   ARMword index){	int way = cache_t->way;	int set_v = index_cache_set (index, cache_t);	int i = 0, index_v = 0;	cache_set_t *set;	while ((way >>= 1) >= 1)		i++;	index_v = index >> (32 - i);	set = cache_t->sets + set_v;	return set->lines + index_v;}/* mmu cache alloc * * @state :ARMul_State * @cache_t	:cache_t to alloc from * @va		:virtual address that require cache alloc, need not cache aligned * @pa		:physical address of va * * $	cache_alloced, always alloc OK */cache_line_t *mmu_cache_alloc (ARMul_State * state, cache_t * cache_t, ARMword va,		 ARMword pa){	cache_line_t *cache;	cache_set_t *set;	int i;	va = va_cache_align (va, cache_t);	pa = va_cache_align (pa, cache_t);	set = &cache_t->sets[va_cache_set (va, cache_t)];	/*robin-round */	cache = &set->lines[set->cycle++];	if (set->cycle == cache_t->way)		set->cycle = 0;	if (cache_t->w_mode == CACHE_WRITE_BACK) {		ARMword t;		/*if cache valid, try to write back */		if (cache->tag & TAG_VALID_FLAG) {			mmu_cache_write_back (state, cache_t, cache);		}		/*read in cache_line */		t = pa;		for (i = 0; i < (cache_t->width >> WORD_SHT);		     i++, t += WORD_SIZE) {			cache->data[i] = mem_read_word (state, t);		}	}	/*store tag and pa */	cache->tag = va | TAG_VALID_FLAG;	cache->pa = pa;	return cache;};/* mmu_cache_write_back write cache data to memory * @state * @cache_t :cache_t of the cache line * @cache : cache line */voidmmu_cache_write_back (ARMul_State * state, cache_t * cache_t,		      cache_line_t * cache){	ARMword pa = cache->pa;	int nw = cache_t->width >> WORD_SHT;	ARMword *data = cache->data;	int i;	int t0, t1, t2;	if ((cache->tag & 1) == 0)		return;	switch (cache->		tag & ~1 & (TAG_FIRST_HALF_DIRTY | TAG_LAST_HALF_DIRTY)) {	case 0:		return;	case TAG_FIRST_HALF_DIRTY:		nw /= 2;		break;	case TAG_LAST_HALF_DIRTY:		nw /= 2;		pa += nw << WORD_SHT;		data += nw;		break;	case TAG_FIRST_HALF_DIRTY | TAG_LAST_HALF_DIRTY:		break;	}	for (i = 0; i < nw; i++, data++, pa += WORD_SIZE)		mem_write_word (state, pa, *data);	cache->tag &= ~(TAG_FIRST_HALF_DIRTY | TAG_LAST_HALF_DIRTY);};/* mmu_cache_clean: clean a cache of va in cache_t * * @state	:ARMul_State * @cache_t	:cache_t to clean * @va		:virtaul address */voidmmu_cache_clean (ARMul_State * state, cache_t * cache_t, ARMword va){	cache_line_t *cache;	cache = mmu_cache_search (state, cache_t, va);	if (cache)		mmu_cache_write_back (state, cache_t, cache);}/* mmu_cache_clean_by_index: clean a cache by set/index format value * * @state	:ARMul_State * @cache_t	:cache_t to clean * @va		:set/index format value */voidmmu_cache_clean_by_index (ARMul_State * state, cache_t * cache_t,			  ARMword index){	cache_line_t *cache;	cache = mmu_cache_search_by_index (state, cache_t, index);	if (cache)		mmu_cache_write_back (state, cache_t, cache);}/* mmu_cache_invalidate : invalidate a cache of va * * @state	:ARMul_State * @cache_t	:cache_t to invalid * @va		:virt_addr to invalid */voidmmu_cache_invalidate (ARMul_State * state, cache_t * cache_t, ARMword va){	cache_line_t *cache;	cache = mmu_cache_search (state, cache_t, va);	if (cache) {		mmu_cache_write_back (state, cache_t, cache);		cache->tag = 0;	}}/* mmu_cache_invalidate_by_index : invalidate a cache by index format * * @state	:ARMul_State * @cache_t	:cache_t to invalid * @index	:set/index data */voidmmu_cache_invalidate_by_index (ARMul_State * state, cache_t * cache_t,			       ARMword index){	cache_line_t *cache;	cache = mmu_cache_search_by_index (state, cache_t, index);	if (cache) {		mmu_cache_write_back (state, cache_t, cache);		cache->tag = 0;	}}/* mmu_cache_invalidate_all * * @state: * @cache_t * */voidmmu_cache_invalidate_all (ARMul_State * state, cache_t * cache_t){	int i, j;	cache_set_t *set;	cache_line_t *cache;	set = cache_t->sets;	for (i = 0; i < cache_t->set; i++, set++) {		cache = set->lines;		for (j = 0; j < cache_t->way; j++, cache++) {			mmu_cache_write_back (state, cache_t, cache);			cache->tag = 0;		}	}};voidmmu_cache_soft_flush (ARMul_State * state, cache_t * cache_t, ARMword pa){	ARMword set, way;	cache_line_t *cache;	pa = (pa / cache_t->width);	way = pa & (cache_t->way - 1);	set = (pa / cache_t->way) & (cache_t->set - 1);	cache = &cache_t->sets[set].lines[way];	mmu_cache_write_back (state, cache_t, cache);	cache->tag = 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -