OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [tags/] [nog_patch_42/] [or1ksim/] [cpu/] [common/] [abstract.c] - Rev 235

Go to most recent revision | Compare with Previous | Blame | View Log

/* abstract.c -- Abstract entities
   Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
 
This file is part of OpenRISC 1000 Architectural Simulator.
 
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
/* Abstract memory and routines that go with this. I need to
add all sorts of other abstract entities. Currently we have
only memory. */
 
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
 
#include "config.h"
#include "sim-config.h"
 
#include "parse.h"
#include "abstract.h"
#include "arch.h"
#include "trace.h"
#include "execute.h"
#include "sprs.h"
#include "stats.h"
#include "except.h"
#include "debug_unit.h"
#include "opcode/or32.h"
 
extern unsigned long reg[];
extern char *disassembled;
 
/* This is an abstract+physical memory array rather than only physical
   memory array */
static struct mem_entry *simmem;
 
/* Pointer to memory area descriptions that are assigned to individual
   peripheral devices. */
struct dev_memarea *dev_list;
 
/* Temporary variable to increase speed.  */
struct dev_memarea *cur_area;
 
void dumpmemory(unsigned int from, unsigned int to, int disasm)
{
	unsigned int i, j;
	struct label_entry *tmp;
	int breakpoint = 0;
	int ilen = disasm ? 4 : 16;
 
	for(i = from; i < to; i += ilen) {
		for (j = 0; j < ilen;) {
			int data = -1;
			if (!disasm) {
				tmp = NULL;
				if (verify_memoryarea(i+j)) {
					struct mem_entry *entry;
					if (cur_area->getentry && (entry = cur_area->getentry(i+j)))
						for(tmp = entry->label; tmp; tmp = tmp->next)
							printf(" %s%s", tmp->name, LABELEND_CHAR);
					printf("%02x ", data = evalsim_mem8(i+j));
				} else printf("XX ");	 
				j++;		 
			} else {
				int breakpoint;
				unsigned int _insn = eval_mem32(i, &breakpoint);
				int index = insn_decode (_insn);
				int len = insn_len (index);
 
				tmp = NULL;
				if (verify_memoryarea(i+j)) {
					struct mem_entry *entry;
					if (cur_area->getentry && (entry = cur_area->getentry(i+j)))
						tmp = entry->label;
 
					for(; tmp; tmp = tmp->next)
						printf(" %s%s", tmp->name, LABELEND_CHAR);					
					printf("%.8x:	 ", i);
 
					printf("%08x		", (unsigned char)_insn);
					if (index >= 0) {
						disassemble_insn (_insn);
						printf(" %s", disassembled);
					} else
						printf("<invalid>");
				} else printf("XXXXXXXX");
				j += len;
			}			 
		}
	}
}
 
/* Searches mem array for a particular label and returns label's address.
   If label does not exist, returns 0. */
 
unsigned long eval_label(char *label)
{
	int i;
	char *plus;
	char *minus;
	int positive_offset = 0;
	int negative_offset = 0;
 
	if (plus = strchr(label, '+')) {
		*plus = '\0';
		positive_offset = atoi(++plus);
	}
 
	if (minus = strchr(label, '-')) {
		*minus = '\0';
		negative_offset = atoi(++minus);
	}
	for (cur_area = dev_list; cur_area; cur_area = cur_area->next) {
		for(i = 0; i < cur_area->size; i++) if (cur_area->getentry) {
			int mi = i + cur_area->start;
			struct mem_entry *entry = cur_area->getentry(mi);
			if (entry) {
				struct label_entry *tmp = entry->label;
				for(; tmp; tmp = tmp->next)
					if (strcmp(label, tmp->name) == 0) {
						debug("eval_label(%s) => 0x%x\n", label, i + positive_offset - negative_offset + cur_area->start);
						return i + positive_offset - negative_offset + cur_area->start;
					}
			}
		}
	}
 
	printf("\nINTERNAL ERROR: undefined label %s\n", label);
	cont_run = 0;
	return 0;
}
 
/* Calls IMMU translation routines before simulating insn
cache for virtually indexed insn cache or after simulating insn cache
for physically indexed insn cache. It returns physical address. */
 
