[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[openrisc] [PATCH] Would you like to have UART0 in a xterm ?




Hello everybody !

Here is a patch to improve simulator interraction with host.
Interraction is made through "channels".  It is possible to associate
a channel with a peripheral (only UART for the momment).  It obseletes
txfile and rxfile (UART only for now).  Sorry to break compatibility :-(

Did I tell you it is for UART only for now ?!

sim.cfg have to change in the following way :

section uart
  enabled = 1
  nuarts = 1

  device 0
    baseaddr = 0x90000000
    irq = 2
    jitter = -1
    16550 = 1
    /*
     * txfile = "oldway.tx"
     * rxfile = "oldway.rx"
     */
    channel = "file:newway.rx,newway.tx"
  enddevice
end


One thing I like to do is:

section uart
  enabled = 1
  nuarts = 1

  device 0
    baseaddr = 0x90000000
    irq = 2
    jitter = -1
    16550 = 1
    channel = "file:/dev/tty10"
  enddevice
end

But make sure the user running the simulation have the appropriate
permission on /dev/tty10.  (Do Ctrl-Atl-F10 to see result and enjoy!)

Two other kind of channels are also available.  The first one use file
descriptors provided at sim startup.  To configure do:

section uart
  enabled = 1
  nuarts = 1

  device 0
    baseaddr = 0x90000000
    irq = 2
    jitter = -1
    16550 = 1
    channel = "fd:3,4"
  enddevice
end

And launch sim this way:
$ or32-uclinux-sim linux 3< uart.rx 4> uart.tx


It is also possible to specify a fifo instead:

section uart
  enabled = 1
  nuarts = 1

  device 0
    baseaddr = 0x90000000
    irq = 2
    jitter = -1
    16550 = 1
    channel = "fd:3"
  enddevice
end

Launch with:
$ mkfifo allo
$ or32-uclinux-sim linux 3<> allo


But the most useful one is with:

section uart
  enabled = 1
  nuarts = 1

  device 0
    baseaddr = 0x90000000
    irq = 2
    jitter = -1
    16550 = 1
    channel = "xterm"
  enddevice
end


Enjoy!

Richard Prescott

diff -urN -X dontdiff or1ksim/BUGS or1ksim.richard/BUGS
--- or1ksim/BUGS	Thu Oct 24 11:56:11 2002
+++ or1ksim.richard/BUGS	Fri Aug  2 07:25:31 2002
@@ -13,4 +13,4 @@
 
 * cuc is under heavy development and is not stable yet!!!
 * cuc: entering cuc, leaving it and re-entering causes to double profiling information
-* channels/xterm: xterm get closed when 'Ctrl-C'ing the master console
+
diff -urN -X dontdiff or1ksim/Makefile.am or1ksim.richard/Makefile.am
--- or1ksim/Makefile.am	Thu Jul  4 12:35:42 2002
+++ or1ksim.richard/Makefile.am	Tue Oct 22 16:16:05 2002
@@ -14,6 +14,6 @@
 	cpu/or1k/libor1k.a support/libsupport.a mmu/libmmu.a \
 	bpb/libbpb.a cache/libcache.a peripheral/libperipheral.a \
 	tick/libtick.a pm/libpm.a pic/libpic.a debug/libdebug.a \
-	vapi/libvapi.a cuc/libcuc.a
+	vapi/libvapi.a cuc/libcuc.a peripheral/channels/libchannels.a
 
 sim_LDFLAGS	= #-lreadline
diff -urN -X dontdiff or1ksim/configure.in or1ksim.richard/configure.in
--- or1ksim/configure.in	Tue Jul 30 04:26:59 2002
+++ or1ksim.richard/configure.in	Tue Oct 22 15:57:14 2002
@@ -219,6 +219,7 @@
 INCLUDES="-I\${top_srcdir} -I\${top_srcdir}/cpu/common -I\${top_srcdir}/cpu/or1k \
 -I\${top_srcdir}/cpu/$CPU_ARCH -I\${top_srcdir}/cache -I\${top_srcdir}/mmu \
 -I\${top_srcdir}/bpb -I\${top_srcdir}/peripheral -I\${top_srcdir}/tick \
+-I\${top_srcdir}/peripheral/channels \
 -I\${top_srcdir}/pm -I\${top_srcdir}/pic -I\${top_srcdir}/debug \
 -I\${top_srcdir}/vapi -I\${top_srcdir}/support -I\${top_srcdir}/cuc"
 AC_SUBST(INCLUDES)
@@ -226,8 +227,8 @@
 AC_OUTPUT([Makefile bpb/Makefile cache/Makefile cpu/Makefile
 	cpu/common/Makefile cpu/or32/Makefile cuc/Makefile
 	cpu/or1k/Makefile cpu/dlx/Makefile debug/Makefile
-	support/Makefile mmu/Makefile peripheral/Makefile tick/Makefile
-	pm/Makefile pic/Makefile debug/Makefile vapi/Makefile],
+	support/Makefile mmu/Makefile peripheral/Makefile peripheral/channels/Makefile
+	tick/Makefile pm/Makefile pic/Makefile debug/Makefile vapi/Makefile],
 [
 # Makefile uses this timestamp file to record whether config.h is up to date.
 echo > stamp-h
diff -urN -X dontdiff or1ksim/peripheral/16450.c or1ksim.richard/peripheral/16450.c
--- or1ksim/peripheral/16450.c	Fri Aug 23 04:40:14 2002
+++ or1ksim.richard/peripheral/16450.c	Tue Oct 22 19:50:51 2002
@@ -37,10 +37,12 @@
 #include "pic.h"
 #include "vapi.h"
 #include "sched.h"
+#include "channel.h"
 
 #define MIN(a,b) ((a) < (b) ? (a) : (b))
 
-static struct dev_16450 uarts[MAX_UARTS];
+static struct dev_16450 uarts[MAX_UARTS];			/* simulation info */
+static struct channel * channels[MAX_UARTS] = { NULL, };	/* emulation info */
 static int thre_int;
 
 /* Number of clock cycles (one clock cycle is one call to the uart_clock())
@@ -308,8 +310,8 @@
       debug (4, "vapi_send (%08x, %08x)\n", config.uarts[uart].vapi_id, data);
       vapi_send (config.uarts[uart].vapi_id, data);
     } else {
-      fputc((int)(uarts[uart].iregs.txser & 0xFF), uarts[uart].txfs);
-      fflush(uarts[uart].txfs);
+      char buffer[1] = { uarts[uart].iregs.txser & 0xFF };
+      channel_write(channels[uart], buffer, 1);
     }
   }
   uarts[uart].istat.txser_full = 0;
@@ -337,14 +339,14 @@
 void uart_clock16 (int i)
 {
   int retval;
-  
+
   /* Schedule for later */
   SCHED_ADD (uart_clock16, i, runtime.sim.cycles + UART_CLOCK_DIVIDER);
   
   /* If VAPI is not selected, UART communicates with two file streams;
      if VAPI is selected, we use VAPI streams.  */
   /* if txfs is corrupted, skip this uart. */
-  if (!config.uarts[i].vapi_id && !uarts[i].txfs) return;
+  if (!config.uarts[i].vapi_id && !channel_ok(channels[i])) return;
   
   if (uarts[i].vapi.next_break_cnt >= 0)
     if (--uarts[i].vapi.next_break_cnt < 0) {
@@ -433,10 +435,17 @@
       if(uarts[i].istat.rxser_full == 0) {
         if (uarts[i].slowdown)
           uarts[i].slowdown--;
-        else if((retval = fgetc(uarts[i].rxfs)) != EOF) {
-          uarts[i].iregs.rxser = (char)retval;
-          uarts[i].istat.rxser_full = 1;
-        } else uarts[i].slowdown = UART_FGETC_SLOWDOWN;
+        else {
+	  char buffer[1];
+	  retval = channel_read(channels[i], buffer, 1);
+	  if(retval < 0)
+		  perror(config.uarts[i].channel);
+	  else if(retval > 0) {
+            uarts[i].iregs.rxser = buffer[0];
+            uarts[i].istat.rxser_full = 1;
+	  } else
+            uarts[i].slowdown = UART_FGETC_SLOWDOWN;
+	}
       }
     } else { /* VAPI */
       int received = 0;
@@ -563,24 +572,25 @@
       if ((config.uarts[i].vapi_id & VAPI_DEVICE_ID) != i) {
         fprintf (stderr, "ERROR: Wrong vapi_id (0x%x) for uart %i, last byte is required to be %02x; ignoring.\n", config.uarts[i].vapi_id, i, i);
         config.uarts[i].vapi_id = 0;
-        uarts[i].txfs = 0;
       } else {
         vapi_install_handler (config.uarts[i].vapi_id, uart_vapi_read);
         register_memoryarea(config.uarts[i].baseaddr, UART_ADDR_SPACE, 1, 0, uart_read_byte, uart_write_byte);
       }
-    } else 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+"))) {
-        debug (0, "WARNING: UART%d has problems with RX file stream.\n", i);
+    } else if (config.uarts[i].channel[0]) { /* MM: Try to create stream.  */
+      if(channels[i])
+        channel_close(channels[i]);
+      else
+        channels[i] = channel_init(config.uarts[i].channel);
+      if(channel_open(channels[i]) < 0) {
+        debug (0, "WARNING: UART%d has problems with channel \"%s\".\n", i, config.uarts[i].channel);
         continue;
       }
-      uarts[i].txfs = fopen(config.uarts[i].txfile, "a");
-      if (uarts[i].rxfs && uarts[i].txfs && config.sim.verbose) {
+      if (config.sim.verbose)
         PRINTF("UART%d at 0x%.8x uses ", i, config.uarts[i].baseaddr);
-        PRINTF("%s for RX and %s for TX.\n", config.uarts[i].rxfile, config.uarts[i].txfile);
-      } else
-        debug (1, "WARNING: UART%d has problems with TX file stream.\n", i);
       register_memoryarea(config.uarts[i].baseaddr, UART_ADDR_SPACE, 1, 0, uart_read_byte, uart_write_byte);
+    } else {
+        debug (0, "WARNING: UART%d has no vapi nor channel specified\n", i);
+	continue;
     }
     
     if (config.uarts[i].uart16550)
@@ -634,7 +644,9 @@
     PRINTF("Using IRQ%i\n", config.uarts[i].irq);
     if (config.uarts[i].vapi_id)
       PRINTF ("Connected to vapi ID=%x\n\n", config.uarts[i].vapi_id);
+    /* TODO: replace by a channel_status
     else
       PRINTF("RX fs: %p  TX fs: %p\n\n", uarts[i].rxfs, uarts[i].txfs);
+    */
   }
 }
