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

Subversion Repositories or1k

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 234 to Rev 235
    Reverse comparison

Rev 234 → Rev 235

/trunk/or1ksim/cpu/common/abstract.c
56,51 → 56,51
 
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;
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)) {
if (cur_area->getentry)
tmp = cur_area->getentry(i+j)->label;
for(; tmp; tmp = tmp->next)
printf(" %s%s", tmp->name, LABELEND_CHAR);
printf("%02x ", data = (unsigned char)cur_area->readfunc(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)) {
if (cur_area->getentry)
tmp = cur_area->getentry(i+j)->label;
for(; tmp; tmp = tmp->next)
printf(" %s%s", tmp->name, LABELEND_CHAR);
printf("%.8x: ", i);
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;
}
}
}
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.
109,7 → 109,7
unsigned long eval_label(char *label)
{
int i;
char *plus;
char *plus;
char *minus;
int positive_offset = 0;
int negative_offset = 0;
123,24 → 123,24
*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;
}
}
}
}
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;
printf("\nINTERNAL ERROR: undefined label %s\n", label);
cont_run = 0;
return 0;
}
 
/* Calls IMMU translation routines before simulating insn
152,26 → 152,26
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;
}
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. */
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)
{
178,17 → 178,17
if (config.dc.tagtype == NONE)
return virtaddr;
else
if (config.dc.tagtype == VIRTUAL) {
dc_simulate_read(virtaddr);
return dmmu_translate(virtaddr);
if (config.ic.tagtype == VIRTUAL) {
ic_simulate_fetch(virtaddr);
return immu_translate(virtaddr);
}
else if (config.dc.tagtype == PHYSICAL) {
unsigned long phyaddr = dmmu_translate(virtaddr);
dc_simulate_read(phyaddr);
unsigned long phyaddr = immu_translate(virtaddr);
ic_simulate_fetch(phyaddr);
return phyaddr;
}
else {
printf("INTERNAL ERROR: Unknown data cache type.\n");
printf("INTERNAL ERROR: Unknown insn cache type.\n");
cont_run = 0;
}
 
223,8 → 223,11
 
/* 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 char (readfunc)(unsigned long),
void (writefunc)(unsigned long, unsigned char), struct mem_entry *(getentry)(unsigned long))
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;
 
235,6 → 238,7
(*pptmp)->start = start;
(*pptmp)->size = size;
(*pptmp)->end = start + size;
(*pptmp)->granularity = granularity;
(*pptmp)->readfunc = readfunc;
(*pptmp)->writefunc = writefunc;
(*pptmp)->getentry = getentry;
251,7 → 255,7
/* Check list of registered devices. */
for(ptmp = dev_list; ptmp; ptmp = ptmp->next)
if (addr >= ptmp->start &&
addr < (ptmp->end))
addr < (ptmp->end))
return cur_area = ptmp;
return cur_area = NULL;
}
260,14 → 264,14
unsigned long eval_mem32(unsigned long memaddr,int* breakpoint)
{
 
unsigned long temp;
struct dev_memarea *dev;
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 */
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;
}
 
276,10 → 280,21
unsigned long temp;
 
if (verify_memoryarea(memaddr)) {
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);
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;
292,12 → 307,12
 
unsigned short eval_mem16(unsigned long memaddr,int* breakpoint)
{
unsigned short temp;
unsigned short temp;
memaddr = simulate_dc_mmu_load(memaddr);
*breakpoint += CheckDebugUnit(DebugLoadAddress,memaddr); /* 28/05/01 CZ */
*breakpoint += CheckDebugUnit(DebugLoadAddress,memaddr); /* 28/05/01 CZ */
 
temp = evalsim_mem16(memaddr);
*breakpoint += CheckDebugUnit(DebugLoadData,temp); /* MM170901 */
*breakpoint += CheckDebugUnit(DebugLoadData,temp); /* MM170901 */
return temp;
}
 
306,8 → 321,19
unsigned short temp;
 