unsigned long simulate_ic_mmu_fetch(unsigned long virtaddr)
{
	if (config.ic.tagtype == NONE)
		return virtaddr;
	else
		if (config.ic.tagtype == VIRTUAL) {
			ic_simulate_fetch(virtaddr);
			return immu_translate(virtaddr);
		}
		else if (config.dc.tagtype == PHYSICAL) {
			unsigned long phyaddr = immu_translate(virtaddr);
			ic_simulate_fetch(phyaddr);
			return phyaddr;
		}
		else {
			printf("INTERNAL ERROR: Unknown insn cache type.\n");
			cont_run = 0;
		}
 
	return -1;
}
 
/* Calls DMMU translation routines (load cycles) before simulating data
	 cache for virtually indexed data cache or after simulating data cache
	 for physically indexed data cache. It returns physical address. */
 
unsigned long simulate_dc_mmu_load(unsigned long virtaddr)
{
	if (config.dc.tagtype == NONE)
		return virtaddr;
	else
	if (config.ic.tagtype == VIRTUAL) {
		ic_simulate_fetch(virtaddr);
		return immu_translate(virtaddr);
	}
	else if (config.dc.tagtype == PHYSICAL) {
		unsigned long phyaddr = immu_translate(virtaddr);
		ic_simulate_fetch(phyaddr);
		return phyaddr;
	}
	else {
		printf("INTERNAL ERROR: Unknown insn cache type.\n");
		cont_run = 0;
	}
 
	return -1;
}
 
/* Calls DMMU translation routines (store cycles) before simulating data
cache for virtually indexed data cache or after simulating data cache
for physically indexed data cache. It returns physical address. */
 
unsigned long simulate_dc_mmu_store(unsigned long virtaddr)
{
	if (config.dc.tagtype == NONE)
		return virtaddr;
	else
	if (config.dc.tagtype == VIRTUAL) {
		dc_simulate_write(virtaddr);
		return dmmu_translate(virtaddr);
	}
	else if (config.dc.tagtype == PHYSICAL) {
		unsigned long phyaddr = dmmu_translate(virtaddr);
		dc_simulate_write(phyaddr);
		return phyaddr;
	}
	else {
		printf("INTERNAL ERROR: Unknown data cache type.\n");
		cont_run = 0;
	}
 
	return -1;
}
 
/* Register read and write function for a memory area (used by peripheral
   devices like 16450 UART etc.) */
void register_memoryarea(unsigned long start, unsigned long size,
												 unsigned granularity,
												 unsigned long (readfunc)(unsigned long),
												 void (writefunc)(unsigned long, unsigned long),
												 struct mem_entry *(getentry)(unsigned long))
{
	struct dev_memarea **pptmp;
 
	/* Go to the end of the list. */
	for(pptmp = &dev_list; *pptmp; pptmp = &(*pptmp)->next);
 
	cur_area = *pptmp = (struct dev_memarea *)malloc(sizeof(struct dev_memarea));
	(*pptmp)->start = start;
	(*pptmp)->size = size;
	(*pptmp)->end = start + size;
	(*pptmp)->granularity = granularity;
	(*pptmp)->readfunc = readfunc;
	(*pptmp)->writefunc = writefunc;
	(*pptmp)->getentry = getentry;
	(*pptmp)->next = NULL;
 
	return;
}
 
/* Check if access is to registered area of memory. */
struct dev_memarea *verify_memoryarea(unsigned long addr)
{
	struct dev_memarea *ptmp;
 
	/* Check list of registered devices. */
	for(ptmp = dev_list; ptmp; ptmp = ptmp->next)
		if (addr >= ptmp->start &&
				addr < (ptmp->end))
			return cur_area = ptmp;
	return cur_area = NULL;
}
 
/* Returns 32-bit values from mem array. Big endian version. */
unsigned long eval_mem32(unsigned long memaddr,int* breakpoint)
{
 
	unsigned long temp;
	struct dev_memarea *dev;
 
	slp_checkaccess(memaddr, SLP_MEMREAD);
	memaddr = simulate_dc_mmu_load(memaddr);
	*breakpoint += CheckDebugUnit(DebugLoadAddress,memaddr); /* 28/05/01 CZ */
	temp = evalsim_mem32(memaddr);
	*breakpoint += CheckDebugUnit(DebugLoadData,temp);	/* MM170901 */
	return temp;
}
 