diff -urN -X dontdiff or1ksim/peripheral/16450.h or1ksim.richard/peripheral/16450.h
--- or1ksim/peripheral/16450.h	Wed Apr 10 03:40:31 2002
+++ or1ksim.richard/peripheral/16450.h	Tue Oct 22 16:40:27 2002
@@ -95,10 +95,6 @@
 
   /* fgetc slowdown */
   int slowdown;
-  
-  /* Required by standard file streams */
-  FILE * rxfs;
-  FILE * txfs;
 };
 
 /*
diff -urN -X dontdiff or1ksim/peripheral/Makefile.am or1ksim.richard/peripheral/Makefile.am
--- or1ksim/peripheral/Makefile.am	Thu Aug 15 17:38:23 2002
+++ or1ksim.richard/peripheral/Makefile.am	Tue Oct 22 11:41:26 2002
@@ -18,6 +18,8 @@
 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 #
 
+SUBDIRS = channels
+
 noinst_LIBRARIES = libperipheral.a
 libperipheral_a_SOURCES = \
 16450.c                   \
diff -urN -X dontdiff or1ksim/peripheral/channels/Makefile.am or1ksim.richard/peripheral/channels/Makefile.am
--- or1ksim/peripheral/channels/Makefile.am	Wed Dec 31 19:00:00 1969
+++ or1ksim.richard/peripheral/channels/Makefile.am	Thu Oct 24 10:34:26 2002
@@ -0,0 +1,27 @@
+# Makefile -- Makefile for peripherals channels to host
+# Copyright (C) 2002 Richard Prescott <rip@step.polymtl.ca>
+#
+# 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.
+#
+
+noinst_LIBRARIES = libchannels.a
+libchannels_a_SOURCES = \
+channel.c		\
+fd.c			\
+file.c			\
+generic.c		\
+xterm.c
diff -urN -X dontdiff or1ksim/peripheral/channels/channel.c or1ksim.richard/peripheral/channels/channel.c
--- or1ksim/peripheral/channels/channel.c	Wed Dec 31 19:00:00 1969
+++ or1ksim.richard/peripheral/channels/channel.c	Thu Oct 24 10:21:30 2002
@@ -0,0 +1,243 @@
+/* channel.h -- Definition of types and structures for 
+   peripheral to communicate with host.  Addapted from UML.
+   
+   Copyright (C) 2002 Richard Prescott <rip@step.polymtl.ca>
+
+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. */
+
+#define _GNU_SOURCE	/* for strndup */
+
+#include <stdio.h>	/* perror */
+#include <stdlib.h>	/* exit */
+#include <malloc.h>	/* calloc, free */
+#include <string.h>	/* strndup, strcmp, strlen, strchr */
+#include <errno.h>	/* errno */
+
+#include "channel.h"
+
+struct channel_factory
+{
+	const char * name;
+	const struct channel_ops * ops;
+	struct channel_factory * next;
+};
+
+extern struct channel_ops fd_channel_ops, file_channel_ops, xterm_channel_ops;
+
+static struct channel_factory preloaded[] =
+{
+	{ "fd",     &fd_channel_ops,     &preloaded[1] },
+	{ "file",   &file_channel_ops,   &preloaded[2] },
+	{ "xterm",  &xterm_channel_ops,  NULL          }
+};
+
+static struct channel_factory * head = &preloaded[0];
+
+static struct channel_factory * find_channel_factory(const char * name);
+
+struct channel * channel_init(const char * descriptor)
+{
+	struct channel * retval;
+	struct channel_factory * current;
+	char * args, * name;
+	int count;
+
+	if(!descriptor)
+	{
+		return NULL;
+	}
+
+	retval = (struct channel*)calloc(1, sizeof(struct channel));
+
+	if(!retval)
+	{
+		perror(descriptor);
+		exit(1);
+	}
+
+	args = strchr(descriptor, ':');
+
+	if(args)
+	{
+		count = args - descriptor;
+		args++;
+	}
+	else
+	{
+		count = strlen(descriptor);
+	}
+
+	name = (char*)strndup(descriptor, count);
+
+	if(!name)
+	{
+		perror(name);
+		exit(1);
+	}
+
+	current = find_channel_factory(name);
+	
+	if(!current)
+	{
+		errno = ENODEV;
+		perror(descriptor);
+		exit(1);
+	}
+
+	retval->ops = current->ops;
+
+	free(name);
+
+	if(!retval->ops)
+	{
+		errno = ENODEV;
+		perror(descriptor);
+		exit(1);
+	}
+
+	if(retval->ops->init)
+	{
+		retval->data = (retval->ops->init)(args);
+
+		if(!retval->data)
+		{
+			perror(descriptor);
+			exit(1);
+		}
+	}
+
+	return retval;
+}
+
+int channel_open(struct channel * channel)
+{
+	if(channel && channel->ops && channel->ops->open)
+	{
+		return (channel->ops->open)(channel->data);
+	}
+	errno = ENOSYS;
+	return -1;
+}
+
+int channel_read(struct channel * channel, char * buffer, int size)
+{
+	if(channel && channel->ops && channel->ops->read)
+	{
+		return (channel->ops->read)(channel->data, buffer, size);
+	}
+	errno = ENOSYS;
+	return -1;
+}
+
+int channel_write(struct channel * channel, const char * buffer, int size)
+{
+	if(channel && channel->ops && channel->ops->write)
+	{
+		return (channel->ops->write)(channel->data, buffer, size);
+	}
+	errno = ENOSYS;
+	return -1;
+}
+
+void channel_close(struct channel * channel)
+{
+	if(channel && channel->ops && channel->ops->close)
+	{
+		(channel->ops->close)(channel->data);
+	}
+}
+
+void channel_free(struct channel * channel)
+{
+	if(channel && channel->ops && channel->ops->close)
+	{
+		(channel->ops->free)(channel->data);
+		free(channel);
+	}
+}
+
+
+int channel_ok(struct channel * channel)
+{
+	if(channel && channel->ops)
+	{
+		if(channel->ops->isok)
+			return (channel->ops->isok)(channel->data);
+		else
+			return 1;
+	}
+	return 0;
+}
+
+char * channel_status(struct channel * channel)
+{
+	if(channel && channel->ops && channel->ops->status)
+	{
+		return (channel->ops->status)(channel->data);
+	}
+	return "";
+}
+
+
+
+static struct channel_factory * find_channel_factory(const char * name)
+{
+	struct channel_factory * current = head;
+
+	current = head;
+	while(current && strcmp(current->name, name))
+	{
+		current = current->next;
+	}
+
+	return current;
+}
+
+int register_channel(const char * name, const struct channel_ops * ops)
+{
+	struct channel_factory * new;
+
+
+	if(find_channel_factory(name))
+	{
+		errno = EEXIST;
+		perror(name);
+		exit(1);
+	}
+
+	new = (struct channel_factory *)calloc(1, sizeof(struct channel_factory));
+
+	if(!new)
+	{
+		perror(name);
+		exit(1);
+	}
+
+	new->name = name;
+	new->ops  = ops;
+	new->next = head;
+	head = new;
+
+	return (int)new;	/* dummy */
+}
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
+
diff -urN -X dontdiff or1ksim/peripheral/channels/channel.h or1ksim.richard/peripheral/channels/channel.h
--- or1ksim/peripheral/channels/channel.h	Wed Dec 31 19:00:00 1969
+++ or1ksim.richard/peripheral/channels/channel.h	Tue Oct 22 17:13:10 2002
@@ -0,0 +1,68 @@
+/* channel.h -- Definition of types and structures for 
+   peripheral to communicate with host.  Addapted from UML.
+   
+   Copyright (C) 2002 Richard Prescott <rip@step.polymtl.ca>
+
+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. */
+
+#ifndef CHANNEL_H
+#define CHANNEL_H
+
+struct channel_ops
+{
+	void *(*init)(const char *);
+	int (*open)(void *);
+	void (*close)(void *);
+	int (*read)(void *, char *, int);
+	int (*write)(void *, const char *, int);
+	void (*free)(void *);
+	int (*isok)(void*);
+	char* (*status)(void*);
+};
+
+struct channel
+{
+	const struct channel_ops * ops;
+	void * data;
+};
+
+
+struct channel * channel_init(const char * descriptor);
+/* read operation in non-blocking */
+int channel_open(struct channel * channel);
+int channel_read(struct channel * channel, char * buffer, int size);
+int channel_write(struct channel * channel, const char * buffer, int size);
+void channel_free(struct channel * channel);
+int channel_ok(struct channel * channel);
+char * channel_status(struct channel * channel);
+
+void channel_close(struct channel * channel);
+
+int register_channel(const char * name, const struct channel_ops * ops);
+/* TODO: int unregister_channel(const char * name); */
+
+/* for those who wants to automatically register at startup */
+#define REGISTER_CHANNEL(NAME,OPS) \
+  static int NAME ## _dummy_register = register_channel(#NAME, OPS)
+
+#endif
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff -urN -X dontdiff or1ksim/peripheral/channels/fd.c or1ksim.richard/peripheral/channels/fd.c
--- or1ksim/peripheral/channels/fd.c	Wed Dec 31 19:00:00 1969
+++ or1ksim.richard/peripheral/channels/fd.c	Thu Oct 24 11:47:12 2002
@@ -0,0 +1,154 @@
+/* fd.c -- Definition of functions and structures for 
+   peripheral to communicate with host through file descriptors
+   
+   Copyright (C) 2002 Richard Prescott <rip@step.polymtl.ca>
+
+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. */
+
+#include <sys/time.h>	/* struct timeval */
+#include <sys/types.h>	/* fd_set */
+#include <stdio.h>	/* perror */
+#include <stdlib.h>	/* atoi */
+#include <unistd.h>	/* read, write, select */
+#include <malloc.h>	/* calloc, free */
+#include <string.h>	/* strchr */
+#include <errno.h>	/* errno */
+
+#include "channel.h"
+#include "generic.h"
+#include "fd.h"
+
+static void * fd_init(const char * args)
+{
+	struct fd_channel * retval;
+
+	retval = (struct fd_channel*)calloc(1, sizeof(struct fd_channel));
+
+	if(!retval)
+	{
+		return NULL;
+	}
+
+
+	retval->fdin  = atoi(args);	/* so 0 if garbage */
+					/* TODO: strtoul */
+
+	args = strchr(args, ',');
+
+	if(args)
+	{
+		retval->fdout  = atoi(args+1);
+	}
+	else
+	{
+		retval->fdout  = retval->fdin;
+	}
+
+	return (void*)retval;
+}
+
+int fd_read(void * data, char * buffer, int size)
+{
+	struct fd_channel * fds = (struct fd_channel *)data;
+	struct timeval timeout = { 0, 0 };
+	fd_set rfds;
+	int retval;
+
+	if(!fds)
+	{
+		errno = ENODEV;
+		return -1;
+	}
+
+	FD_ZERO(&rfds);
+	FD_SET(fds->fdin, &rfds);
+
+	retval = select(fds->fdin+1, &rfds, NULL, NULL, &timeout);
+
+	if(retval <= 0)
+		return retval;
+
+	return read(fds->fdin, buffer, size);
+}
+
+int fd_write(void * data, const char * buffer, int size)
+{
+	struct fd_channel * fds = (struct fd_channel *)data;
+	if(fds)
+	{
+		return write(fds->fdout, buffer, size);
+	}
+	errno = ENODEV;
+	return -1;
+}
+
+static int fd_isok(void * data)
+{
+	struct fd_channel * fds = (struct fd_channel *)data;
+	if(fds)
+	{
+		return fds->fdout != -1 && fds->fdin != -1;
+	}
+	return 0;
+}
+
+static int fd_status_fd(int fd, char * str, int size)
+{
+	if(fd == -1)
+		return snprintf(str, size, "closed");
+
+	return snprintf(str, size, "opened(fd=%d)", fd);
+}
+
+char * fd_status(void * data)
+{
+	static char retval[256];
+	int index = 0;
+
+	struct fd_channel * fds = (struct fd_channel *)data;
+	if(fds)
+	{
+		index += snprintf(retval + index, sizeof(retval) - index, "in ");
+		index += fd_status_fd(fds->fdin, retval + index, sizeof(retval) - index);
+
+		index += snprintf(retval + index, sizeof(retval) - index, "out ");
+		index += fd_status_fd(fds->fdout, retval + index, sizeof(retval) - index);
+	}
+	else
+	{
+		snprintf(retval, sizeof(retval), "(null)");
+	}
+	return retval;
+}
+
+struct channel_ops fd_channel_ops =
+{
+	init:	fd_init,
+	open:	generic_open,
+	close:	generic_close,
+	read:	fd_read,
+	write:	fd_write,
+	free:	generic_free,
+	isok:	fd_isok,
+	status:	fd_status,
+};
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff -urN -X dontdiff or1ksim/peripheral/channels/fd.h or1ksim.richard/peripheral/channels/fd.h
--- or1ksim/peripheral/channels/fd.h	Wed Dec 31 19:00:00 1969
+++ or1ksim.richard/peripheral/channels/fd.h	Tue Oct 22 15:27:30 2002
@@ -0,0 +1,34 @@
+/* generic.h -- Declaration of generic functions for peripheral to 
+ * communicate with host
+   
+   Copyright (C) 2002 Richard Prescott <rip@step.polymtl.ca>
+
+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. */
+
+#ifndef FD_H
+#define FD_H
+
+struct fd_channel
+{
+	int fdin;
+	int fdout;
+};
+
+int fd_read(void * data, char * buffer, int size);
+int fd_write(void * data, const char * buffer, int size);
+
+#endif
diff -urN -X dontdiff or1ksim/peripheral/channels/file.c or1ksim.richard/peripheral/channels/file.c
--- or1ksim/peripheral/channels/file.c	Wed Dec 31 19:00:00 1969
+++ or1ksim.richard/peripheral/channels/file.c	Thu Oct 24 11:46:14 2002
@@ -0,0 +1,156 @@
+/* file.c -- Definition of functions and structures for 
+   peripheral to communicate with host through files
+   
+   Copyright (C) 2002 Richard Prescott <rip@step.polymtl.ca>
+
+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. */
+
+#define _GNU_SOURCE	/* for strndup */
+
+#include <sys/types.h>	/* open() */
+#include <sys/stat.h>	/* open() */
+#include <fcntl.h>	/* open() */
+#include <malloc.h>	/* calloc(), free() */
+#include <string.h>	/* strndup(), strchr() */
+#include <errno.h>	/* errno */
+#include <unistd.h>	/* close() */
+
+#include "channel.h"	/* struct channel_ops */
+#include "fd.h"		/* struct fd_channel, fd_read(), fd_write() */
+
+struct file_channel
+{
+	struct fd_channel fds;
+	char * namein;
+	char * nameout;
+};
+
+static void * file_init(const char * args)
+{
+	struct file_channel * retval;
+	char * nameout;
+
+	if(!args)
+	{
+		errno = EINVAL;
+		return NULL;
+	}
+
+	retval = (struct file_channel*)calloc(1, sizeof(struct file_channel));
+
+	if(!retval)
+	{
+		return NULL;
+	}
+
+	retval->fds.fdin  = -1;
+	retval->fds.fdout = -1;
+
+	nameout = strchr(args, ',');
+
+	if(nameout)
+	{
+		retval->namein  = strndup(args, nameout - args);
+		retval->nameout = strdup(nameout+1);
+	}
+	else
+	{
+		retval->nameout = retval->namein  = strdup(args);
+	}
+
+	return (void*)retval;
+}
+
+static int file_open(void * data)
+{
+	struct file_channel * files = (struct file_channel *)data;
+
+	if(!files)
+	{
+		errno = ENODEV;
+		return -1;
+	}
+
+	if(files->namein == files->nameout)
+	{
+		/* if we have the same name in and out 
+		 * it cannot (logically) be a regular files.
+		 * so we wont create one
+		 */
+		files->fds.fdin = files->fds.fdout = open(files->namein, O_RDWR);
+
+		return files->fds.fdin < 0 ? -1 : 0;
+	}
+
+
+	files->fds.fdin = open(files->namein, O_RDONLY | O_CREAT, 0664);
+
+	if(files->fds.fdin < 0)
+		return -1;
+
+	files->fds.fdout = open(files->nameout, O_WRONLY | O_CREAT, 0664);
+
+	if(files->fds.fdout < 0)
+	{
+		close(files->fds.fdout);
+		files->fds.fdout = -1;
+		return -1;
+	}
+
+	return 0;
+}
+
+static void file_close(void * data)
+{
+	struct file_channel * files = (struct file_channel *)data;
+
+	if(files->fds.fdin != files->fds.fdout)
+		close(files->fds.fdin);
+
+	close(files->fds.fdout);
+
+	files->fds.fdin  = -1;
+	files->fds.fdout = -1;
+}
+
+static void file_free(void * data)
+{
+	struct file_channel * files = (struct file_channel *)data;
+
+	if(files->namein != files->nameout)
+		free(files->namein);
+
+	free(files->nameout);
+
+	free(files);
+}
+
+struct channel_ops file_channel_ops =
+{
+	init:	file_init,
+	open:	file_open,
+	close:	file_close,
+	read:	fd_read,
+	write:	fd_write,
+	free:	file_free,
+};
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff -urN -X dontdiff or1ksim/peripheral/channels/generic.c or1ksim.richard/peripheral/channels/generic.c
--- or1ksim/peripheral/channels/generic.c	Wed Dec 31 19:00:00 1969
+++ or1ksim.richard/peripheral/channels/generic.c	Tue Oct 22 14:10:28 2002
@@ -0,0 +1,54 @@
+/* generic.c -- Definition of generic functions for peripheral to 
+ * communicate with host
+   
+   Copyright (C) 2002 Richard Prescott <rip@step.polymtl.ca>
+
+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. */
+
+#include <malloc.h>	/* free */
+#include <errno.h>	/* errno */
+
+
+int generic_open(void * data)
+{
+	if(data)
+	{
+		return 0;
+	}
+	errno = ENODEV;
+	return -1;
+}
+
+void generic_close(void * data)
+{
+	return;
+}
+
+void generic_free(void * data)
+{
+	if(data)
+	{
+		free(data);
+	}
+}
+
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff -urN -X dontdiff or1ksim/peripheral/channels/generic.h or1ksim.richard/peripheral/channels/generic.h
--- or1ksim/peripheral/channels/generic.h	Wed Dec 31 19:00:00 1969
+++ or1ksim.richard/peripheral/channels/generic.h	Tue Oct 22 14:12:30 2002
@@ -0,0 +1,29 @@
+/* generic.h -- Declaration of generic functions for peripheral to 
+ * communicate with host
+   
+   Copyright (C) 2002 Richard Prescott <rip@step.polymtl.ca>
+
+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. */
+
+#ifndef GENERIC_H
+#define GENERIC_H
+
+int generic_open(void * data);
+void generic_close(void * data);
+void generic_free(void * data);
+
+#endif
diff -urN -X dontdiff or1ksim/peripheral/channels/xterm.c or1ksim.richard/peripheral/channels/xterm.c
--- or1ksim/peripheral/channels/xterm.c	Wed Dec 31 19:00:00 1969
+++ or1ksim.richard/peripheral/channels/xterm.c	Thu Oct 24 11:45:00 2002
@@ -0,0 +1,207 @@
+/* xterm.c -- Definition of functions and structures for 
+   peripheral to communicate with host through an xterm.
+   Inspired from SWI-Prolog by Jan Wielemaker (GPL too)
+   even if there is really few in common.
+   
+   Copyright (C) 2002 Richard Prescott <rip@step.polymtl.ca>
+
+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. */
+
+/*
+ *  I really dislike using stuff beginning with '_' 
+ *  They are suppose to be reserved for the compiler
+ *  as explained in C standards.
+ */
+#define _XOPEN_SOURCE		/* grantpt() and al. */
+#define _GNU_SOURCE		/* on_exit */
+
+#include <sys/types.h>		/* waitpid() */
+#include <sys/wait.h>		/* waitpid() */
+#include <stdio.h>		/* sprintf() */
+#include <stdlib.h>		/* kill(), on_exit() */
+#include <unistd.h>		/* close() */
+#include <fcntl.h>		/* O_RDWR */
+#include <string.h>		/* strchr() */
+#include <sys/stropts.h>	/* grantpt(), unlockpt() */
+#include <termios.h>		/* struct termios and al. */
+#include <signal.h>		/* signal() and al. */
+#include <libgen.h>		/* basename() */
+#include <errno.h>		/* errno and al. */
+
+#include "channel.h"
+#include "generic.h"
+#include "fd.h"
+
+
+struct xterm_channel
+{
+	struct fd_channel fds;
+	int pid;
+};
+
+
+static void xterm_close(void * data)
+{
+	struct xterm_channel * xt = data;
+
+	if(!xt)
+		return;
+
+	if(xt->fds.fdin != -1)
+		close(xt->fds.fdin);
+
+	if(xt->pid != -1)
+	{
+		kill(xt->pid, SIGKILL);
+		waitpid(xt->pid, NULL, 0);
+	}
+  
+	xt->fds.fdin = -1;
+	xt->fds.fdout = -1;
+	xt->pid = -1;
+}
+
+static void xterm_exit(int i, void * data)
+{
+	xterm_close(data);
+}
+
+static void * xterm_init(const char * input)
+{
+	struct xterm_channel * retval = malloc(sizeof(struct xterm_channel));
+	if(retval)
+	{
+		retval->fds.fdin = -1;
+		retval->fds.fdout = -1;
+		retval->pid = -1;
+		/* reset cause exit(1), leaving an xterm opened */
+		on_exit(xterm_exit, retval);	
+	}
+	return (void*)retval;
+}
+
+
+
+static int xterm_open(void * data)
+{
+	struct xterm_channel * xt = data;
+	int master, retval;
+	char * slavename;
+	struct termios termio;
+	char arg[64], * fin;
+
+	if(!data)
+	{
+		errno = ENODEV;
+		return -1;
+	}
+
+
+	master = open("/dev/ptmx", O_RDWR);
+
+	if(master < 0)
+		return -1;
+
+	grantpt(master);                             
+	unlockpt(master);
+	slavename = (char*)ptsname(master);
+
+	if(!slavename)
+	{
+		errno = ENOTTY;
+		goto closemastererror;
+	}
+
+	xt->fds.fdout = xt->fds.fdin = open(slavename, O_RDWR);
+	if(xt->fds.fdout < 0) goto closemastererror;
+
+	retval = ioctl(xt->fds.fdin, I_PUSH, "ptem"); 
+	if(retval < 0) goto closeslaveerror;
+
+	retval = ioctl(xt->fds.fdin, I_PUSH, "ldterm");
+	if(retval < 0) goto closeslaveerror;
+ 
+	retval = tcgetattr(xt->fds.fdin, &termio);
+	if(retval < 0) goto closeslaveerror;
+
+
+	termio.c_lflag &= ~ECHO;
+	retval = tcsetattr(xt->fds.fdin, TCSADRAIN, &termio);
+	if(retval < 0) goto closeslaveerror;
+
+	xt->pid = fork();
+
+	if(xt->pid == -1) goto closeslaveerror;
+
+	if(xt->pid == 0)
+	{
+		/* Ctrl-C on sim still kill the xterm, grrr */
+		signal(SIGINT, SIG_IGN);
+
+		fin = slavename+strlen(slavename)-2;
+		if (strchr(fin, '/' ))
+		{
+			sprintf(arg, "-S%s/%d",
+				basename(slavename),
+				master);
+		}
+		else
+		{
+		      sprintf(arg, "-S%c%c%d", fin[0], fin[1], master);
+		}
+		execlp("xterm", "xterm", arg, NULL);
+		write(master, "\n", 1);
+		exit(1);
+	}
+
+	do retval = read(xt->fds.fdin, &arg, 1);
+	while(retval >= 0 && arg[0] != '\n');
+
+	if(retval < 0) goto closeslaveerror;
+
+	termio.c_lflag |= ECHO;
+	retval = tcsetattr(xt->fds.fdin, TCSADRAIN, &termio);
+
+	if(retval < 0) goto closeslaveerror;
+ 
+	return 0;
+
+closeslaveerror:
+	close(xt->fds.fdin);
+
+closemastererror:
+	close(master);
+	xt->pid = xt->fds.fdin = xt->fds.fdout = -1;
+	return -1;
+}
+ 
+struct channel_ops xterm_channel_ops =
+{
+	init:	xterm_init,
+	open:	xterm_open,
+	close:	xterm_close,
+	read:	fd_read,
+	write:	fd_write,
+	free:	generic_free,
+};
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
+
diff -urN -X dontdiff or1ksim/sim-config.c or1ksim.richard/sim-config.c
--- or1ksim/sim-config.c	Fri Aug 23 05:38:05 2002
+++ or1ksim.richard/sim-config.c	Tue Oct 22 18:56:38 2002
@@ -365,8 +365,7 @@
 void end_device ();
 void uart_nuarts ();
 void uart_baseaddr ();
