URL
https://opencores.org/ocsvn/eco32/eco32/trunk
Subversion Repositories eco32
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 245 to Rev 246
- ↔ Reverse comparison
Rev 245 → Rev 246
/eco32/trunk/sim/term.h
File deleted
/eco32/trunk/sim/term.c
File deleted
/eco32/trunk/sim/serial.c
0,0 → 1,314
/* |
* serial.c -- serial line simulation |
*/ |
|
|
#ifdef __linux__ |
#define _XOPEN_SOURCE |
#endif |
|
#include <stdio.h> |
#include <stdlib.h> |
#include <string.h> |
#include <setjmp.h> |
#include <signal.h> |
#include <sys/types.h> |
#include <sys/wait.h> |
#include <unistd.h> |
#include <fcntl.h> |
#include <termios.h> |
|
#include "common.h" |
#include "console.h" |
#include "error.h" |
#include "except.h" |
#include "cpu.h" |
#include "timer.h" |
#include "serial.h" |
|
|
/**************************************************************/ |
|
|
static Bool debug = false; |
|
|
typedef struct { |
pid_t pid; |
FILE *in; |
FILE *out; |
Word rcvrCtrl; |
Word rcvrData; |
int rcvrIRQ; |
Word xmtrCtrl; |
Word xmtrData; |
int xmtrIRQ; |
} Serial; |
|
|
static Serial serials[MAX_NSERIALS]; |
static int nSerials; |
|
|
/**************************************************************/ |
|
|
static void rcvrCallback(int dev) { |
int c; |
|
if (debug) { |
cPrintf("\n**** SERIAL RCVR CALLBACK ****\n"); |
} |
timerStart(SERIAL_RCVR_USEC, rcvrCallback, dev); |
c = fgetc(serials[dev].in); |
if (c == EOF) { |
/* no character typed */ |
return; |
} |
/* any character typed */ |
serials[dev].rcvrData = c & 0xFF; |
serials[dev].rcvrCtrl |= SERIAL_RCVR_RDY; |
if (serials[dev].rcvrCtrl & SERIAL_RCVR_IEN) { |
/* raise serial line rcvr interrupt */ |
cpuSetInterrupt(serials[dev].rcvrIRQ); |
} |
} |
|
|
static void xmtrCallback(int dev) { |
if (debug) { |
cPrintf("\n**** SERIAL XMTR CALLBACK ****\n"); |
} |
fputc(serials[dev].xmtrData & 0xFF, serials[dev].out); |
serials[dev].xmtrCtrl |= SERIAL_XMTR_RDY; |
if (serials[dev].xmtrCtrl & SERIAL_XMTR_IEN) { |
/* raise serial line xmtr interrupt */ |
cpuSetInterrupt(serials[dev].xmtrIRQ); |
} |
} |
|
|
/**************************************************************/ |
|
|
Word serialRead(Word addr) { |
int dev, reg; |
Word data; |
|
if (debug) { |
cPrintf("\n**** SERIAL READ from 0x%08X", addr); |
} |
dev = addr >> 12; |
if (dev >= nSerials) { |
/* illegal device */ |
throwException(EXC_BUS_TIMEOUT); |
} |
reg = addr & 0x0FFF; |
if (reg == SERIAL_RCVR_CTRL) { |
data = serials[dev].rcvrCtrl; |
} else |
if (reg == SERIAL_RCVR_DATA) { |
serials[dev].rcvrCtrl &= ~SERIAL_RCVR_RDY; |
if (serials[dev].rcvrCtrl & SERIAL_RCVR_IEN) { |
/* lower serial line rcvr interrupt */ |
cpuResetInterrupt(serials[dev].rcvrIRQ); |
} |
data = serials[dev].rcvrData; |
} else |
if (reg == SERIAL_XMTR_CTRL) { |
data = serials[dev].xmtrCtrl; |
} else |
if (reg == SERIAL_XMTR_DATA) { |
/* this register is write-only */ |
throwException(EXC_BUS_TIMEOUT); |
} else { |
/* illegal register */ |
throwException(EXC_BUS_TIMEOUT); |
} |
if (debug) { |
cPrintf(", data = 0x%08X ****\n", data); |
} |
return data; |
} |
|
|
void serialWrite(Word addr, Word data) { |
int dev, reg; |
|
if (debug) { |
cPrintf("\n**** SERIAL WRITE to 0x%08X, data = 0x%08X ****\n", |
addr, data); |
} |
dev = addr >> 12; |
if (dev >= nSerials) { |
/* illegal device */ |
throwException(EXC_BUS_TIMEOUT); |
} |
reg = addr & 0x0FFF; |
if (reg == SERIAL_RCVR_CTRL) { |
if (data & SERIAL_RCVR_IEN) { |
serials[dev].rcvrCtrl |= SERIAL_RCVR_IEN; |
} else { |
serials[dev].rcvrCtrl &= ~SERIAL_RCVR_IEN; |
} |
if (data & SERIAL_RCVR_RDY) { |
serials[dev].rcvrCtrl |= SERIAL_RCVR_RDY; |
} else { |
serials[dev].rcvrCtrl &= ~SERIAL_RCVR_RDY; |
} |
if ((serials[dev].rcvrCtrl & SERIAL_RCVR_IEN) != 0 && |
(serials[dev].rcvrCtrl & SERIAL_RCVR_RDY) != 0) { |
/* raise serial line rcvr interrupt */ |
cpuSetInterrupt(serials[dev].rcvrIRQ); |
} else { |
/* lower serial line rcvr interrupt */ |
cpuResetInterrupt(serials[dev].rcvrIRQ); |
} |
} else |
if (reg == SERIAL_RCVR_DATA) { |
/* this register is read-only */ |
throwException(EXC_BUS_TIMEOUT); |
} else |
if (reg == SERIAL_XMTR_CTRL) { |
if (data & SERIAL_XMTR_IEN) { |
serials[dev].xmtrCtrl |= SERIAL_XMTR_IEN; |
} else { |
serials[dev].xmtrCtrl &= ~SERIAL_XMTR_IEN; |
} |
if (data & SERIAL_XMTR_RDY) { |
serials[dev].xmtrCtrl |= SERIAL_XMTR_RDY; |
} else { |
serials[dev].xmtrCtrl &= ~SERIAL_XMTR_RDY; |
} |
if ((serials[dev].xmtrCtrl & SERIAL_XMTR_IEN) != 0 && |
(serials[dev].xmtrCtrl & SERIAL_XMTR_RDY) != 0) { |
/* raise serial line xmtr interrupt */ |
cpuSetInterrupt(serials[dev].xmtrIRQ); |
} else { |
/* lower serial line xmtr interrupt */ |
cpuResetInterrupt(serials[dev].xmtrIRQ); |
} |
} else |
if (reg == SERIAL_XMTR_DATA) { |
serials[dev].xmtrData = data & 0xFF; |
serials[dev].xmtrCtrl &= ~SERIAL_XMTR_RDY; |
if (serials[dev].xmtrCtrl & SERIAL_XMTR_IEN) { |
/* lower serial line xmtr interrupt */ |
cpuResetInterrupt(serials[dev].xmtrIRQ); |
} |
timerStart(SERIAL_XMTR_USEC, xmtrCallback, dev); |
} else { |
/* illegal register */ |
throwException(EXC_BUS_TIMEOUT); |
} |
} |
|
|
/**************************************************************/ |
|
|
void serialReset(void) { |
int i; |
|
cPrintf("Resetting Serial Lines...\n"); |
for (i = 0; i < nSerials; i++) { |
serials[i].rcvrCtrl = 0; |
serials[i].rcvrData = 0; |
serials[i].rcvrIRQ = IRQ_SERIAL_0_RCVR + 2 * i; |
timerStart(SERIAL_RCVR_USEC, rcvrCallback, i); |
serials[i].xmtrCtrl = SERIAL_XMTR_RDY; |
serials[i].xmtrData = 0; |
serials[i].xmtrIRQ = IRQ_SERIAL_0_XMTR + 2 * i; |
} |
} |
|
|
static void makeRaw(int fd) { |
struct termios t; |
|
tcgetattr(fd, &t); |
t.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON); |
t.c_oflag &= ~OPOST; |
t.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); |
t.c_cflag &= ~(CSIZE|PARENB); |
t.c_cflag |= CS8; |
tcsetattr(fd, TCSANOW, &t); |
} |
|
|
void serialInit(int numSerials, Bool connectTerminals[]) { |
int i; |
int master; |
char slavePath[100]; |
int slave; |
char termTitle[100]; |
char termSlave[100]; |
|
nSerials = numSerials; |
for (i = 0; i < nSerials; i++) { |
/* open pseudo terminal */ |
master = open("/dev/ptmx", O_RDWR | O_NONBLOCK); |
if (master < 0) { |
error("cannot open pseudo terminal master for serial line %d", i); |
} |
grantpt(master); |
unlockpt(master); |
strcpy(slavePath, ptsname(master)); |
if (debug) { |
cPrintf("pseudo terminal %d: master fd = %d, slave path = '%s'\n", |
i, master, slavePath); |
} |
if (connectTerminals[i]) { |
/* connect a terminal to the serial line */ |
/* i.e., fork and exec a new xterm process */ |
serials[i].pid = fork(); |
if (serials[i].pid < 0) { |
error("cannot fork xterm process for serial line %d", i); |
} |
if (serials[i].pid == 0) { |
/* terminal process */ |
setpgid(0, 0); |
close(master); |
/* open and configure pseudo terminal slave */ |
slave = open(slavePath, O_RDWR | O_NONBLOCK); |
if (slave < 0) { |
error("cannot open pseudo terminal slave '%s'\n", slavePath); |
} |
makeRaw(slave); |
/* exec xterm */ |
sprintf(termTitle, "ECO32 Terminal %d", i); |
sprintf(termSlave, "-Sab%d", slave); |
execlp("xterm", "xterm", "-title", termTitle, termSlave, NULL); |
error("cannot exec xterm process for serial line %d", i); |
} |
} else { |
/* leave serial line unconnected */ |
serials[i].pid = 0; |
cPrintf("Serial line %d can be accessed by opening device '%s'.\n", |
i, slavePath); |
} |
fcntl(master, F_SETFL, O_NONBLOCK); |
serials[i].in = fdopen(master, "r"); |
setvbuf(serials[i].in, NULL, _IONBF, 0); |
serials[i].out = fdopen(master, "w"); |
setvbuf(serials[i].out, NULL, _IONBF, 0); |
if (connectTerminals[i]) { |
/* skip the window id written by xterm */ |
while (fgetc(serials[i].in) != '\n') ; |
} |
} |
serialReset(); |
} |
|
|
void serialExit(void) { |
int i; |
|
/* kill and wait for all xterm processes */ |
for (i = 0; i < nSerials; i++) { |
if (serials[i].pid > 0) { |
kill(serials[i].pid, SIGKILL); |
waitpid(serials[i].pid, NULL, 0); |
} |
} |
} |
/eco32/trunk/sim/serial.h
0,0 → 1,32
/* |
* serial.h -- serial line simulation |
*/ |
|
|
#ifndef _SERIAL_H_ |
#define _SERIAL_H_ |
|
|
#define SERIAL_RCVR_CTRL 0 /* receiver control register */ |
#define SERIAL_RCVR_DATA 4 /* receiver data register */ |
#define SERIAL_XMTR_CTRL 8 /* transmitter control register */ |
#define SERIAL_XMTR_DATA 12 /* transmitter data register */ |
|
#define SERIAL_RCVR_RDY 0x01 /* receiver has a character */ |
#define SERIAL_RCVR_IEN 0x02 /* enable receiver interrupt */ |
#define SERIAL_RCVR_USEC 2000 /* input checking interval */ |
|
#define SERIAL_XMTR_RDY 0x01 /* transmitter accepts a character */ |
#define SERIAL_XMTR_IEN 0x02 /* enable transmitter interrupt */ |
#define SERIAL_XMTR_USEC 1042 /* output speed */ |
|
|
Word serialRead(Word addr); |
void serialWrite(Word addr, Word data); |
|
void serialReset(void); |
void serialInit(int numSerials, Bool connectTerminals[]); |
void serialExit(void); |
|
|
#endif /* _SERIAL_H_ */ |
/eco32/trunk/sim/error.c
16,7 → 16,7
#include "memory.h" |
#include "timer.h" |
#include "dspkbd.h" |
#include "term.h" |
#include "serial.h" |
#include "disk.h" |
#include "output.h" |
#include "shutdown.h" |
32,7 → 32,7
timerExit(); |
displayExit(); |
keyboardExit(); |
termExit(); |
serialExit(); |
diskExit(); |
outputExit(); |
shutdownExit(); |
/eco32/trunk/sim/cpu.h
7,14 → 7,14
#define _CPU_H_ |
|
|
#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 */ |
#define IRQ_TERM_1_XMTR 2 /* terminal 1 transmitter interrupt */ |
#define IRQ_TERM_0_RCVR 1 /* terminal 0 receiver interrupt */ |
#define IRQ_TERM_0_XMTR 0 /* terminal 0 transmitter 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_SERIAL_1_RCVR 3 /* line 1 receiver interrupt */ |
#define IRQ_SERIAL_1_XMTR 2 /* line 1 transmitter interrupt */ |
#define IRQ_SERIAL_0_RCVR 1 /* line 0 receiver interrupt */ |
#define IRQ_SERIAL_0_XMTR 0 /* line 0 transmitter interrupt */ |
|
#define PSW_V 0x08000000 /* interrupt vector bit in PSW */ |
#define PSW_UM 0x04000000 /* user mode enable bit in PSW */ |
/eco32/trunk/sim/Makefile
11,8 → 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 shutdown.c \ |
graph.c |
timer.c dspkbd.c serial.c disk.c output.c \ |
shutdown.c graph.c |
OBJS = $(patsubst %.c,%.o,$(SRCS)) |
BIN = sim |
|
/eco32/trunk/sim/memory.c
16,7 → 16,7
#include "memory.h" |
#include "timer.h" |
#include "dspkbd.h" |
#include "term.h" |
#include "serial.h" |
#include "disk.h" |
#include "output.h" |
#include "shutdown.h" |
63,8 → 63,8
data = keyboardRead(pAddr & IO_REG_MASK); |
return data; |
} |
if ((pAddr & IO_DEV_MASK) == TERM_BASE) { |
data = termRead(pAddr & IO_REG_MASK); |
if ((pAddr & IO_DEV_MASK) == SERIAL_BASE) { |
data = serialRead(pAddr & IO_REG_MASK); |
return data; |
} |
if ((pAddr & IO_DEV_MASK) == DISK_BASE) { |
153,8 → 153,8
keyboardWrite(pAddr & IO_REG_MASK, data); |
return; |
} |
if ((pAddr & IO_DEV_MASK) == TERM_BASE) { |
termWrite(pAddr & IO_REG_MASK, data); |
if ((pAddr & IO_DEV_MASK) == SERIAL_BASE) { |
serialWrite(pAddr & IO_REG_MASK, data); |
return; |
} |
if ((pAddr & IO_DEV_MASK) == DISK_BASE) { |
/eco32/trunk/sim/shutdown.c
15,7 → 15,7
#include "memory.h" |
#include "timer.h" |
#include "dspkbd.h" |
#include "term.h" |
#include "serial.h" |
#include "disk.h" |
#include "output.h" |
#include "shutdown.h" |
36,7 → 36,7
timerExit(); |
displayExit(); |
keyboardExit(); |
termExit(); |
serialExit(); |
diskExit(); |
outputExit(); |
shutdownExit(); |
/eco32/trunk/sim/command.c
20,7 → 20,7
#include "memory.h" |
#include "timer.h" |
#include "dspkbd.h" |
#include "term.h" |
#include "serial.h" |
#include "disk.h" |
#include "output.h" |
#include "shutdown.h" |
855,7 → 855,7
timerReset(); |
displayReset(); |
keyboardReset(); |
termReset(); |
serialReset(); |
diskReset(); |
outputReset(); |
shutdownReset(); |
/eco32/trunk/sim/main.c
17,7 → 17,7
#include "memory.h" |
#include "timer.h" |
#include "dspkbd.h" |
#include "term.h" |
#include "serial.h" |
#include "disk.h" |
#include "output.h" |
#include "shutdown.h" |
34,9 → 34,9
fprintf(stderr, " [-r <rom>] set ROM image file name\n"); |
fprintf(stderr, " [-d <disk>] set disk image file name\n"); |
fprintf(stderr, " [-s <n>] install n serial lines (0-%d)\n", |
MAX_NTERMS); |
MAX_NSERIALS); |
fprintf(stderr, " [-t <k>] connect terminal to line k (0-%d)\n", |
MAX_NTERMS - 1); |
MAX_NSERIALS - 1); |
fprintf(stderr, " [-g] install graphics controller\n"); |
fprintf(stderr, " [-c] install console\n"); |
fprintf(stderr, " [-o <file>] bind output device to file\n"); |
58,8 → 58,8
unsigned int loadAddr; |
char *romName; |
char *diskName; |
int numTerms; |
Bool hasTerm[MAX_NTERMS]; |
int numSerials; |
Bool connectTerminals[MAX_NSERIALS]; |
Bool graphics; |
Bool console; |
char *outputName; |
73,9 → 73,9
loadAddr = 0; |
romName = NULL; |
diskName = NULL; |
numTerms = 0; |
for (j = 0; j < MAX_NTERMS; j++) { |
hasTerm[j] = false; |
numSerials = 0; |
for (j = 0; j < MAX_NSERIALS; j++) { |
connectTerminals[j] = false; |
} |
graphics = false; |
console = false; |
132,10 → 132,10
if (i == argc - 1) { |
usage(argv[0]); |
} |
numTerms = strtol(argv[++i], &endp, 10); |
numSerials = strtol(argv[++i], &endp, 10); |
if (*endp != '\0' || |
numTerms < 0 || |
numTerms > MAX_NTERMS) { |
numSerials < 0 || |
numSerials > MAX_NSERIALS) { |
usage(argv[0]); |
} |
break; |
146,10 → 146,10
j = strtol(argv[++i], &endp, 10); |
if (*endp != '\0' || |
j < 0 || |
j > MAX_NTERMS - 1) { |
j > MAX_NSERIALS - 1) { |
usage(argv[0]); |
} |
hasTerm[j] = true; |
connectTerminals[j] = true; |
break; |
case 'g': |
graphics = true; |
180,7 → 180,7
displayInit(); |
keyboardInit(); |
} |
termInit(numTerms, hasTerm); |
serialInit(numSerials, connectTerminals); |
diskInit(diskName); |
outputInit(outputName); |
shutdownInit(); |
217,7 → 217,7
timerExit(); |
displayExit(); |
keyboardExit(); |
termExit(); |
serialExit(); |
diskExit(); |
outputExit(); |
shutdownExit(); |
/eco32/trunk/sim/common.h
26,8 → 26,8
#define TIMER_BASE 0x30000000 /* physical timer base address */ |
#define DISPLAY_BASE 0x30100000 /* physical display base address */ |
#define KEYBOARD_BASE 0x30200000 /* physical keyboard base address */ |
#define TERM_BASE 0x30300000 /* physical terminal base address */ |
#define MAX_NTERMS 2 /* max number of terminals */ |
#define SERIAL_BASE 0x30300000 /* physical serial line base address */ |
#define MAX_NSERIALS 2 /* max number of serial lines */ |
#define DISK_BASE 0x30400000 /* physical disk base address */ |
#define OUTPUT_BASE 0x3F000000 /* physical output device address */ |
#define SHUTDOWN_BASE 0x3F100000 /* physical shutdown device address */ |