unsigned long evalsim_mem32(unsigned long memaddr)
{
	unsigned long temp;
 
	if (verify_memoryarea(memaddr)) {
		switch(cur_area->granularity) {
		case 1:
			temp = cur_area->readfunc(memaddr) << 24;
			temp |= cur_area->readfunc(memaddr + 1) << 16;
			temp |= cur_area->readfunc(memaddr + 2) << 8;
			temp |= cur_area->readfunc(memaddr + 3);
			break;
		case 2:
			temp = cur_area->readfunc(memaddr) << 16;
			temp |= cur_area->readfunc(memaddr + 2);
			break;
		case 4:
			temp = cur_area->readfunc(memaddr);
			break;
		} 
	} else {
		printf("EXCEPTION: read out of memory (32-bit access to %.8lx)\n", memaddr);
		cont_run = 0;
		temp = 0;
	}
	return temp;
}
 
/* Returns 16-bit values from mem array. Big endian version. */
 
unsigned short eval_mem16(unsigned long memaddr,int* breakpoint)
{
	unsigned short temp;
	memaddr = simulate_dc_mmu_load(memaddr);
	*breakpoint += CheckDebugUnit(DebugLoadAddress,memaddr); /* 28/05/01 CZ */
 
	temp = evalsim_mem16(memaddr);
	*breakpoint += CheckDebugUnit(DebugLoadData,temp);	/* MM170901 */
	return temp;
}
 
unsigned short evalsim_mem16(unsigned long memaddr)
{
	unsigned short temp;
 
	if (verify_memoryarea(memaddr)) {
		switch(cur_area->granularity) {
		case 1:
			temp = cur_area->readfunc(memaddr) << 8;
			temp |= cur_area->readfunc(memaddr + 1);
			break;
		case 2:
			temp = cur_area->readfunc(memaddr);
			break;
		case 4:
			printf("EXCEPTION: read 16-bit value from 32-bit region (address 0x%08lX)\n", cur_area->granularity * 8, memaddr);
			cont_run = 0;
			break;
		} 
	} else {
		printf("EXCEPTION: read out of memory (16-bit access to %.8lx)\n", memaddr);
		cont_run = 0;
		temp = 0;
	}
	return temp;
}
 
 
/* Returns 8-bit values from mem array. */
 
unsigned char eval_mem8(unsigned long memaddr,int* breakpoint)
{
	unsigned char temp;
	memaddr = simulate_dc_mmu_load(memaddr);
	*breakpoint += CheckDebugUnit(DebugLoadAddress,memaddr);	/* 28/05/01 CZ */
 
	temp = evalsim_mem8(memaddr);
	*breakpoint += CheckDebugUnit(DebugLoadData,temp);	/* MM170901 */
	return temp;
}
 
unsigned char evalsim_mem8(unsigned long memaddr)
{
	unsigned char temp;
 
	if (verify_memoryarea(memaddr)) {
		switch(cur_area->granularity) {
		case 1:
			temp = cur_area->readfunc(memaddr);
			temp |= cur_area->readfunc(memaddr + 1) << 16;
			temp |= cur_area->readfunc(memaddr + 2) << 8;
			temp |= cur_area->readfunc(memaddr + 3);
			break;
		case 2:
		case 4:
			printf("EXCEPTION: read 8-bit value from %u-bit region (address 0x%08lX)\n", cur_area->granularity * 8, memaddr);
			cont_run = 0;
			break;
		} 
	} else {
		printf("EXCEPTION: read out of memory (8-bit access to %.8lx)\n", memaddr);
		cont_run = 0;
		temp = 0;
	}
	return temp;
}
 
/* Set mem, 32-bit. Big endian version. */
 
void set_mem32(unsigned long memaddr, unsigned long value,int* breakpoint)
{
	slp_checkaccess(memaddr, SLP_MEMWRITE);
	memaddr = simulate_dc_mmu_store(memaddr);
 
	*breakpoint += CheckDebugUnit(DebugStoreAddress,memaddr);	 /* 28/05/01 CZ */
	*breakpoint += CheckDebugUnit(DebugStoreData,value);
 
	setsim_mem32(memaddr, value);
 
	return;
}
 
void setsim_mem32(unsigned long memaddr, unsigned long value)
{
	struct dev_memarea *dev;
 
	if (verify_memoryarea(memaddr)) {
		switch(cur_area->granularity) {
		case 1:
			cur_area->writefunc(memaddr, (value >> 24) & 0xFF);
			cur_area->writefunc(memaddr + 1, (value >> 16) & 0xFF);
			cur_area->writefunc(memaddr + 2, (value >> 8) & 0xFF);
			cur_area->writefunc(memaddr + 3, value & 0xFF);
			break;
		case 2:
			cur_area->writefunc(memaddr, (value >> 16) & 0xFFFF);
			cur_area->writefunc(memaddr + 2, value & 0xFFFF);
			break;
		case 4:
			cur_area->writefunc(memaddr, value);
			break;
		} 
	} else {
		printf("EXCEPTION: write out of memory (32-bit access to %.8lx)\n", memaddr);
		cont_run = 0;
	}
 
	return;
}
 
