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

Subversion Repositories or1k

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

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 goes with this. I need to
add all sorts of other abstract entities. Currently we have
only memory. */
 
#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"
 
extern unsigned long reg[];
 
/* This is an abstract+physical memory array rather than only physical
   memory array */
struct mem_entry mem[MEMORY_LEN];
 
/* Pointer to memory area descriptions that are assigned to individual
   peripheral devices. */
struct dev_memarea *dev_list;
 
void dumpmemory(unsigned int from, unsigned int to)
{
	unsigned int i, done = 0;
	struct label_entry *tmp;
 
	for(i = from; i < to && i < (MEMORY_START + MEMORY_LEN); i++) {
		if (mem[i].insn) {
			printf("\n%.8x:  ", i);
			tmp = mem[i].label;
			for(; tmp; tmp = tmp->next)
				printf("%s%s\n", tmp->name, LABELEND_CHAR);
			if (mem[i].insn)
				printf("\t\t%s\t%s", mem[i].insn->insn, mem[i].insn->op1);
			if (strlen(mem[i].insn->op2))
				printf("%s%s", OPERAND_DELIM, mem[i].insn->op2);
			if (strlen(mem[i].insn->op3))
				printf("%s%s", OPERAND_DELIM, mem[i].insn->op3);
			if (strlen(mem[i].insn->op4))
				printf("%s%s", OPERAND_DELIM, mem[i].insn->op4);
			i += (insn_len(mem[i].insn->insn) - 1);
		} else
		{
			if (i % 8 == 0)
				printf("\n%.8x:  ", i);
 
			/* don't print ascii chars below 0x20. */
			if (mem[i].data < 0x20)
				printf("0x%.2x     ", (unsigned char)mem[i].data);
			else
				printf("0x%.2x'%c'  ", (unsigned char)mem[i].data, mem[i].data);
 
		}
		done = 1;
	}
 
	if (done)
		return;
 
	for(i = from; i < to; i++) {
		if (i % 8 == 0)
			printf("\n%.8x:  ", i);
 
		/* don't print ascii chars below 0x20. */
		if (eval_mem32(i) < 0x20)
			printf("0x%.2x     ", (unsigned char)eval_mem32(i));
		else
			printf("0x%.2x'%c'  ", (unsigned char)eval_mem32(i), (unsigned char)eval_mem32(i));
 
	}
}
 
/* 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;
	struct label_entry *tmp;
 
	if (plus = strchr(label, '+')) {
		*plus = '\0';
		positive_offset = atoi(++plus);
	}
 
	if (minus = strchr(label, '-')) {
		*minus = '\0';
		negative_offset = atoi(++minus);
	}
 
	for(i = 0; i < (MEMORY_START + MEMORY_LEN); i++) {
		tmp = mem[i].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);
				return i+positive_offset-negative_offset;
			}
  	}
 
        printf("\nINTERNAL ERROR: undefined label %s\n", label);
        cont_run = 0;
        return 0;
 
}
 
/* Calls MMU 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 == VIRTUAL) {
		dc_simulate_read(virtaddr);
		return dmmu_translate(virtaddr);
	}
	else if (config.dc.tagtype == PHYSICAL) {
		unsigned long phyaddr = dmmu_translate(virtaddr);
		dc_simulate_read(phyaddr);
		return phyaddr;
	}
	else {
		printf("INTERNAL ERROR: Unknown data cache type.\n");
		cont_run = 0;
	}
 
	return -1;
}
 
/* Calls MMU 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 == 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 baseaddr, unsigned long size, unsigned char (readfunc)(unsigned long), void (writefunc)(unsigned long, unsigned char))
{
	struct dev_memarea **pptmp;
 
	/* Go to the end of the list. */
	for(pptmp = &dev_list; *pptmp; pptmp = &(*pptmp)->next);
 
	*pptmp = (struct dev_memarea *)malloc(sizeof(struct dev_memarea));
	(*pptmp)->baseaddr = baseaddr;
	(*pptmp)->size = size;
	(*pptmp)->readfunc = readfunc;
	(*pptmp)->writefunc = writefunc;
	(*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->baseaddr &&
		    addr < (ptmp->baseaddr + ptmp->size))
			return ptmp;
	return NULL;
}
 
/* Returns 32-bit values from mem array. Big endian version. */
unsigned long eval_mem32(unsigned long memaddr)
{
	unsigned long temp;
	struct dev_memarea *dev;
 
	slp_checkaccess(memaddr, SLP_MEMREAD);
	memaddr = simulate_dc_mmu_load(memaddr);
 
	if (memaddr < (MEMORY_START + MEMORY_LEN)) {
		temp = mem[memaddr].data << 24;
		temp +=	mem[memaddr + 1].data << 16;
		temp +=	mem[memaddr + 2].data << 8;
		temp +=	mem[memaddr + 3].data;
	} else if (dev = verify_memoryarea(memaddr)) {
		temp = dev->readfunc(memaddr);
	} 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)
{
	unsigned short temp;
 
	memaddr = simulate_dc_mmu_load(memaddr);
 
	if (memaddr < (MEMORY_START + MEMORY_LEN)) {
		temp = ((unsigned short)(mem[memaddr].data << 8) & 0xff00);
		temp +=	((unsigned short)mem[memaddr + 1].data & 0x00ff);
	} 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)
{	
	memaddr = simulate_dc_mmu_load(memaddr);
 
	if (memaddr < (MEMORY_START + MEMORY_LEN)) {
		return (unsigned char)mem[memaddr].data;
	} else {
		printf("EXCEPTION: read out of memory (8-bit access to %.8lx)\n", memaddr);
		cont_run = 0;
		return 0;
	}
}
 
/* Set mem, 32-bit. Big endian version. */
 
void set_mem32(unsigned long memaddr, unsigned long value)
{
	struct dev_memarea *dev;
 
	slp_checkaccess(memaddr, SLP_MEMWRITE);
	memaddr = simulate_dc_mmu_store(memaddr);
 
	if (memaddr < (MEMORY_START + MEMORY_LEN)) {
		mem[memaddr].data = (value >> 24);
		mem[memaddr + 1].data = (char)(value >> 16);
		mem[memaddr + 2].data = (char)(value >> 8);
		mem[memaddr + 3].data = (char)(value);
	} else if (dev = verify_memoryarea(memaddr)) {
		dev->writefunc(memaddr, value);
	} 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)
{
	memaddr = simulate_dc_mmu_store(memaddr);
 
	if (memaddr < (MEMORY_START + MEMORY_LEN)) {
		mem[memaddr].data = (value >> 8);
		mem[memaddr + 1].data = (char)(value);
	} 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)
{
	memaddr = simulate_dc_mmu_store(memaddr);
 
	if (memaddr < (MEMORY_START + MEMORY_LEN)) {
		mem[memaddr].data = value;
	} else {
		printf("EXCEPTION: write out of memory (8-bit access to %.8lx)\n", memaddr);
		cont_run = 0;
	}
 
	return;
}
 
/* Reports interrupt to architecture specific interrupt mechanism. */
void report_interrupt()
{
	printf("Interrupt reported.\n");
	if (mfspr(SPR_SR) & SPR_SR_EIR)
		except_handle(EXCEPT_EXTINT, 0);
}
 

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.