if (verify_memoryarea(memaddr)) {
temp = cur_area->readfunc(memaddr) << 8;
temp |= cur_area->readfunc(memaddr + 1);
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;
321,21 → 347,33
 
unsigned char eval_mem8(unsigned long memaddr,int* breakpoint)
{
unsigned char temp;
unsigned char temp;
memaddr = simulate_dc_mmu_load(memaddr);
*breakpoint += CheckDebugUnit(DebugLoadAddress,memaddr); /* 28/05/01 CZ */
*breakpoint += CheckDebugUnit(DebugLoadAddress,memaddr); /* 28/05/01 CZ */
 
temp = evalsim_mem8(memaddr);
*breakpoint += CheckDebugUnit(DebugLoadData,temp); /* MM170901 */
*breakpoint += CheckDebugUnit(DebugLoadData,temp); /* MM170901 */
return temp;
}
 
unsigned char evalsim_mem8(unsigned long memaddr)
{
unsigned char temp;
unsigned char temp;
 
if (verify_memoryarea(memaddr)) {
temp = cur_area->readfunc(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;
348,15 → 386,15
 
void set_mem32(unsigned long memaddr, unsigned long value,int* breakpoint)
{
slp_checkaccess(memaddr, SLP_MEMWRITE);
memaddr = simulate_dc_mmu_store(memaddr);
slp_checkaccess(memaddr, SLP_MEMWRITE);
memaddr = simulate_dc_mmu_store(memaddr);
 
*breakpoint += CheckDebugUnit(DebugStoreAddress,memaddr); /* 28/05/01 CZ */
*breakpoint += CheckDebugUnit(DebugStoreData,value);
*breakpoint += CheckDebugUnit(DebugStoreAddress,memaddr); /* 28/05/01 CZ */
*breakpoint += CheckDebugUnit(DebugStoreData,value);
 
setsim_mem32(memaddr, value);
setsim_mem32(memaddr, value);
 
return;
return;
}
 
void setsim_mem32(unsigned long memaddr, unsigned long value)
363,11 → 401,22
{
struct dev_memarea *dev;
 
if (verify_memoryarea(memaddr)) {
cur_area->writefunc(memaddr, value >> 24);
cur_area->writefunc(memaddr + 1, (unsigned char)(value >> 16));
cur_area->writefunc(memaddr + 2, (unsigned char)(value >> 8));
cur_area->writefunc(memaddr + 3, (unsigned char)value);
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;
380,27 → 429,38
 
void set_mem16(unsigned long memaddr, unsigned short value,int* breakpoint)
{
memaddr = simulate_dc_mmu_store(memaddr);
memaddr = simulate_dc_mmu_store(memaddr);
 
*breakpoint += CheckDebugUnit(DebugStoreAddress,memaddr); /* 28/05/01 CZ */
*breakpoint += CheckDebugUnit(DebugStoreData,value);
*breakpoint += CheckDebugUnit(DebugStoreAddress,memaddr); /* 28/05/01 CZ */
*breakpoint += CheckDebugUnit(DebugStoreData,value);
 
setsim_mem16(memaddr, value);
setsim_mem16(memaddr, value);
 
return;
return;
}
 
void setsim_mem16(unsigned long memaddr, unsigned short value)
{
if (verify_memoryarea(memaddr)) {
cur_area->writefunc(memaddr, (unsigned char) (value >> 8));
cur_area->writefunc(memaddr + 1, (unsigned char)value);
} else {
printf("EXCEPTION: write out of memory (16-bit access to %.8lx)\n", memaddr);
cont_run = 0;
}
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;
return;
}
 
/* Set mem, 8-bit. */
407,20 → 467,25
 
void set_mem8(unsigned long memaddr, unsigned char value,int* breakpoint)
{
memaddr = simulate_dc_mmu_store(memaddr);
memaddr = simulate_dc_mmu_store(memaddr);
 
*breakpoint += CheckDebugUnit(DebugStoreAddress,memaddr); /* 28/05/01 CZ */
*breakpoint += CheckDebugUnit(DebugStoreData,value);
*breakpoint += CheckDebugUnit(DebugStoreAddress,memaddr); /* 28/05/01 CZ */
*breakpoint += CheckDebugUnit(DebugStoreData,value);
 
setsim_mem8(memaddr, value);
setsim_mem8(memaddr, value);
 
return;
return;
}
 
void setsim_mem8(unsigned long memaddr, unsigned char value)
{
if (verify_memoryarea(memaddr)) {
cur_area->writefunc(memaddr, (unsigned char)value);
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;
429,44 → 494,44
return;
}
 
unsigned char simmem_readfunc(unsigned long addr) {
return simmem[cur_area->misc + addr - cur_area->start].data;
unsigned long simmem_read_byte(unsigned long addr) {
return simmem[cur_area->misc + addr - cur_area->start].data;
}
 
void simmem_writefunc(unsigned long addr, unsigned char value) {
simmem[cur_area->misc + addr - cur_area->start].data = value;
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];
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, &simmem_readfunc, &simmem_writefunc, &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, &simmem_readfunc, &simmem_writefunc, &simmem_getentry);
memory_needed += DEFAULT_MEMORY_LEN;
}
simmem = (struct mem_entry *) malloc (sizeof (struct mem_entry) * memory_needed);
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);
}
/trunk/or1ksim/cpu/common/abstract.h
60,8 → 60,9
unsigned long start;
unsigned long end;
unsigned long size;
unsigned char (*readfunc)(unsigned long);
void (*writefunc)(unsigned long, unsigned char);
unsigned long granularity; /* how many bytes read/write accepts: 1/2/4 */
unsigned long (*readfunc)(unsigned long);
void (*writefunc)(unsigned long, unsigned long);
struct mem_entry* (*getentry) (unsigned long);
/* private data */
unsigned long misc;
91,8 → 92,11
 
/* 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 char (readfunc)(unsigned long),
void (writefunc)(unsigned long, unsigned char), struct mem_entry *(getentry)(unsigned long));
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));
/* Check if access is to registered area of memory. */
struct dev_memarea *verify_memoryarea(unsigned long addr);
/* Temporary variable to increase speed. */
/trunk/or1ksim/peripheral/16450.c
31,6 → 31,7
#include <stdio.h>
#include <string.h>
 
#include "abstract.h"
#include "16450.h"
#include "sim-config.h"
#include "pic.h"
61,11 → 62,11
}
 
/* Set a specific UART register with value. */
void uart_write(unsigned long addr, unsigned long value)
void uart_write8(unsigned long addr, unsigned char value)
{
int chipsel;
debug("uart_write(%x,%x)\n", addr, (value >> 24));
debug("uart_write8(%x,%02x)\n", addr, (unsigned)value);
for(chipsel = 0; chipsel < NR_UARTS; chipsel++)
if ((addr & ~(UART_ADDR_SPACE-1)) == uarts[chipsel].baseaddr)
76,13 → 77,13
if (uarts[chipsel].regs.lcr & UART_LCR_DLAB) {
switch (addr % UART_ADDR_SPACE) {
case UART_DLL:
uarts[chipsel].regs.dll = (value >> 24);
uarts[chipsel].regs.dll = value;
break;
case UART_DLH:
uarts[chipsel].regs.dlh = (value >> 24);
uarts[chipsel].regs.dlh = value;
break;
case UART_LCR:
uarts[chipsel].regs.lcr = (value >> 24) & UART_VALID_LCR;
uarts[chipsel].regs.lcr = value & UART_VALID_LCR;
break;
default:
debug("write out of range (addr %x, DLAB=1)\n", addr);
93,7 → 94,7
switch (addr % UART_ADDR_SPACE) {
case UART_TXBUF:
uarts[chipsel].regs.txbuf = (value >> 24);
uarts[chipsel].regs.txbuf = value;
uarts[chipsel].istat.txbuf = FULL;
uarts[chipsel].regs.lsr &= ~UART_LSR_TXBUFE;
uarts[chipsel].regs.lsr &= ~UART_LSR_TXSERE;
100,16 → 101,16
uarts[chipsel].istat.thre_int = 0;
break;
case UART_IER:
uarts[chipsel].regs.ier = (value >> 24) & UART_VALID_IER;
uarts[chipsel].regs.ier = value & UART_VALID_IER;
break;
case UART_LCR:
uarts[chipsel].regs.lcr = (value >> 24) & UART_VALID_LCR;
uarts[chipsel].regs.lcr = value & UART_VALID_LCR;
break;
case UART_MCR:
uarts[chipsel].regs.mcr = (value >> 24) & UART_VALID_MCR;
uarts[chipsel].regs.mcr = value & UART_VALID_MCR;
break;
case UART_SCR:
uarts[chipsel].regs.scr = (value >> 24);
uarts[chipsel].regs.scr = value;
break;
default:
debug("write out of range (addr %x)\n", addr);
119,12 → 120,12
}
 
/* Read a specific UART register. */
unsigned long uart_read(unsigned long addr)
unsigned char uart_read8(unsigned long addr)
{
unsigned char value = 0;
int chipsel;
debug("uart_read(%x)\n", addr);
debug("uart_read8(%x)\n", addr);
for(chipsel = 0; chipsel < NR_UARTS; chipsel++)
if ((addr & ~(UART_ADDR_SPACE-1)) == uarts[chipsel].baseaddr)
143,7 → 144,7
default:
debug("read out of range (addr %x, DLAB=1)\n", addr);
}
return (value << 24);
return value;
}
switch (addr % UART_ADDR_SPACE) {
181,7 → 182,7
default:
debug("read out of range (addr %x)\n", addr);
}
return (value << 24);
return value;
}
 
/* Reset. It initializes all registers of all UART devices to zero values,
189,27 → 190,27
space. */
void uart_reset()
{
int i;
int i;
printf("Resetting %u UART(s).\n", NR_UARTS);
memset(uarts, 0, sizeof(uarts));
printf("Resetting %u UART(s).\n", NR_UARTS);
memset(uarts, 0, sizeof(uarts));
for(i = 0; i < NR_UARTS; i++)
if (config.uarts[i].txfile) { /* MM: Try to create stream. */
if (!(uarts[i].rxfs = fopen(config.uarts[i].rxfile, "r"))
&& !(uarts[i].rxfs = fopen(config.uarts[i].rxfile, "r+"))) {
printf("UART%d has problems with RX file stream.\n", i);
continue;
}
uarts[i].txfs = fopen(config.uarts[i].txfile, "a");
uarts[i].baseaddr = config.uarts[i].baseaddr;
if (uarts[i].txfs && uarts[i].txfs) {
printf("UART%d at 0x%.8x uses ", i, uarts[i].baseaddr);
printf("%s for RX and %s for TX.\n", config.uarts[i].rxfile, config.uarts[i].txfile);
} else
printf("UART%d has problems with TX file stream.\n", i);
register_memoryarea(uarts[i].baseaddr, UART_ADDR_SPACE, uart_read, uart_write);
}
for(i = 0; i < NR_UARTS; i++)
if (config.uarts[i].txfile) { /* MM: Try to create stream. */
if (!(uarts[i].rxfs = fopen(config.uarts[i].rxfile, "r"))
&& !(uarts[i].rxfs = fopen(config.uarts[i].rxfile, "r+"))) {
printf("UART%d has problems with RX file stream.\n", i);
continue;
}
uarts[i].txfs = fopen(config.uarts[i].txfile, "a");
uarts[i].baseaddr = config.uarts[i].baseaddr;
if (uarts[i].txfs && uarts[i].txfs) {
printf("UART%d at 0x%.8x uses ", i, uarts[i].baseaddr);
printf("%s for RX and %s for TX.\n", config.uarts[i].rxfile, config.uarts[i].txfile);
} else
printf("UART%d has problems with TX file stream.\n", i);
register_memoryarea(uarts[i].baseaddr, UART_ADDR_SPACE, 1, uart_read8, uart_write8, 0);
}
}
/* Simulation hook. Must be called every clock cycle to simulate all UART
320,9 → 321,8
int i;
for(i = 0; i < NR_UARTS; i++) {
/* if (!uarts[i].txfs)
if ( !uarts[i].baseaddr )
continue;
*/
printf("\nUART%d visible registers at 0x%.8x:\n", i, uarts[i].baseaddr);
printf("RXBUF: %.2x TXBUF: %.2x\n", uarts[i].regs.rxbuf, uarts[i].regs.txbuf);
printf("DLL : %.2x DLH : %.2x\n", uarts[i].regs.dll, uarts[i].regs.dlh);
/trunk/or1ksim/peripheral/dma.c
1,22 → 1,22
/* dma.c -- Simulation of DMA
Copyright (C) 2001 by Erez Volk, erez@mailandnews.com
Copyright (C) 2001 by Erez Volk, erez@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.
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.
*/
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.
*/
 
/*
* This simulation of the DMA core is not meant to be full.
28,15 → 28,15
#include "sim-config.h"
#include "trace.h"
#include "pic.h"
#include "abstract.h"
#include "fields.h"
 
/* TODO List:
* - "Restarting DMA Transfers"
*/
 
/* The representation of the DMA controllers */
static struct dma_controller dmas[NR_DMAS];
 
static unsigned long dma_read32( unsigned long addr );
static void dma_write32( unsigned long addr, unsigned long value );
 
static unsigned long dma_read_ch_csr( struct dma_channel *channel );
static void dma_write_ch_csr( struct dma_channel *channel, unsigned long value );
static void dma_controller_clock( struct dma_controller *dma );
52,136 → 52,116
/* Reset. Initializes all registers to default and places devices in memory address space. */
void dma_reset()
{
unsigned i;
unsigned i;
 
memset( dmas, 0, sizeof(dmas) );
for ( i = 0; i < NR_DMAS; ++ i )
{
struct dma_controller *dma = &(dmas[i]);
unsigned channel_number;
memset( dmas, 0, sizeof(dmas) );
for ( i = 0; i < NR_DMAS; ++ i ) {
struct dma_controller *dma = &(dmas[i]);
unsigned channel_number;
 
dma->baseaddr = config.dmas[i].baseaddr;
for ( channel_number = 0; channel_number < DMA_NUM_CHANNELS; ++ channel_number )
{
dma->ch[channel_number].controller = &(dmas[i]);
dma->ch[channel_number].channel_number = channel_number;
dma->ch[channel_number].channel_mask = 1LU << channel_number;
dma->ch[channel_number].regs.am0 = dma->ch[channel_number].regs.am1 = 0xFFFFFFFC;
dma->baseaddr = config.dmas[i].baseaddr;
dma->irq = config.dmas[i].irq;
for ( channel_number = 0; channel_number < DMA_NUM_CHANNELS; ++ channel_number ) {
dma->ch[channel_number].controller = &(dmas[i]);
dma->ch[channel_number].channel_number = channel_number;
dma->ch[channel_number].channel_mask = 1LU << channel_number;
dma->ch[channel_number].regs.am0 = dma->ch[channel_number].regs.am1 = 0xFFFFFFFC;
}
if ( dma->baseaddr != 0 )
register_memoryarea( dma->baseaddr, DMA_ADDR_SPACE, 4, dma_read32, dma_write32, 0 );
}
if ( dma->baseaddr != 0 )
register_memoryarea( dma->baseaddr, DMA_ADDR_SPACE, dma_read, dma_write );
}
}
 
/* Print register values on stdout */
void dma_status( void )
{
unsigned i, j;
unsigned i, j;
 
for ( i = 0; i < NR_DMAS; ++ i )
{
struct dma_controller *dma = &(dmas[i]);
for ( i = 0; i < NR_DMAS; ++ i ) {
struct dma_controller *dma = &(dmas[i]);
if ( dma->baseaddr == 0 )
continue;
if ( dma->baseaddr == 0 )
continue;
 
printf( "\nDMA controller %u at 0x%08X:\n", i, dma->baseaddr );
printf( "CSR : 0x%08lX\n", dma->regs.csr );
printf( "INT_MSK_A : 0x%08lX\n", dma->regs.int_msk_a );
printf( "INT_MSK_B : 0x%08lX\n", dma->regs.int_msk_b );
printf( "INT_SRC_A : 0x%08lX\n", dma->regs.int_src_a );
printf( "INT_SRC_B : 0x%08lX\n", dma->regs.int_src_b );
printf( "\nDMA controller %u at 0x%08X:\n", i, dma->baseaddr );
printf( "CSR : 0x%08lX\n", dma->regs.csr );
printf( "INT_MSK_A : 0x%08lX\n", dma->regs.int_msk_a );
printf( "INT_MSK_B : 0x%08lX\n", dma->regs.int_msk_b );
printf( "INT_SRC_A : 0x%08lX\n", dma->regs.int_src_a );
printf( "INT_SRC_B : 0x%08lX\n", dma->regs.int_src_b );
 
for ( j = 0; j < DMA_NUM_CHANNELS; ++ j )
{
struct dma_channel *channel = &(dma->ch[j]);
if ( !channel->referenced )
continue;
printf( "CH%u_CSR : 0x%08lX\n", j, channel->regs.csr );
printf( "CH%u_SZ : 0x%08lX\n", j, channel->regs.sz );
printf( "CH%u_A0 : 0x%08lX\n", j, channel->regs.a0 );
printf( "CH%u_AM0 : 0x%08lX\n", j, channel->regs.am0 );
printf( "CH%u_A1 : 0x%08lX\n", j, channel->regs.a1 );
printf( "CH%u_AM1 : 0x%08lX\n", j, channel->regs.am1 );
printf( "CH%u_DESC : 0x%08lX\n", j, channel->regs.desc );
printf( "CH%u_SWPTR : 0x%08lX\n", j, channel->regs.swptr );
for ( j = 0; j < DMA_NUM_CHANNELS; ++ j ) {
struct dma_channel *channel = &(dma->ch[j]);
if ( !channel->referenced )
continue;
printf( "CH%u_CSR : 0x%08lX\n", j, channel->regs.csr );
printf( "CH%u_SZ : 0x%08lX\n", j, channel->regs.sz );
printf( "CH%u_A0 : 0x%08lX\n", j, channel->regs.a0 );
printf( "CH%u_AM0 : 0x%08lX\n", j, channel->regs.am0 );
printf( "CH%u_A1 : 0x%08lX\n", j, channel->regs.a1 );
printf( "CH%u_AM1 : 0x%08lX\n", j, channel->regs.am1 );
printf( "CH%u_DESC : 0x%08lX\n", j, channel->regs.desc );
printf( "CH%u_SWPTR : 0x%08lX\n", j, channel->regs.swptr );
}
}
}
}
 
/* Read a register */
unsigned long dma_read( unsigned long addr )
unsigned long dma_read32( unsigned long addr )
{
unsigned i;
struct dma_controller *dma = NULL;
unsigned i;
struct dma_controller *dma = NULL;
 
for ( i = 0; i < NR_DMAS && dma == NULL; ++ i )
{
if ( addr >= dmas[i].baseaddr && addr < dmas[i].baseaddr + DMA_ADDR_SPACE )
dma = &(dmas[i]);
}
/* verify we found a controller */
if ( dma == NULL )
{
debug( "dma_read( 0x%08lX ): Out of range\n", addr );
cont_run = 0;
return 0;
}
for ( i = 0; i < NR_DMAS && dma == NULL; ++ i ) {
if ( addr >= dmas[i].baseaddr && addr < dmas[i].baseaddr + DMA_ADDR_SPACE )
dma = &(dmas[i]);
}
/* verify we found a controller */
if ( dma == NULL ) {
fprintf( stderr, "dma_read32( 0x%08lX ): Out of range\n", addr );
cont_run = 0;
return 0;
}
 
addr -= dma->baseaddr;
addr -= dma->baseaddr;
 
if ( addr % 4 != 0 )
{
debug( "dma_read( 0x%08lX ): Not register-aligned\n", addr + dma->baseaddr );
cont_run = 0;
return 0;
}
if ( addr % 4 != 0 ) {
fprintf( stderr, "dma_read32( 0x%08lX ): Not register-aligned\n", addr + dma->baseaddr );
cont_run = 0;
return 0;
}
 
/* case of global (not per-channel) registers */
if ( addr < DMA_CH_BASE )
{
switch( addr )
{
case DMA_CSR: return dma->regs.csr;
case DMA_INT_MSK_A: return dma->regs.int_msk_a;
case DMA_INT_MSK_B: return dma->regs.int_msk_b;
case DMA_INT_SRC_A: {
/* TODO: Doc doesn't say clear the bits, but this looks right. Check it */
unsigned long result = dma->regs.int_src_a;
dma->regs.int_src_a = 0;
return result;
}
case DMA_INT_SRC_B: {
unsigned long result = dma->regs.int_src_b;
dma->regs.int_src_b = 0;
return result;
}
default:
debug( "dma_read( 0x%08lX ): Illegal register\n", addr + dma->baseaddr );
cont_run = 0;
return 0;
}
}
else
{
/* case of per-channel registers */
unsigned chno = (addr - DMA_CH_BASE) / DMA_CH_SIZE;
addr = (addr - DMA_CH_BASE) % DMA_CH_SIZE;
switch( addr )
{
case DMA_CH_CSR: return dma_read_ch_csr( &(dma->ch[chno]) );
case DMA_CH_SZ: return dma->ch[chno].regs.sz;
case DMA_CH_A0: return dma->ch[chno].regs.a0;
case DMA_CH_AM0: return dma->ch[chno].regs.am0;
case DMA_CH_A1: return dma->ch[chno].regs.a1;
case DMA_CH_AM1: return dma->ch[chno].regs.am1;
case DMA_CH_DESC: return dma->ch[chno].regs.desc;
case DMA_CH_SWPTR: return dma->ch[chno].regs.swptr;
}
}
/* case of global (not per-channel) registers */
if ( addr < DMA_CH_BASE ) {
switch( addr ) {
case DMA_CSR: return dma->regs.csr;
case DMA_INT_MSK_A: return dma->regs.int_msk_a;
case DMA_INT_MSK_B: return dma->regs.int_msk_b;
case DMA_INT_SRC_A: return dma->regs.int_src_a;
case DMA_INT_SRC_B: return dma->regs.int_src_b;
default:
fprintf( stderr, "dma_read32( 0x%08lX ): Illegal register\n", addr + dma->baseaddr );
cont_run = 0;
return 0;
}
} else {
/* case of per-channel registers */
unsigned chno = (addr - DMA_CH_BASE) / DMA_CH_SIZE;
addr = (addr - DMA_CH_BASE) % DMA_CH_SIZE;
switch( addr ) {
case DMA_CH_CSR: return dma_read_ch_csr( &(dma->ch[chno]) );
case DMA_CH_SZ: return dma->ch[chno].regs.sz;
case DMA_CH_A0: return dma->ch[chno].regs.a0;
case DMA_CH_AM0: return dma->ch[chno].regs.am0;
case DMA_CH_A1: return dma->ch[chno].regs.a1;
case DMA_CH_AM1: return dma->ch[chno].regs.am1;
case DMA_CH_DESC: return dma->ch[chno].regs.desc;
case DMA_CH_SWPTR: return dma->ch[chno].regs.swptr;
}
}
}
 
 
188,88 → 168,80
/* Handle read from a channel CSR */
unsigned long dma_read_ch_csr( struct dma_channel *channel )
{
unsigned long result = channel->regs.csr;
unsigned long result = channel->regs.csr;
 
/* before returning, clear all relevant bits */
CLEAR_FLAG( channel->regs.csr, DMA_CH_CSR, INT_CHUNK_DONE );
CLEAR_FLAG( channel->regs.csr, DMA_CH_CSR, INT_DONE );
CLEAR_FLAG( channel->regs.csr, DMA_CH_CSR, INT_ERR );
CLEAR_FLAG( channel->regs.csr, DMA_CH_CSR, ERR );
/* before returning, clear all relevant bits */
CLEAR_FLAG( channel->regs.csr, DMA_CH_CSR, INT_CHUNK_DONE );
CLEAR_FLAG( channel->regs.csr, DMA_CH_CSR, INT_DONE );
CLEAR_FLAG( channel->regs.csr, DMA_CH_CSR, INT_ERR );
CLEAR_FLAG( channel->regs.csr, DMA_CH_CSR, ERR );
 
return result;
return result;
}
 
 
 
/* Write a register */
void dma_write( unsigned long addr, unsigned long value )
void dma_write32( unsigned long addr, unsigned long value )
{
unsigned i;
struct dma_controller *dma = NULL;
unsigned i;
struct dma_controller *dma = NULL;
 
/* Find which controller this is */
for ( i = 0; i < NR_DMAS && dma == NULL; ++ i )
{
if ( (addr >= dmas[i].baseaddr) && (addr < dmas[i].baseaddr + DMA_ADDR_SPACE) )
dma = &(dmas[i]);
}
/* verify we found a controller */
if ( dma == NULL )
{
debug( "dma_write( 0x%08lX ): Out of range\n", addr );
cont_run = 0;
return;
}
/* Find which controller this is */
for ( i = 0; i < NR_DMAS && dma == NULL; ++ i ) {
if ( (addr >= dmas[i].baseaddr) && (addr < dmas[i].baseaddr + DMA_ADDR_SPACE) )
dma = &(dmas[i]);
}
/* verify we found a controller */
if ( dma == NULL ) {
fprintf( stderr, "dma_write32( 0x%08lX ): Out of range\n", addr );
cont_run = 0;
return;
}
 
addr -= dma->baseaddr;
addr -= dma->baseaddr;
 
if ( addr % 4 != 0 )
{
debug( "dma_write( 0x%08lX ): Not register-aligned\n", addr + dma->baseaddr );
cont_run = 0;
return;
}
if ( addr % 4 != 0 ) {
fprintf( stderr, "dma_write32( 0x%08lX, 0x%08lX ): Not register-aligned\n", addr + dma->baseaddr, value );
cont_run = 0;
return;
}
 
/* case of global (not per-channel) registers */
if ( addr < DMA_CH_BASE )
{
switch( addr )
{
case DMA_CSR:
if ( TEST_FLAG( value, DMA_CSR, PAUSE ) )
debug( "dma: PAUSE not implemented\n" );
break;
/* case of global (not per-channel) registers */
if ( addr < DMA_CH_BASE ) {
switch( addr ) {
case DMA_CSR:
if ( TEST_FLAG( value, DMA_CSR, PAUSE ) )
fprintf( stderr, "dma: PAUSE not implemented\n" );
break;
 
case DMA_INT_MSK_A: dma->regs.int_msk_a = value; break;
case DMA_INT_MSK_B: dma->regs.int_msk_b = value; break;
case DMA_INT_SRC_A: dma->regs.int_src_a = value; break;
case DMA_INT_SRC_B: dma->regs.int_src_b = value; break;
default:
debug( "dma_write( 0x%08lX ): Illegal register\n", addr + dma->baseaddr );
cont_run = 0;
return;
case DMA_INT_MSK_A: dma->regs.int_msk_a = value; break;
case DMA_INT_MSK_B: dma->regs.int_msk_b = value; break;
case DMA_INT_SRC_A: dma->regs.int_src_a = value; break;
case DMA_INT_SRC_B: dma->regs.int_src_b = value; break;
default:
fprintf( stderr, "dma_write32( 0x%08lX ): Illegal register\n", addr + dma->baseaddr );
cont_run = 0;
return;
}
} else {
/* case of per-channel registers */
unsigned chno = (addr - DMA_CH_BASE) / DMA_CH_SIZE;
struct dma_channel *channel = &(dma->ch[chno]);
channel->referenced = 1;
addr = (addr - DMA_CH_BASE) % DMA_CH_SIZE;
switch( addr ) {
case DMA_CSR: dma_write_ch_csr( &(dma->ch[chno]), value ); break;
case DMA_CH_SZ: channel->regs.sz = value; break;
case DMA_CH_A0: channel->regs.a0 = value; break;
case DMA_CH_AM0: channel->regs.am0 = value; break;
case DMA_CH_A1: channel->regs.a1 = value; break;
case DMA_CH_AM1: channel->regs.am1 = value; break;
case DMA_CH_DESC: channel->regs.desc = value; break;
case DMA_CH_SWPTR: channel->regs.swptr = value; break;
}
}
}
else
{
/* case of per-channel registers */
unsigned chno = (addr - DMA_CH_BASE) / DMA_CH_SIZE;
struct dma_channel *channel = &(dma->ch[chno]);
channel->referenced = 1;
addr = (addr - DMA_CH_BASE) % DMA_CH_SIZE;
switch( addr )
{
case DMA_CSR: dma_write_ch_csr( &(dma->ch[chno]), value ); break;
case DMA_CH_SZ: channel->regs.sz = value; break;
case DMA_CH_A0: channel->regs.a0 = value; break;
case DMA_CH_AM0: channel->regs.am0 = value; break;
case DMA_CH_A1: channel->regs.a1 = value; break;
case DMA_CH_AM1: channel->regs.am1 = value; break;
case DMA_CH_DESC: channel->regs.desc = value; break;
case DMA_CH_SWPTR: channel->regs.swptr = value; break;
}
}
}
 
 
278,9 → 250,9
*/
void dma_write_ch_csr( struct dma_channel *channel, unsigned long value )
{
/* Copy the writable bits to the channel CSR */
channel->regs.csr &= ~DMA_CH_CSR_WRITE_MASK;
channel->regs.csr |= value & DMA_CH_CSR_WRITE_MASK;
/* Copy the writable bits to the channel CSR */
channel->regs.csr &= ~DMA_CH_CSR_WRITE_MASK;
channel->regs.csr |= value & DMA_CH_CSR_WRITE_MASK;
}
 
 
291,27 → 263,27
 
void set_dma_req_i( unsigned dma_controller, unsigned channel )
{
dmas[dma_controller].ch[channel].dma_req_i = 1;
dmas[dma_controller].ch[channel].dma_req_i = 1;
}
 
void clear_dma_req_i( unsigned dma_controller, unsigned channel )
{
dmas[dma_controller].ch[channel].dma_req_i = 0;
dmas[dma_controller].ch[channel].dma_req_i = 0;
}
 
void set_dma_nd_i( unsigned dma_controller, unsigned channel )
{
dmas[dma_controller].ch[channel].dma_nd_i = 1;
dmas[dma_controller].ch[channel].dma_nd_i = 1;
}
 
void clear_dma_nd_i( unsigned dma_controller, unsigned channel )
{
dmas[dma_controller].ch[channel].dma_nd_i = 0;
dmas[dma_controller].ch[channel].dma_nd_i = 0;
}
 
unsigned check_dma_acq_o( unsigned dma_controller, unsigned channel )
unsigned check_dma_ack_o( unsigned dma_controller, unsigned channel )
{
return dmas[dma_controller].ch[channel].dma_acq_o;
return dmas[dma_controller].ch[channel].dma_ack_o;
}
 
 
319,12 → 291,11
/* Simulation hook. Must be called every clock cycle to simulate DMA. */
void dma_clock()
{
unsigned i;
for ( i = 0; i < NR_DMAS; ++ i )
{
if ( dmas[i].baseaddr != 0 )
dma_controller_clock( &(dmas[i]) );
}
unsigned i;
for ( i = 0; i < NR_DMAS; ++ i ) {
if ( dmas[i].baseaddr != 0 )
dma_controller_clock( &(dmas[i]) );
}
}
 
 
334,92 → 305,85
*/
void dma_controller_clock( struct dma_controller *dma )
{
unsigned chno, i;
int breakpoint = 0;
for ( chno = 0; chno < DMA_NUM_CHANNELS; ++ chno )
{
struct dma_channel *channel = &(dma->ch[chno]);
/* check if this channel is enabled */
if ( !TEST_FLAG( channel->regs.csr, DMA_CH_CSR, CH_EN ) )
continue;
unsigned chno, i;
int breakpoint = 0;
for ( chno = 0; chno < DMA_NUM_CHANNELS; ++ chno ) {
struct dma_channel *channel = &(dma->ch[chno]);
/* check if this channel is enabled */
if ( !TEST_FLAG( channel->regs.csr, DMA_CH_CSR, CH_EN ) )
continue;
 
/* Do we need to abort? */
if ( TEST_FLAG( channel->regs.csr, DMA_CH_CSR, STOP ) )
{
debug( "DMA: STOP requested\n" );
CLEAR_FLAG( channel->regs.csr, DMA_CH_CSR, CH_EN );
CLEAR_FLAG( channel->regs.csr, DMA_CH_CSR, BUSY );
SET_FLAG( channel->regs.csr, DMA_CH_CSR, ERR );
if ( TEST_FLAG( channel->regs.csr, DMA_CH_CSR, INE_ERR ) &&
(channel->controller->regs.int_msk_a & channel->channel_mask) )
{
SET_FLAG( channel->regs.csr, DMA_CH_CSR, INT_ERR );
channel->controller->regs.int_src_a = channel->channel_mask;
report_interrupt( INT_DMA );
}
/* Do we need to abort? */
if ( TEST_FLAG( channel->regs.csr, DMA_CH_CSR, STOP ) ) {
fprintf( stderr, "DMA: STOP requested\n" );
CLEAR_FLAG( channel->regs.csr, DMA_CH_CSR, CH_EN );
CLEAR_FLAG( channel->regs.csr, DMA_CH_CSR, BUSY );
SET_FLAG( channel->regs.csr, DMA_CH_CSR, ERR );
if ( TEST_FLAG( channel->regs.csr, DMA_CH_CSR, INE_ERR ) &&
(channel->controller->regs.int_msk_a & channel->channel_mask) ) {
SET_FLAG( channel->regs.csr, DMA_CH_CSR, INT_ERR );
channel->controller->regs.int_src_a = channel->channel_mask;
report_interrupt( channel->controller->irq );
}
 
continue;
}
continue;
}
 
/* In HW Handshake mode, only work when dma_req_i asserted */
if ( TEST_FLAG( channel->regs.csr, DMA_CH_CSR, MODE ) &&
!channel->dma_req_i )
{
debug( "DMA: Waiting for HW handshake\n" );
continue;
}
/* In HW Handshake mode, only work when dma_req_i asserted */
if ( TEST_FLAG( channel->regs.csr, DMA_CH_CSR, MODE ) &&
!channel->dma_req_i ) {
fprintf( stderr, "DMA: Waiting for HW handshake\n" );
continue;
}
 
/* If this is the first cycle of the transfer, initialize our state */
if ( !TEST_FLAG( channel->regs.csr, DMA_CH_CSR, BUSY ) )
{
CLEAR_FLAG( channel->regs.csr, DMA_CH_CSR, DONE );
CLEAR_FLAG( channel->regs.csr, DMA_CH_CSR, ERR );
SET_FLAG( channel->regs.csr, DMA_CH_CSR, BUSY );
/* If this is the first cycle of the transfer, initialize our state */
if ( !TEST_FLAG( channel->regs.csr, DMA_CH_CSR, BUSY ) ) {
CLEAR_FLAG( channel->regs.csr, DMA_CH_CSR, DONE );
CLEAR_FLAG( channel->regs.csr, DMA_CH_CSR, ERR );
SET_FLAG( channel->regs.csr, DMA_CH_CSR, BUSY );
 
/* If using linked lists, copy the appropriate fields to our registers */
if ( TEST_FLAG( channel->regs.csr, DMA_CH_CSR, USE_ED ) )
dma_load_descriptor( channel );
else
channel->load_next_descriptor_when_done = 0;
/* Set our internal status */
dma_init_transfer( channel );
/* If using linked lists, copy the appropriate fields to our registers */
if ( TEST_FLAG( channel->regs.csr, DMA_CH_CSR, USE_ED ) )
dma_load_descriptor( channel );
else
channel->load_next_descriptor_when_done = 0;
/* Set our internal status */
dma_init_transfer( channel );
 
/* Might need to skip descriptor */
if ( CHANNEL_ND_I( channel ) )
{
debug( "DMA: dma_nd_i asserted before dma_req_i, skipping descriptor\n" );
dma_channel_terminate_transfer( channel, 0 );
continue;
}
}
/* Might need to skip descriptor */
if ( CHANNEL_ND_I( channel ) ) {
fprintf( stderr, "DMA: dma_nd_i asserted before dma_req_i, skipping descriptor\n" );
dma_channel_terminate_transfer( channel, 0 );
continue;
}
}
 
/* Transfer one word */
set_mem32( channel->destination, eval_mem32( channel->source, &breakpoint ), &breakpoint );
/* Transfer one word */
set_mem32( channel->destination, eval_mem32( channel->source, &breakpoint ), &breakpoint );
 
/* Advance the source and destionation pointers */
masked_increase( &(channel->source), channel->source_mask );
masked_increase( &(channel->destination), channel->destination_mask );
++ channel->words_transferred;
/* Advance the source and destionation pointers */
masked_increase( &(channel->source), channel->source_mask );
masked_increase( &(channel->destination), channel->destination_mask );
++ channel->words_transferred;
 
/* Have we finished a whole chunk? */
channel->dma_acq_o = (channel->words_transferred % channel->chunk_size == 0);
/* Have we finished a whole chunk? */
channel->dma_ack_o = (channel->words_transferred % channel->chunk_size == 0);
 
/* When done with a chunk, check for dma_nd_i */
if ( CHANNEL_ND_I( channel ) )
{
debug( "DMA: dma_nd_i asserted, \n" );
dma_channel_terminate_transfer( channel, 0 );
continue;
/* When done with a chunk, check for dma_nd_i */
if ( CHANNEL_ND_I( channel ) ) {
fprintf( stderr, "DMA: dma_nd_i asserted, \n" );
dma_channel_terminate_transfer( channel, 0 );
continue;
}
 
/* Are we done? */
if ( channel->words_transferred >= channel->total_size )
dma_channel_terminate_transfer( channel, 1 );
}
 
/* Are we done? */
if ( channel->words_transferred >= channel->total_size )
dma_channel_terminate_transfer( channel, 1 );
}
}
 
 
426,23 → 390,23
/* Copy relevant valued from linked list descriptor to channel registers */
void dma_load_descriptor( struct dma_channel *channel )
{
int breakpoint = 0;
unsigned long desc_csr = eval_mem32( channel->regs.desc + DMA_DESC_CSR, &breakpoint );
int breakpoint = 0;
unsigned long desc_csr = eval_mem32( channel->regs.desc + DMA_DESC_CSR, &breakpoint );
 
channel->load_next_descriptor_when_done = !TEST_FLAG( desc_csr, DMA_DESC_CSR, EOL );
channel->load_next_descriptor_when_done = !TEST_FLAG( desc_csr, DMA_DESC_CSR, EOL );
ASSIGN_FLAG( channel->regs.csr, DMA_CH_CSR, INC_SRC, TEST_FLAG( desc_csr, DMA_DESC_CSR, INC_SRC ) );
ASSIGN_FLAG( channel->regs.csr, DMA_CH_CSR, INC_DST, TEST_FLAG( desc_csr, DMA_DESC_CSR, INC_DST ) );
ASSIGN_FLAG( channel->regs.csr, DMA_CH_CSR, SRC_SEL, TEST_FLAG( desc_csr, DMA_DESC_CSR, SRC_SEL ) );
ASSIGN_FLAG( channel->regs.csr, DMA_CH_CSR, DST_SEL, TEST_FLAG( desc_csr, DMA_DESC_CSR, DST_SEL ) );
ASSIGN_FLAG( channel->regs.csr, DMA_CH_CSR, INC_SRC, TEST_FLAG( desc_csr, DMA_DESC_CSR, INC_SRC ) );
ASSIGN_FLAG( channel->regs.csr, DMA_CH_CSR, INC_DST, TEST_FLAG( desc_csr, DMA_DESC_CSR, INC_DST ) );
ASSIGN_FLAG( channel->regs.csr, DMA_CH_CSR, SRC_SEL, TEST_FLAG( desc_csr, DMA_DESC_CSR, SRC_SEL ) );
ASSIGN_FLAG( channel->regs.csr, DMA_CH_CSR, DST_SEL, TEST_FLAG( desc_csr, DMA_DESC_CSR, DST_SEL ) );
 
SET_FIELD( channel->regs.sz, DMA_CH_SZ, TOT_SZ, GET_FIELD( desc_csr, DMA_DESC_CSR, TOT_SZ ) );
SET_FIELD( channel->regs.sz, DMA_CH_SZ, TOT_SZ, GET_FIELD( desc_csr, DMA_DESC_CSR, TOT_SZ ) );
 
channel->regs.a0 = eval_mem32( channel->regs.desc + DMA_DESC_ADR0, &breakpoint );
channel->regs.a1 = eval_mem32( channel->regs.desc + DMA_DESC_ADR1, &breakpoint );
channel->regs.a0 = eval_mem32( channel->regs.desc + DMA_DESC_ADR0, &breakpoint );
channel->regs.a1 = eval_mem32( channel->regs.desc + DMA_DESC_ADR1, &breakpoint );
channel->current_descriptor = channel->regs.desc;
channel->regs.desc = eval_mem32( channel->regs.desc + DMA_DESC_NEXT, &breakpoint );
channel->current_descriptor = channel->regs.desc;
channel->regs.desc = eval_mem32( channel->regs.desc + DMA_DESC_NEXT, &breakpoint );
}
 
 
449,15 → 413,15
/* Initialize internal parameters used to implement transfers */
void dma_init_transfer( struct dma_channel *channel )
{
channel->source = channel->regs.a0;
channel->destination = channel->regs.a1;
channel->source_mask = TEST_FLAG( channel->regs.csr, DMA_CH_CSR, INC_SRC ) ? channel->regs.am0 : 0;
channel->destination_mask = TEST_FLAG( channel->regs.csr, DMA_CH_CSR, INC_DST ) ? channel->regs.am1 : 0;
channel->total_size = GET_FIELD( channel->regs.sz, DMA_CH_SZ, TOT_SZ );
channel->chunk_size = GET_FIELD( channel->regs.sz, DMA_CH_SZ, CHK_SZ );
if ( !channel->chunk_size || (channel->chunk_size > channel->total_size) )
channel->chunk_size = channel->total_size;
channel->words_transferred = 0;
channel->source = channel->regs.a0;
channel->destination = channel->regs.a1;
channel->source_mask = TEST_FLAG( channel->regs.csr, DMA_CH_CSR, INC_SRC ) ? channel->regs.am0 : 0;
channel->destination_mask = TEST_FLAG( channel->regs.csr, DMA_CH_CSR, INC_DST ) ? channel->regs.am1 : 0;
channel->total_size = GET_FIELD( channel->regs.sz, DMA_CH_SZ, TOT_SZ );
channel->chunk_size = GET_FIELD( channel->regs.sz, DMA_CH_SZ, CHK_SZ );
if ( !channel->chunk_size || (channel->chunk_size > channel->total_size) )
channel->chunk_size = channel->total_size;
channel->words_transferred = 0;
}
 
 
464,54 → 428,49
/* Take care of transfer termination */
void dma_channel_terminate_transfer( struct dma_channel *channel, int generate_interrupt )
{
/* Might be working in a linked list */
if ( channel->load_next_descriptor_when_done )
{
dma_load_descriptor( channel );
dma_init_transfer( channel );
return;
}
/* Might be working in a linked list */
if ( channel->load_next_descriptor_when_done ) {
dma_load_descriptor( channel );
dma_init_transfer( channel );
return;
}
 
/* Might be in auto-restart mode */
if ( TEST_FLAG( channel->regs.csr, DMA_CH_CSR, ARS ) )
{
dma_init_transfer( channel );
return;
}
/* Might be in auto-restart mode */
if ( TEST_FLAG( channel->regs.csr, DMA_CH_CSR, ARS ) ) {
dma_init_transfer( channel );
return;
}
 
/* If needed, write amount of data transferred back to memory */
if ( TEST_FLAG( channel->regs.csr, DMA_CH_CSR, SZ_WB ) &&
TEST_FLAG( channel->regs.csr, DMA_CH_CSR, USE_ED ) )
{
int breakpoint = 0;
unsigned long desc_csr = eval_mem32( channel->regs.desc + DMA_DESC_CSR, &breakpoint );
/* TODO: What should we write back? Doc says "total number of remaining bytes" !? */
unsigned long remaining_words = channel->total_size - channel->words_transferred;
SET_FIELD( channel->regs.sz, DMA_DESC_CSR, TOT_SZ, remaining_words );
}
/* If needed, write amount of data transferred back to memory */
if ( TEST_FLAG( channel->regs.csr, DMA_CH_CSR, SZ_WB ) &&
TEST_FLAG( channel->regs.csr, DMA_CH_CSR, USE_ED ) ) {
int breakpoint = 0;
unsigned long desc_csr = eval_mem32( channel->regs.desc + DMA_DESC_CSR, &breakpoint );
/* TODO: What should we write back? Doc says "total number of remaining bytes" !? */
unsigned long remaining_words = channel->total_size - channel->words_transferred;
SET_FIELD( channel->regs.sz, DMA_DESC_CSR, TOT_SZ, remaining_words );
}
 
/* Mark end of transfer */
CLEAR_FLAG( channel->regs.csr, DMA_CH_CSR, CH_EN );
SET_FLAG( channel->regs.csr, DMA_CH_CSR, DONE );
CLEAR_FLAG( channel->regs.csr, DMA_CH_CSR, ERR );
CLEAR_FLAG( channel->regs.csr, DMA_CH_CSR, BUSY );
/* If needed, generate interrupt */
if ( generate_interrupt )
{
/* TODO: Which channel should we interrupt? */
if ( TEST_FLAG( channel->regs.csr, DMA_CH_CSR, INE_DONE ) &&
(channel->controller->regs.int_msk_a & channel->channel_mask) )
{
SET_FLAG( channel->regs.csr, DMA_CH_CSR, INT_DONE );
channel->controller->regs.int_src_a = channel->channel_mask;
report_interrupt( INT_DMA );
/* Mark end of transfer */
CLEAR_FLAG( channel->regs.csr, DMA_CH_CSR, CH_EN );
SET_FLAG( channel->regs.csr, DMA_CH_CSR, DONE );
CLEAR_FLAG( channel->regs.csr, DMA_CH_CSR, ERR );
CLEAR_FLAG( channel->regs.csr, DMA_CH_CSR, BUSY );
/* If needed, generate interrupt */
if ( generate_interrupt ) {
/* TODO: Which channel should we interrupt? */
if ( TEST_FLAG( channel->regs.csr, DMA_CH_CSR, INE_DONE ) &&
(channel->controller->regs.int_msk_a & channel->channel_mask) ) {
SET_FLAG( channel->regs.csr, DMA_CH_CSR, INT_DONE );
channel->controller->regs.int_src_a = channel->channel_mask;
report_interrupt( channel->controller->irq );
}
}
}
}
 
/* Utility function: Add 4 to a value with a mask */
void masked_increase( unsigned long *value, unsigned long mask )
{
*value = (*value & ~mask) | ((*value & mask) + 4);
*value = (*value & ~mask) | ((*value & mask) + 4);
}
/trunk/or1ksim/peripheral/16450.h
18,8 → 18,6
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
/* Prototypes */
void uart_write(unsigned long addr, unsigned long value);
unsigned long uart_read(unsigned long addr);
void uart_reset();
void uart_clock();
 
/trunk/or1ksim/peripheral/dma.h
1,5 → 1,5
/* dma.h -- Definition of types and structures for DMA
Copyright (C) 2001 by Erez Volk, erez@mailandnews.com
Copyright (C) 2001 by Erez Volk, erez@opencores.org
 
This file is part of OpenRISC 1000 Architectural Simulator.
16,19 → 16,17
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.
*/
*/
 
/* Exported function prototypes */
void dma_reset( void );
void dma_clock( void );
void dma_write( unsigned long addr, unsigned long value );
unsigned long dma_read( unsigned long addr );
 
void set_dma_req_i( unsigned dma_controller, unsigned channel );
void clear_dma_req_i( unsigned dma_controller, unsigned channel );
void set_dma_nd_i( unsigned dma_controller, unsigned channel );
void clear_dma_nd_i( unsigned dma_controller, unsigned channel );
unsigned check_dma_acq_o( unsigned dma_controller, unsigned channel );
unsigned check_dma_ack_o( unsigned dma_controller, unsigned channel );
 
/* Number of channel per DMA controller */
#define DMA_NUM_CHANNELS 31
137,39 → 135,39
/* Implementation of DMA Channel Registers and State */
struct dma_channel
{
/* The controller we belong to */
struct dma_controller *controller;
/* The controller we belong to */
struct dma_controller *controller;
 
/* Our channel number and bit mask */
unsigned channel_number;
unsigned long channel_mask;
/* Our channel number and bit mask */
unsigned channel_number;
unsigned long channel_mask;
 
/* Used for dump, to save dumping all 32 channels */
unsigned referenced;
/* Used for dump, to save dumping all 32 channels */
unsigned referenced;
 
/* Inner state of transfer etc. */
unsigned load_next_descriptor_when_done;
unsigned long current_descriptor;
unsigned long source, destination, source_mask, destination_mask;
unsigned long chunk_size, total_size, words_transferred;
/* Inner state of transfer etc. */
unsigned load_next_descriptor_when_done;
unsigned long current_descriptor;
unsigned long source, destination, source_mask, destination_mask;
unsigned long chunk_size, total_size, words_transferred;
 
/* The interface registers */
struct
{
unsigned long csr;
unsigned long sz;
unsigned long a0;
unsigned long am0;
unsigned long a1;
unsigned long am1;
unsigned long desc;
unsigned long swptr;
} regs;
/* The interface registers */
struct
{
unsigned long csr;
unsigned long sz;
unsigned long a0;
unsigned long am0;
unsigned long a1;
unsigned long am1;
unsigned long desc;
unsigned long swptr;
} regs;
 
/* Some control signals */
unsigned dma_req_i;
unsigned dma_acq_o;
unsigned dma_nd_i;
/* Some control signals */
unsigned dma_req_i;
unsigned dma_ack_o;
unsigned dma_nd_i;
};
 
 
176,19 → 174,22
/* Implementation of DMA Controller Registers and State */
struct dma_controller
{
/* Base address in memory */
unsigned long baseaddr;
/* Base address in memory */
unsigned long baseaddr;
 
/* Controller Registers */
struct
{
unsigned long csr;
unsigned long int_msk_a;
unsigned long int_msk_b;
unsigned long int_src_a;
unsigned long int_src_b;
} regs;
/* Which interrupt number we generate */
unsigned irq;
 
/* Channels */
struct dma_channel ch[DMA_NUM_CHANNELS];
/* Controller Registers */
struct
{
unsigned long csr;
unsigned long int_msk_a;
unsigned long int_msk_b;
unsigned long int_src_a;
unsigned long int_src_b;
} regs;
 
/* Channels */
struct dma_channel ch[DMA_NUM_CHANNELS];
};

powered by: WebSVN 2.1.0

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