/* Set mem, 16-bit. Big endian version. */
 
void set_mem16(unsigned long memaddr, unsigned short value,int* breakpoint)
{
	memaddr = simulate_dc_mmu_store(memaddr);
 
	*breakpoint += CheckDebugUnit(DebugStoreAddress,memaddr);	 /* 28/05/01 CZ */
	*breakpoint += CheckDebugUnit(DebugStoreData,value);
 
	setsim_mem16(memaddr, value);
 
	return;
}
 
void setsim_mem16(unsigned long memaddr, unsigned short value)
{
	if (verify_memoryarea(memaddr)) {
		switch(cur_area->granularity) {
		case 1:
			cur_area->writefunc(memaddr, (value >> 8) & 0xFF);
			cur_area->writefunc(memaddr + 1, value & 0xFF);
			break;
		case 2:
			cur_area->writefunc(memaddr, (value >> 16) & 0xFFFF);
			break;
		case 4:
			printf("EXCEPTION: write 16-bit value to 32-bit region (address 0x%08lX)\n", memaddr);
			cont_run = 0;
			break;
		} 
	} else {
		printf("EXCEPTION: write out of memory (16-bit access to %.8lx)\n", memaddr);
		cont_run = 0;
	}
 
	return;
}
 
/* Set mem, 8-bit. */
 
void set_mem8(unsigned long memaddr, unsigned char value,int* breakpoint)
{
	memaddr = simulate_dc_mmu_store(memaddr);
 
	*breakpoint += CheckDebugUnit(DebugStoreAddress,memaddr);	 /* 28/05/01 CZ */
	*breakpoint += CheckDebugUnit(DebugStoreData,value);
 
	setsim_mem8(memaddr, value);
 
	return;
}
 
void setsim_mem8(unsigned long memaddr, unsigned char value)
{
	if (verify_memoryarea(memaddr)) {
		if (cur_area->granularity == 1)
			cur_area->writefunc(memaddr, value);
		else {
			printf("EXCEPTION: write 8-bit value to %u-bit region (address 0x%08lX)\n", cur_area->granularity * 8, memaddr);
			cont_run = 0;
		}
	} else {
		printf("EXCEPTION: write out of memory (8-bit access to %.8lx)\n", memaddr);
		cont_run = 0;
	}
 
	return;
}
 
unsigned long simmem_read_byte(unsigned long addr) {
	return simmem[cur_area->misc + addr - cur_area->start].data;
}
 
void simmem_write_byte(unsigned long addr, unsigned long value) {
	simmem[cur_area->misc + addr - cur_area->start].data = (unsigned char)value;
}
 
struct mem_entry * simmem_getentry(unsigned long addr) {
	return &simmem[cur_area->misc + addr - cur_area->start];
}
 
void sim_read_memory_table (char *filename)
{
	FILE *f;
	unsigned long memory_needed = 0;
	char *home = getenv("HOME");
	char ctmp[256];
	int local = 1;
	sprintf(ctmp, "%s/.or1k/%s", home, filename);
	if ((f = fopen (filename, "rt")) != NULL
			|| home != NULL && !(local = 0) && (f = fopen (ctmp, "rt")) != NULL) {
		unsigned long start, length;
		char type[100];
		printf ("Reading memory table from '%s':\n", local ? filename : ctmp);
		while (fscanf (f, "%08x %08x %s\n", &start, &length, &type) == 3) {
			printf ("%08X %08X (%i KB): %s\n", start, length, length >> 10, type);
			register_memoryarea(start, length, 1, &simmem_read_byte, &simmem_write_byte, &simmem_getentry);
			cur_area->misc = memory_needed;
			memory_needed += DEFAULT_MEMORY_LEN;
		}
		fclose (f);
		printf ("\n");
	} else {
		fprintf (stderr, "Cannot read memory table from '%s',\nneither '%s', assuming standard configuration.\n", filename, ctmp);
		register_memoryarea(DEFAULT_MEMORY_START, DEFAULT_MEMORY_LEN, 1, &simmem_read_byte, &simmem_write_byte, &simmem_getentry);
		memory_needed += DEFAULT_MEMORY_LEN;
	}
 
	simmem = (struct mem_entry *) malloc (sizeof (struct mem_entry) * memory_needed);
}
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.