URL
https://opencores.org/ocsvn/eco32/eco32/trunk
Subversion Repositories eco32
Compare Revisions
- This comparison shows the changes necessary to convert path
/eco32/trunk/sim
- from Rev 24 to Rev 25
- ↔ Reverse comparison
Rev 24 → Rev 25
/output.c
45,7 → 45,7
/* output device not installed */ |
return; |
} |
cPrintf("Resetting output device...\n"); |
cPrintf("Resetting Output Device...\n"); |
fseek(outputFile, 0, SEEK_SET); |
} |
|
/dspkbd.c
1,5 → 1,5
/* |
* display.c -- display controller simulation |
* dspkbd.h -- display & keyboard controller simulation |
*/ |
|
|
794,7 → 794,7
if (debug) { |
cPrintf("\n**** KEYBOARD CALLBACK ****\n"); |
} |
timerStart(KEYBOARD_MSEC, kbdCallback, dev); |
timerStart(KEYBOARD_USEC, kbdCallback, dev); |
if (kbdBufWritePtr == kbdBufReadPtr) { |
/* no character ready */ |
return; |
886,7 → 886,7
kbdBufInit(); |
kbdCtrl = 0; |
kbdData = 0; |
timerStart(KEYBOARD_MSEC, kbdCallback, 0); |
timerStart(KEYBOARD_USEC, kbdCallback, 0); |
} |
|
|
/term.c
59,7 → 59,7
if (debug) { |
cPrintf("\n**** TERM RCVR CALLBACK ****\n"); |
} |
timerStart(TERM_RCVR_MSEC, rcvrCallback, dev); |
timerStart(TERM_RCVR_USEC, rcvrCallback, dev); |
c = fgetc(terminals[dev].in); |
if (c == EOF) { |
/* no character typed */ |
98,12 → 98,12
if (debug) { |
cPrintf("\n**** TERM READ from 0x%08X", addr); |
} |
dev = addr >> 4; |
dev = addr >> 12; |
if (dev >= numTerminals) { |
/* illegal device */ |
throwException(EXC_BUS_TIMEOUT); |
} |
reg = addr & 0x0F; |
reg = addr & 0x0FFF; |
if (reg == TERM_RCVR_CTRL) { |
data = terminals[dev].rcvrCtrl; |
} else |
139,12 → 139,12
cPrintf("\n**** TERM WRITE to 0x%08X, data = 0x%08X ****\n", |
addr, data); |
} |
dev = addr >> 4; |
dev = addr >> 12; |
if (dev >= numTerminals) { |
/* illegal device */ |
throwException(EXC_BUS_TIMEOUT); |
} |
reg = addr & 0x0F; |
reg = addr & 0x0FFF; |
if (reg == TERM_RCVR_CTRL) { |
if (data & TERM_RCVR_IEN) { |
terminals[dev].rcvrCtrl |= TERM_RCVR_IEN; |
196,7 → 196,7
/* lower terminal xmtr interrupt */ |
cpuResetInterrupt(terminals[dev].xmtrIRQ); |
} |
timerStart(TERM_XMTR_MSEC, xmtrCallback, dev); |
timerStart(TERM_XMTR_USEC, xmtrCallback, dev); |
} else { |
/* illegal register */ |
throwException(EXC_BUS_TIMEOUT); |
215,7 → 215,7
terminals[i].rcvrCtrl = 0; |
terminals[i].rcvrData = 0; |
terminals[i].rcvrIRQ = IRQ_TERM_0_RCVR + 2 * i; |
timerStart(TERM_RCVR_MSEC, rcvrCallback, i); |
timerStart(TERM_RCVR_USEC, rcvrCallback, i); |
terminals[i].xmtrCtrl = TERM_XMTR_RDY; |
terminals[i].xmtrData = 0; |
terminals[i].xmtrIRQ = IRQ_TERM_0_XMTR + 2 * i; |
/dspkbd.h
20,7 → 20,7
|
#define KEYBOARD_RDY 0x01 /* keyboard has a character */ |
#define KEYBOARD_IEN 0x02 /* enable keyboard interrupt */ |
#define KEYBOARD_MSEC 20 /* input checking interval */ |
#define KEYBOARD_USEC 2000 /* input checking interval */ |
|
|
Word keyboardRead(Word addr); |
/term.h
14,11 → 14,11
|
#define TERM_RCVR_RDY 0x01 /* receiver has a character */ |
#define TERM_RCVR_IEN 0x02 /* enable receiver interrupt */ |
#define TERM_RCVR_MSEC 20 /* input checking interval */ |
#define TERM_RCVR_USEC 2000 /* input checking interval */ |
|
#define TERM_XMTR_RDY 0x01 /* transmitter accepts a character */ |
#define TERM_XMTR_IEN 0x02 /* enable transmitter interrupt */ |
#define TERM_XMTR_MSEC 8 /* output speed */ |
#define TERM_XMTR_USEC 1042 /* output speed */ |
|
|
Word termRead(Word addr); |
/cpu.c
42,7 → 42,6
static Word psw; /* processor status word */ |
static Word r[32]; /* general purpose registers */ |
|
static int instrCount; /* counts instrs for timer tick */ |
static unsigned irqPending; /* one bit for each pending IRQ */ |
|
static Bool breakSet; /* breakpoint set if true */ |
59,15 → 58,6
/**************************************************************/ |
|
|
static void handleRealTimeTasks(void) { |
/* handle 'real-time' tasks */ |
if (++instrCount == INSTRS_PER_MSEC) { |
instrCount = 0; |
timerTick(); |
} |
} |
|
|
static void handleInterrupts(void) { |
unsigned irqMask; |
unsigned irqSeen; |
572,7 → 562,7
if (exception == 0) { |
/* initialization */ |
pushEnvironment(&myEnvironment); |
handleRealTimeTasks(); |
timerTick(); |
execNextInstruction(); |
handleInterrupts(); |
} else { |
602,7 → 592,7
} |
} |
while (run) { |
handleRealTimeTasks(); |
timerTick(); |
execNextInstruction(); |
handleInterrupts(); |
if (breakSet && pc == breakAddr) { |
641,7 → 631,6
r[0] = 0; |
psw = 0; |
/* reset simulator control variables */ |
instrCount = 0; |
irqPending = 0; |
total = 0; |
} |
/error.c
19,6 → 19,7
#include "term.h" |
#include "disk.h" |
#include "output.h" |
#include "shutdown.h" |
#include "graph.h" |
|
|
34,6 → 35,7
termExit(); |
diskExit(); |
outputExit(); |
shutdownExit(); |
graphExit(); |
cExit(); |
va_start(ap, fmt); |
/disk.c
158,7 → 158,7
if (delta > diskCap) { |
delta = diskCap; |
} |
timerStart(DISK_DELAY + (delta * DISK_SEEK) / diskCap, |
timerStart(DISK_DELAY_USEC + (delta * DISK_SEEK_USEC) / diskCap, |
diskCallback, 1); |
} |
} else { |
213,7 → 213,7
if (totalSectors != 0) { |
cPrintf("Disk of size %ld sectors (%ld bytes) installed.\n", |
totalSectors, totalSectors * SECTOR_SIZE); |
timerStart(DISK_STARTUP, diskCallback, 0); |
timerStart(DISK_START_USEC, diskCallback, 0); |
} |
} |
|
/cpu.h
7,7 → 7,8
#define _CPU_H_ |
|
|
#define IRQ_TIMER 14 /* timer interrupt */ |
#define IRQ_TIMER_1 15 /* timer 1 interrupt */ |
#define IRQ_TIMER_0 14 /* timer 0 interrupt */ |
#define IRQ_DISK 8 /* disk interrupt */ |
#define IRQ_KEYBOARD 4 /* keyboard interrupt */ |
#define IRQ_TERM_1_RCVR 3 /* terminal 1 receiver interrupt */ |
/Makefile
11,7 → 11,8
|
SRCS = main.c console.c error.c except.c command.c \ |
instr.c asm.c disasm.c cpu.c mmu.c memory.c \ |
timer.c dspkbd.c term.c disk.c output.c graph.c |
timer.c dspkbd.c term.c disk.c output.c shutdown.c \ |
graph.c |
OBJS = $(patsubst %.c,%.o,$(SRCS)) |
BIN = sim |
|
/disk.h
21,9 → 21,9
#define DISK_DONE 0x10 /* 1 = disk has finished the command */ |
#define DISK_READY 0x20 /* 1 = capacity valid, disk accepts command */ |
|
#define DISK_DELAY 10 /* seek start/settle + rotational delay */ |
#define DISK_SEEK 50 /* full disk seek time */ |
#define DISK_STARTUP 1000 /* disk startup time (until DISK_READY) */ |
#define DISK_DELAY_USEC 10000 /* seek start/settle + rotational delay */ |
#define DISK_SEEK_USEC 50000 /* full disk seek time */ |
#define DISK_START_USEC 1000000 /* disk startup time (until DISK_READY) */ |
|
|
Word diskRead(Word addr); |
/memory.c
19,6 → 19,7
#include "term.h" |
#include "disk.h" |
#include "output.h" |
#include "shutdown.h" |
#include "graph.h" |
|
|
73,6 → 74,10
data = outputRead(pAddr & IO_REG_MASK); |
return data; |
} |
if ((pAddr & IO_DEV_MASK) == SHUTDOWN_BASE) { |
data = shutdownRead(pAddr & IO_REG_MASK); |
return data; |
} |
if ((pAddr & IO_DEV_MASK) >= GRAPH_BASE) { |
data = graphRead(pAddr & IO_GRAPH_MASK); |
return data; |
159,6 → 164,10
outputWrite(pAddr & IO_REG_MASK, data); |
return; |
} |
if ((pAddr & IO_DEV_MASK) == SHUTDOWN_BASE) { |
shutdownWrite(pAddr & IO_REG_MASK, data); |
return; |
} |
if ((pAddr & IO_DEV_MASK) >= GRAPH_BASE) { |
graphWrite(pAddr & IO_GRAPH_MASK, data); |
return; |
/shutdown.c
0,0 → 1,61
/* |
* shutdown.c -- shutdown device |
*/ |
|
|
#include <stdio.h> |
#include <stdlib.h> |
#include <string.h> |
|
#include "common.h" |
#include "console.h" |
#include "error.h" |
#include "cpu.h" |
#include "mmu.h" |
#include "memory.h" |
#include "timer.h" |
#include "dspkbd.h" |
#include "term.h" |
#include "disk.h" |
#include "output.h" |
#include "shutdown.h" |
#include "graph.h" |
|
|
Word shutdownRead(Word addr) { |
/* the shutdown device always returns 0 on read */ |
return 0; |
} |
|
|
void shutdownWrite(Word addr, Word data) { |
/* the device supports a single function: exiting the simulator */ |
cpuExit(); |
mmuExit(); |
memoryExit(); |
timerExit(); |
displayExit(); |
keyboardExit(); |
termExit(); |
diskExit(); |
outputExit(); |
shutdownExit(); |
graphExit(); |
cPrintf("ECO32 Simulator shutdown\n"); |
cExit(); |
exit(data & 0xFF); |
} |
|
|
void shutdownReset(void) { |
cPrintf("Resetting Shutdown Device...\n"); |
} |
|
|
void shutdownInit(void) { |
shutdownReset(); |
} |
|
|
void shutdownExit(void) { |
} |
/command.c
22,6 → 22,8
#include "dspkbd.h" |
#include "term.h" |
#include "disk.h" |
#include "output.h" |
#include "shutdown.h" |
#include "graph.h" |
|
|
731,6 → 733,8
keyboardReset(); |
termReset(); |
diskReset(); |
outputReset(); |
shutdownReset(); |
graphReset(); |
memoryReset(); |
mmuReset(); |
/timer.c
19,6 → 19,9
#define TIME_WRAP 1000000 /* avoid overflow of current time */ |
|
|
/* |
* data structure for simulation timer |
*/ |
typedef struct timer { |
struct timer *next; |
int alarm; |
27,29 → 30,47
} Timer; |
|
|
/* |
* data structure for timer/counter device |
*/ |
typedef struct { |
Word ctrl; |
Word divisor; |
Word counter; |
int irq; |
} TimerCounter; |
|
|
static Bool debug = false; |
|
static Timer *activeTimers = NULL; |
static Timer *freeTimers = NULL; |
static int currentTime = 0; /* measured in clock cycles */ |
|
static int currentTime = 0; |
static TimerCounter timerCounters[NUMBER_TMRCNT]; |
|
static Word timerCtrl = 0x00000000; |
static Word timerDivisor = 0xFFFFFFFF; |
static Word timerCounter = 0xFFFFFFFF; |
|
|
Word timerRead(Word addr) { |
int dev, reg; |
Word data; |
|
if (debug) { |
cPrintf("\n**** TIMER READ from 0x%08X", addr); |
} |
if (addr == TIMER_CTRL) { |
data = timerCtrl; |
dev = addr >> 12; |
if (dev >= NUMBER_TMRCNT) { |
/* illegal device */ |
throwException(EXC_BUS_TIMEOUT); |
} |
reg = addr & 0x0FFF; |
if (reg == TIMER_CTRL) { |
data = timerCounters[dev].ctrl; |
} else |
if (addr == TIMER_DIVISOR) { |
data = timerDivisor; |
if (reg == TIMER_DIVISOR) { |
data = timerCounters[dev].divisor; |
} else |
if (reg == TIMER_COUNTER) { |
data = timerCounters[dev].counter; |
} else { |
/* illegal register */ |
throwException(EXC_BUS_TIMEOUT); |
62,33 → 83,41
|
|
void timerWrite(Word addr, Word data) { |
int dev, reg; |
|
if (debug) { |
cPrintf("\n**** TIMER WRITE to 0x%08X, data = 0x%08X ****\n", |
addr, data); |
} |
if (addr == TIMER_CTRL) { |
dev = addr >> 12; |
if (dev >= NUMBER_TMRCNT) { |
/* illegal device */ |
throwException(EXC_BUS_TIMEOUT); |
} |
reg = addr & 0x0FFF; |
if (reg == TIMER_CTRL) { |
if (data & TIMER_IEN) { |
timerCtrl |= TIMER_IEN; |
timerCounters[dev].ctrl |= TIMER_IEN; |
} else { |
timerCtrl &= ~TIMER_IEN; |
timerCounters[dev].ctrl &= ~TIMER_IEN; |
} |
if (data & TIMER_EXP) { |
timerCtrl |= TIMER_EXP; |
timerCounters[dev].ctrl |= TIMER_EXP; |
} else { |
timerCtrl &= ~TIMER_EXP; |
timerCounters[dev].ctrl &= ~TIMER_EXP; |
} |
if ((timerCtrl & TIMER_IEN) != 0 && |
(timerCtrl & TIMER_EXP) != 0) { |
if ((timerCounters[dev].ctrl & TIMER_IEN) != 0 && |
(timerCounters[dev].ctrl & TIMER_EXP) != 0) { |
/* raise timer interrupt */ |
cpuSetInterrupt(IRQ_TIMER); |
cpuSetInterrupt(timerCounters[dev].irq); |
} else { |
/* lower timer interrupt */ |
cpuResetInterrupt(IRQ_TIMER); |
cpuResetInterrupt(timerCounters[dev].irq); |
} |
} else |
if (addr == TIMER_DIVISOR) { |
timerDivisor = data; |
timerCounter = data; |
if (reg == TIMER_DIVISOR) { |
timerCounters[dev].divisor = data; |
timerCounters[dev].counter = data; |
} else { |
/* illegal register */ |
throwException(EXC_BUS_TIMEOUT); |
100,9 → 129,12
Timer *timer; |
void (*callback)(int param); |
int param; |
int i; |
|
/* increment current time, avoid overflow */ |
if (++currentTime == TIME_WRAP) { |
/* increment current time */ |
currentTime += CC_PER_INSTR; |
/* avoid overflow */ |
if (currentTime >= TIME_WRAP) { |
currentTime -= TIME_WRAP; |
timer = activeTimers; |
while (timer != NULL) { |
121,19 → 153,23
freeTimers = timer; |
(*callback)(param); |
} |
/* decrement counter and check if an interrupt must be raised */ |
if (--timerCounter == 0) { |
timerCounter = timerDivisor; |
timerCtrl |= TIMER_EXP; |
if (timerCtrl & TIMER_IEN) { |
/* raise timer interrupt */ |
cpuSetInterrupt(IRQ_TIMER); |
/* decrement counters and check if an interrupt must be raised */ |
for (i = 0; i < NUMBER_TMRCNT; i++) { |
if (timerCounters[i].counter <= CC_PER_INSTR) { |
timerCounters[i].counter += timerCounters[i].divisor - CC_PER_INSTR; |
timerCounters[i].ctrl |= TIMER_EXP; |
if (timerCounters[i].ctrl & TIMER_IEN) { |
/* raise timer interrupt */ |
cpuSetInterrupt(timerCounters[i].irq); |
} |
} else { |
timerCounters[i].counter -= CC_PER_INSTR; |
} |
} |
} |
|
|
void timerStart(int msec, void (*callback)(int param), int param) { |
void timerStart(int usec, void (*callback)(int param), int param) { |
Timer *timer; |
Timer *p; |
|
142,7 → 178,7
} |
timer = freeTimers; |
freeTimers = timer->next; |
timer->alarm = currentTime + msec; |
timer->alarm = currentTime + usec * CC_PER_USEC; |
timer->callback = callback; |
timer->param = param; |
if (activeTimers == NULL || |
165,6 → 201,7
|
void timerReset(void) { |
Timer *timer; |
int i; |
|
cPrintf("Resetting Timer...\n"); |
while (activeTimers != NULL) { |
173,6 → 210,12
timer->next = freeTimers; |
freeTimers = timer; |
} |
for (i = 0; i < NUMBER_TMRCNT; i++) { |
timerCounters[i].ctrl = 0x00000000; |
timerCounters[i].divisor = 0xFFFFFFFF; |
timerCounters[i].counter = 0xFFFFFFFF; |
timerCounters[i].irq = IRQ_TIMER_0 + i; |
} |
} |
|
|
195,7 → 238,12
void timerExit(void) { |
Timer *timer; |
|
timerReset(); |
while (activeTimers != NULL) { |
timer = activeTimers; |
activeTimers = timer->next; |
timer->next = freeTimers; |
freeTimers = timer; |
} |
while (freeTimers != NULL) { |
timer = freeTimers; |
freeTimers = timer->next; |
/shutdown.h
0,0 → 1,18
/* |
* shutdown.h -- shutdown device |
*/ |
|
|
#ifndef _SHUTDOWN_H_ |
#define _SHUTDOWN_H_ |
|
|
Word shutdownRead(Word addr); |
void shutdownWrite(Word addr, Word data); |
|
void shutdownReset(void); |
void shutdownInit(void); |
void shutdownExit(void); |
|
|
#endif /* _SHUTDOWN_H_ */ |
/main.c
20,6 → 20,7
#include "term.h" |
#include "disk.h" |
#include "output.h" |
#include "shutdown.h" |
#include "graph.h" |
|
|
150,6 → 151,7
termInit(numTerms); |
diskInit(diskName); |
outputInit(outputName); |
shutdownInit(); |
if (graphics) { |
graphInit(); |
} |
186,6 → 188,7
termExit(); |
diskExit(); |
outputExit(); |
shutdownExit(); |
graphExit(); |
cPrintf("ECO32 Simulator finished\n"); |
cExit(); |
/timer.h
9,11 → 9,13
|
#define TIMER_CTRL 0 /* timer control register */ |
#define TIMER_DIVISOR 4 /* timer divisor register */ |
#define TIMER_COUNTER 8 /* timer counter register */ |
|
#define TIMER_EXP 0x01 /* timer has expired */ |
#define TIMER_IEN 0x02 /* enable timer interrupt */ |
|
#define NUMBER_TIMERS 20 /* total number of simulation timers */ |
#define NUMBER_TIMERS 20 /* number of simulation timers */ |
#define NUMBER_TMRCNT 2 /* number of timer/counters */ |
|
|
Word timerRead(Word addr); |
20,7 → 22,7
void timerWrite(Word addr, Word data); |
|
void timerTick(void); |
void timerStart(int msec, void (*callback)(int param), int param); |
void timerStart(int usec, void (*callback)(int param), int param); |
|
void timerReset(void); |
void timerInit(void); |
/common.h
30,6 → 30,7
#define MAX_NTERMS 2 /* max number of terminals */ |
#define DISK_BASE 0x30400000 /* physical disk base address */ |
#define OUTPUT_BASE 0x3F000000 /* physical output device address */ |
#define SHUTDOWN_BASE 0x3F100000 /* physical shutdown device address */ |
#define GRAPH_BASE 0x3FC00000 /* physical grahics base address */ |
/* extends to end of address space */ |
|
37,7 → 38,8
#define OFFSET_MASK (PAGE_SIZE - 1) /* mask for offset within a page */ |
#define PAGE_MASK (~OFFSET_MASK) /* mask for page number */ |
|
#define INSTRS_PER_MSEC 1700 /* average execution speed */ |
#define CC_PER_USEC 50 /* clock cycles per microsecond */ |
#define CC_PER_INSTR 18 /* clock cycles per instruction */ |
|
|
typedef enum { false, true } Bool; /* truth values */ |