-void uart_rxfile ();
-void uart_txfile ();
+void uart_channel ();
 void uart_jitter ();
 void uart_irq ();
 void uart_16550 ();
@@ -503,8 +502,7 @@
 {2, "irq",                "=%i",         uart_irq,      (void *)(&tempL), 0},
 {2, "16550",              "=%i",         uart_16550,    (void *)(&tempL), 0},
 {2, "jitter",             "=%i",         uart_jitter,   (void *)(&tempL), 0},
-{2, "rxfile",             "=\"%s\"",     uart_rxfile,   (void *)(&tempS[0]), 0},
-{2, "txfile",             "=\"%s\"",     uart_txfile,   (void *)(&tempS[0]), 0},
+{2, "channel",            "=\"%s\"",     uart_channel,  (void *)(&tempS[0]), 0},
 {2, "vapi_id",            "=0x%x",       uart_vapi_id,  (void *)(&tempUL), 0},
 
 {3, "ndmas",              "=%i",         dma_ndmas,     (void *)(&tempL), CPF_GLOBAL},
@@ -762,16 +760,9 @@
     ERROR("invalid device number.");
 }
 
-void uart_rxfile () {
+void uart_channel () {
   if (current_device >= 0 && current_device < config.nuarts)
-    strcpy (config.uarts[current_device].rxfile, tempS);
-  else
-    ERROR("invalid device number.");
-}
-
-void uart_txfile () {
-  if (current_device >= 0 && current_device < config.nuarts)
-    strcpy (config.uarts[current_device].txfile, tempS);
+    strcpy (config.uarts[current_device].channel, tempS);
   else
     ERROR("invalid device number.");
 }
@@ -1479,8 +1470,8 @@
   fprintf (f, "  nuarts:%i, uarts:{", config.nuarts);
   comma = 0;
   for (i = 0; i < config.nuarts; i++) {
-    fprintf (f, "%s\n    {rxfile:\"%s\", txfile:\"%s\", jitter:%i, baseaddr:0x%08x, irq:%i, vapi_id:0x%08x, uart16550:%i}",
-      comma ? "," :"", config.uarts[i].rxfile, config.uarts[i].txfile, config.uarts[i].jitter, config.uarts[i].baseaddr, config.uarts[i].irq,
+    fprintf (f, "%s\n    {channel:\"%s\", jitter:%i, baseaddr:0x%08x, irq:%i, vapi_id:0x%08x, uart16550:%i}",
+      comma ? "," :"", config.uarts[i].channel, config.uarts[i].jitter, config.uarts[i].baseaddr, config.uarts[i].irq,
       config.uarts[i].vapi_id, config.uarts[i].uart16550);
     comma = 1;
   }
diff -urN -X dontdiff or1ksim/sim-config.h or1ksim.richard/sim-config.h
--- or1ksim/sim-config.h	Fri Aug 23 04:38:35 2002
+++ or1ksim.richard/sim-config.h	Tue Oct 22 17:37:39 2002
@@ -46,13 +46,12 @@
   
   int nuarts;
   struct {
-    char rxfile[STR_SIZE];            /* Filename for RX */
-    char txfile[STR_SIZE];            /* Filename for TX (required) */
     int jitter;                       /* CZ 250801 - in msecs...time to block */
     unsigned long baseaddr;           /* Naturally aligned base address */
     int irq;                          /* IRQ of this device */
     unsigned long vapi_id;            /* VAPI id for this instance */
     int uart16550;                    /* Whether this device is uart 16450 or 16550 */
+    char channel[STR_SIZE];           /* How to communicate with host */
   } uarts[MAX_UARTS];
   
   int ndmas;