URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
Compare Revisions
- This comparison shows the changes necessary to convert path
/or1k/tags/nog_patch_47/or1ksim/testbench/uos
- from Rev 1419 to Rev 1765
- ↔ Reverse comparison
Rev 1419 → Rev 1765
/Makefile.in
0,0 → 1,357
# Makefile.in generated by automake 1.6.3 from Makefile.am. |
# @configure_input@ |
|
# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 |
# Free Software Foundation, Inc. |
# This Makefile.in is free software; the Free Software Foundation |
# gives unlimited permission to copy and/or distribute it, |
# with or without modifications, as long as this notice is preserved. |
|
# This program is distributed in the hope that it will be useful, |
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without |
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A |
# PARTICULAR PURPOSE. |
|
@SET_MAKE@ |
|
# |
# 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. |
# |
SHELL = @SHELL@ |
|
srcdir = @srcdir@ |
top_srcdir = @top_srcdir@ |
VPATH = @srcdir@ |
prefix = @prefix@ |
exec_prefix = @exec_prefix@ |
|
bindir = @bindir@ |
sbindir = @sbindir@ |
libexecdir = @libexecdir@ |
datadir = @datadir@ |
sysconfdir = @sysconfdir@ |
sharedstatedir = @sharedstatedir@ |
localstatedir = @localstatedir@ |
libdir = @libdir@ |
infodir = @infodir@ |
mandir = @mandir@ |
includedir = @includedir@ |
oldincludedir = /usr/include |
pkgdatadir = $(datadir)/@PACKAGE@ |
pkglibdir = $(libdir)/@PACKAGE@ |
pkgincludedir = $(includedir)/@PACKAGE@ |
top_builddir = .. |
|
ACLOCAL = @ACLOCAL@ |
AUTOCONF = @AUTOCONF@ |
AUTOMAKE = @AUTOMAKE@ |
AUTOHEADER = @AUTOHEADER@ |
|
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd |
INSTALL = @INSTALL@ |
INSTALL_PROGRAM = @INSTALL_PROGRAM@ |
INSTALL_DATA = @INSTALL_DATA@ |
install_sh_DATA = $(install_sh) -c -m 644 |
install_sh_PROGRAM = $(install_sh) -c |
install_sh_SCRIPT = $(install_sh) -c |
INSTALL_SCRIPT = @INSTALL_SCRIPT@ |
INSTALL_HEADER = $(INSTALL_DATA) |
transform = @program_transform_name@ |
NORMAL_INSTALL = : |
PRE_INSTALL = : |
POST_INSTALL = : |
NORMAL_UNINSTALL = : |
PRE_UNINSTALL = : |
POST_UNINSTALL = : |
host_alias = @host_alias@ |
host_triplet = @host@ |
|
EXEEXT = @EXEEXT@ |
OBJEXT = @OBJEXT@ |
PATH_SEPARATOR = @PATH_SEPARATOR@ |
AMTAR = @AMTAR@ |
AWK = @AWK@ |
CC = @CC@ |
CCAS = @CCAS@ |
CCASFLAGS = @CCASFLAGS@ |
DEPDIR = @DEPDIR@ |
INCLUDES = @INCLUDES@ |
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ |
LD = @LD@ |
MAKE_SHELL = @MAKE_SHELL@ |
OR1K_SRCDIR = @OR1K_SRCDIR@ |
PACKAGE = @PACKAGE@ |
RANLIB = @RANLIB@ |
SIM = @SIM@ |
STRIP = @STRIP@ |
TESTS_ENV = @TESTS_ENV@ |
VERSION = @VERSION@ |
am__include = @am__include@ |
am__quote = @am__quote@ |
install_sh = @install_sh@ |
|
LDADD = ../support/libsupport.a |
LDFLAGS = -T${top_srcdir}/default.ld |
|
bin_PROGRAMS = uos |
uos_SOURCES = except_or32.S support.h spr_defs.h task.c int.h ipc.h tick.c uos.h uos.c |
subdir = uos |
mkinstalldirs = $(SHELL) $(top_srcdir)/../mkinstalldirs |
CONFIG_CLEAN_FILES = |
bin_PROGRAMS = uos$(EXEEXT) |
PROGRAMS = $(bin_PROGRAMS) |
|
am_uos_OBJECTS = except_or32.$(OBJEXT) task.$(OBJEXT) tick.$(OBJEXT) \ |
uos.$(OBJEXT) |
uos_OBJECTS = $(am_uos_OBJECTS) |
uos_LDADD = $(LDADD) |
uos_DEPENDENCIES = ../support/libsupport.a |
uos_LDFLAGS = |
|
DEFS = @DEFS@ |
DEFAULT_INCLUDES = -I. -I$(srcdir) |
CPPFLAGS = @CPPFLAGS@ |
LIBS = @LIBS@ |
depcomp = $(SHELL) $(top_srcdir)/../depcomp |
am__depfiles_maybe = depfiles |
@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/task.Po ./$(DEPDIR)/tick.Po \ |
@AMDEP_TRUE@ ./$(DEPDIR)/uos.Po |
CCASCOMPILE = $(CCAS) $(AM_CCASFLAGS) $(CCASFLAGS) |
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ |
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) |
CCLD = $(CC) |
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ |
CFLAGS = @CFLAGS@ |
DIST_SOURCES = $(uos_SOURCES) |
DIST_COMMON = README Makefile.am Makefile.in |
SOURCES = $(uos_SOURCES) |
|
all: all-am |
|
.SUFFIXES: |
.SUFFIXES: .S .c .o .obj |
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) |
cd $(top_srcdir) && \ |
$(AUTOMAKE) --gnu uos/Makefile |
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status |
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) |
binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) |
install-binPROGRAMS: $(bin_PROGRAMS) |
@$(NORMAL_INSTALL) |
$(mkinstalldirs) $(DESTDIR)$(bindir) |
@list='$(bin_PROGRAMS)'; for p in $$list; do \ |
p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ |
if test -f $$p \ |
; then \ |
f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ |
echo " $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) $$p $(DESTDIR)$(bindir)/$$f"; \ |
$(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) $$p $(DESTDIR)$(bindir)/$$f; \ |
else :; fi; \ |
done |
|
uninstall-binPROGRAMS: |
@$(NORMAL_UNINSTALL) |
@list='$(bin_PROGRAMS)'; for p in $$list; do \ |
f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ |
echo " rm -f $(DESTDIR)$(bindir)/$$f"; \ |
rm -f $(DESTDIR)$(bindir)/$$f; \ |
done |
|
clean-binPROGRAMS: |
-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) |
uos$(EXEEXT): $(uos_OBJECTS) $(uos_DEPENDENCIES) |
@rm -f uos$(EXEEXT) |
$(LINK) $(uos_LDFLAGS) $(uos_OBJECTS) $(uos_LDADD) $(LIBS) |
|
mostlyclean-compile: |
-rm -f *.$(OBJEXT) core *.core |
|
distclean-compile: |
-rm -f *.tab.c |
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/task.Po@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tick.Po@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uos.Po@am__quote@ |
|
distclean-depend: |
-rm -rf ./$(DEPDIR) |
|
.S.o: |
$(CCASCOMPILE) -c `test -f '$<' || echo '$(srcdir)/'`$< |
|
.S.obj: |
$(CCASCOMPILE) -c `cygpath -w $<` |
|
.c.o: |
@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ |
@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ |
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ |
$(COMPILE) -c `test -f '$<' || echo '$(srcdir)/'`$< |
|
.c.obj: |
@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ |
@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ |
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ |
$(COMPILE) -c `cygpath -w $<` |
CCDEPMODE = @CCDEPMODE@ |
uninstall-info-am: |
|
ETAGS = etags |
ETAGSFLAGS = |
|
tags: TAGS |
|
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) |
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ |
unique=`for i in $$list; do \ |
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ |
done | \ |
$(AWK) ' { files[$$0] = 1; } \ |
END { for (i in files) print i; }'`; \ |
mkid -fID $$unique |
|
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ |
$(TAGS_FILES) $(LISP) |
tags=; \ |
here=`pwd`; \ |
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ |
unique=`for i in $$list; do \ |
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ |
done | \ |
$(AWK) ' { files[$$0] = 1; } \ |
END { for (i in files) print i; }'`; \ |
test -z "$(ETAGS_ARGS)$$tags$$unique" \ |
|| $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ |
$$tags $$unique |
|
GTAGS: |
here=`$(am__cd) $(top_builddir) && pwd` \ |
&& cd $(top_srcdir) \ |
&& gtags -i $(GTAGS_ARGS) $$here |
|
distclean-tags: |
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH |
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) |
|
top_distdir = .. |
distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) |
|
distdir: $(DISTFILES) |
@list='$(DISTFILES)'; for file in $$list; do \ |
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ |
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ |
if test "$$dir" != "$$file" && test "$$dir" != "."; then \ |
dir="/$$dir"; \ |
$(mkinstalldirs) "$(distdir)$$dir"; \ |
else \ |
dir=''; \ |
fi; \ |
if test -d $$d/$$file; then \ |
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ |
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ |
fi; \ |
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ |
else \ |
test -f $(distdir)/$$file \ |
|| cp -p $$d/$$file $(distdir)/$$file \ |
|| exit 1; \ |
fi; \ |
done |
check-am: all-am |
check: check-am |
all-am: Makefile $(PROGRAMS) |
|
installdirs: |
$(mkinstalldirs) $(DESTDIR)$(bindir) |
|
install: install-am |
install-exec: install-exec-am |
install-data: install-data-am |
uninstall: uninstall-am |
|
install-am: all-am |
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am |
|
installcheck: installcheck-am |
install-strip: |
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ |
INSTALL_STRIP_FLAG=-s \ |
`test -z '$(STRIP)' || \ |
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install |
mostlyclean-generic: |
|
clean-generic: |
|
distclean-generic: |
-rm -f Makefile $(CONFIG_CLEAN_FILES) |
|
maintainer-clean-generic: |
@echo "This command is intended for maintainers to use" |
@echo "it deletes files that may require special tools to rebuild." |
clean: clean-am |
|
clean-am: clean-binPROGRAMS clean-generic mostlyclean-am |
|
distclean: distclean-am |
|
distclean-am: clean-am distclean-compile distclean-depend \ |
distclean-generic distclean-tags |
|
dvi: dvi-am |
|
dvi-am: |
|
info: info-am |
|
info-am: |
|
install-data-am: |
|
install-exec-am: install-binPROGRAMS |
|
install-info: install-info-am |
|
install-man: |
|
installcheck-am: |
|
maintainer-clean: maintainer-clean-am |
|
maintainer-clean-am: distclean-am maintainer-clean-generic |
|
mostlyclean: mostlyclean-am |
|
mostlyclean-am: mostlyclean-compile mostlyclean-generic |
|
uninstall-am: uninstall-binPROGRAMS uninstall-info-am |
|
.PHONY: GTAGS all all-am check check-am clean clean-binPROGRAMS \ |
clean-generic distclean distclean-compile distclean-depend \ |
distclean-generic distclean-tags distdir dvi dvi-am info \ |
info-am install install-am install-binPROGRAMS install-data \ |
install-data-am install-exec install-exec-am install-info \ |
install-info-am install-man install-strip installcheck \ |
installcheck-am installdirs maintainer-clean \ |
maintainer-clean-generic mostlyclean mostlyclean-compile \ |
mostlyclean-generic tags uninstall uninstall-am \ |
uninstall-binPROGRAMS uninstall-info-am |
|
|
again: clean all |
# Tell versions [3.59,3.63) of GNU make to not export all variables. |
# Otherwise a system limit (for SysV at least) may be exceeded. |
.NOEXPORT: |
/task.c
0,0 → 1,54
/* This file is part of test microkernel for OpenRISC 1000. */ |
/* (C) 2000 Damjan Lampret, lampret@opencores.org */ |
|
#include "support.h" |
#include "uos.h" |
#include "ipc.h" |
#include "int.h" |
|
extern struct tcb tasks[MAX_TASKS+1]; |
|
int task(int id) |
{ |
int rc; |
struct _msg { |
char id; |
unsigned long count; |
} msg; |
|
printf("Task %d started\n", id); |
|
if(id == 1) { |
msg.id = 1; |
msg.count = 0; |
uos_msgsnd(2, (char *)&msg, sizeof(msg)); |
} |
|
for(;;) { |
rc = uos_msgrcv(0, (char *)&msg, sizeof(msg)); |
|
if(rc != 0) { |
printf("Task %d: Waiting for massage\n", id); |
} else { |
printf("Task %d: Got massage from task %d: 0x%.8x. Sending message to task %d: 0x%.8x \n", id, msg.id, (int)msg.count, (id == 3 ? 1 : (id + 1)), (int)(msg.count + 1)); |
msg.id = id; |
|
if((id == 1) && (msg.count > 15)) { |
report(msg.count + 0xdeadde9c); |
exit(0); |
} |
|
msg.count += 1; |
uos_msgsnd((id == 3 ? 1 : (id + 1)), (char *)&msg, sizeof(msg)); |
} |
} |
} |
|
/* Called by kernel_init to collect all tasks entries. */ |
void tasks_entries() |
{ |
tasks[1].regs.pc = (unsigned long)task; |
tasks[2].regs.pc = (unsigned long)task; |
tasks[3].regs.pc = (unsigned long)task; |
} |
|
/uos.c
0,0 → 1,314
/* This file is part of test microkernel for OpenRISC 1000. */ |
/* (C) 2000 Damjan Lampret, lampret@opencores.org */ |
|
#include "support.h" |
#include "spr_defs.h" |
#include "uos.h" |
#include "ipc.h" |
#include "int.h" |
|
/* External functions prototypes */ |
int tick_init(unsigned long period, void (* inf)(void)); |
|
/* Pointers to contexts used by except_or32.S routines */ |
unsigned long *task_context; |
unsigned long *kernel_context; |
|
/* TCBs for all tasks in the system */ |
struct tcb tasks[MAX_TASKS+1]; |
|
/* Stacks for the tasks (stacks[0] is kernel stack) */ |
unsigned char stacks[MAX_TASKS+1][STACK_SIZE]; |
|
/* MCBs for IPC messages */ |
struct mcb msgs[MAX_MSGS]; |
|
/* Pointer to linked list of free MCBs. */ |
struct mcb *free_mcbs; |
|
/* TID of the current user task */ |
tid_t curtask = 0; |
|
/* Statistics */ |
int kernel_sched_cnt = 0; |
int kernel_syscall_cnt = 0; |
|
/* Timestamp via or1ksim (CPU cycle number). */ |
unsigned long timestamp() |
{ |
register unsigned long cycles asm("r3"); |
asm("l.sys 201"); |
return cycles; |
} |
|
/* Standard function for filling memory with a constant byte. */ |
void *memset(void *dst, int c, size_t size) |
{ |
char *tmp = dst; |
|
for(;tmp && (tmp < (char *)dst + size); tmp++) |
*(char *)tmp = (char)c; |
|
return dst; |
} |
|
/* Traverse linked list of MCBs and show individual messages. */ |
void kernel_show_mcbs(struct mcb *mcb) |
{ |
for(;mcb; mcb = mcb->next) { |
printf("MCB len=%u origintask=%u ", mcb->length, mcb->origin); |
printf("msg:%s\n", mcb->msg); |
} |
} |
|
/* Show all contexts. */ |
void kernel_show_contexts() |
{ |
int i; |
tid_t t; |
|
for(t = 1; t <= MAX_TASKS; t++) { |
printf("\ntask TID=%d: PC=0x%x ", t, (unsigned)tasks[t].regs.pc & ~0x3); |
printf("SP(r1)=0x%x ", (unsigned)tasks[t].regs.sp); |
printf("SR[IEE]=%d\n", (unsigned)tasks[t].regs.sr & SPR_SR_IEE); |
printf("SR[TEE]=%d\n", (unsigned)tasks[t].regs.sr & SPR_SR_TEE); |
printf("SR[SM]=%d\n", (unsigned)tasks[t].regs.sr & SPR_SR_SM); |
for(i = 1; i < GPRS; i++) { |
if (i % 4 == 0) |
printf("\n"); |
printf("r%d=0x%.8x ", i, (unsigned)tasks[t].regs.gprs[i]); |
} |
printf("\n"); |
kernel_show_mcbs(tasks[t].waiting_msgs); |
} |
printf("\n"); |
} |
|
/* Simple round-robin scheduler that directly calls dispatcher. It is |
called by low level external interrupt exception handler or by |
kernel_syscall if KERNEL_SYSCALL_SCHED is defined. */ |
void kernel_sched() |
{ |
if ((++curtask > MAX_TASKS) || !(tasks[curtask].regs.pc & ~0x3)) |
curtask = 1; |
task_context = (unsigned long *)&tasks[curtask].regs; |
|
#if KERNEL_OUTPUT |
printf("kernel_sched(): entry number %d, ", ++kernel_sched_cnt); |
printf("dispatching task TID=%d, time %u cycles", curtask, timestamp()); |
|
kernel_show_contexts(); |
#endif |
|
dispatch(); |
} |
|
/* System call uos_msgsnd. */ |
int uos_msgsnd(tid_t desttask, char *buf, int len) |
{ |
asm("l.sys 1"); |
asm("l.nop"); |
} |
|
/* System call uos_msgrcv. */ |
int uos_msgrcv(tid_t origintask, char *buf, int len) |
{ |
asm("l.sys 2"); |
asm("l.nop"); |
} |
|
/* Handles system call uos_msgsnd. */ |
void kernel_msgsnd(tid_t tid) |
{ |
struct mcb *mcb; |
struct mcb **dstmq; |
struct tcb *task; |
|
task = &tasks[tid]; |
|
/* Sanity checks. */ |
|
/* Does destination task exist? */ |
if (!task->regs.gprs[1] || (task->regs.gprs[1] > MAX_TASKS)) { |
task->regs.gprs[9] = IPC_ENOTASK; |
return; |
} |
|
/* Are there any free MCBs? */ |
if (!free_mcbs) { |
task->regs.gprs[9] = IPC_EOUTOFMCBS; |
return; |
} |
|
/* Is message too big to fit into MCB's message buffer? */ |
if (task->regs.gprs[3] > MAX_MSGLEN) { |
task->regs.gprs[9] = IPC_ETOOBIG; |
return; |
} |
|
/* OK, send the message. */ |
|
/* First, allocate MCB. */ |
mcb = free_mcbs; |
free_mcbs = mcb->next; |
|
/* Second, copy message to the MCB. */ |
memcpy(mcb->msg, (void *)task->regs.gprs[2], task->regs.gprs[3]); |
mcb->origin = tid; |
mcb->length = task->regs.gprs[3]; |
mcb->next = NULL; |
|
/* Insert MCB into destination task's message queue at |
the end. */ |
dstmq = &tasks[task->regs.gprs[1]].waiting_msgs; |
for(;*dstmq;) |
dstmq = &((*dstmq)->next); |
*dstmq = mcb; |
|
task->regs.gprs[9] = IPC_NOERR; |
return; |
} |
|
/* Handles system call uos_msgrcv. */ |
void kernel_msgrcv(tid_t tid) |
{ |
struct mcb *mcb; |
struct mcb *curmsg, **linkp; |
struct tcb *task; |
|
task = &tasks[tid]; |
|
/* Sanity checks. */ |
|
/* Does origin task exist? */ |
if (task->regs.gprs[1] > MAX_TASKS) { |
task->regs.gprs[9] = IPC_ENOTASK; |
return; |
} |
|
/* Are there any messages waiting for reception? */ |
if (!task->waiting_msgs) { |
task->regs.gprs[9] = IPC_ENOMSGS; |
return; |
} |
|
/* OK, receive the message. */ |
|
/* Search waiting messages for one coming from origintask. If |
origintask is zero then grab the first message. */ |
curmsg = task->waiting_msgs; |
linkp = &task->waiting_msgs; |
for(;task->regs.gprs[1] && curmsg->next && curmsg->origin != task->regs.gprs[1];) { |
linkp = &curmsg->next; |
curmsg = curmsg->next; |
} |
|
/* Is receive buffer too small for receiving message? */ |
if (task->regs.gprs[3] < curmsg->length) { |
task->regs.gprs[9] = IPC_ETOOBIG; |
return; |
} |
|
/* Now copy the message from the MCB. */ |
memcpy((void *)task->regs.gprs[2], curmsg->msg, task->regs.gprs[3]); |
|
/* Remove MCB from task's waiting queue and place it |
back into free MCBs queue. */ |
*linkp = curmsg->next; |
curmsg->next = free_mcbs; |
free_mcbs = curmsg; |
|
task->regs.gprs[9] = IPC_NOERR; |
return; |
} |
|
/* Handles all uOS system calls. It is called by low level system call |
exception handler. */ |
void kernel_syscall() |
{ |
unsigned short syscall_num; |
|
#if KERNEL_OUTPUT |
printf("kernel_syscall(): entry number %d, ", ++kernel_syscall_cnt); |
printf("current TID=%d, time %u cycles", curtask, timestamp()); |
|
kernel_show_contexts(); |
#endif |
syscall_num = *(unsigned short *)((tasks[curtask].regs.pc & ~0x3) - 6); |
|
switch(syscall_num) { |
case IPC_MSGSND: |
kernel_msgsnd(curtask); |
break; |
case IPC_MSGRCV: |
kernel_msgrcv(curtask); |
break; |
default: |
printf("kernel_syscall(): unknown syscall (%u)\n", syscall_num); |
} |
|
#if KERNEL_SYSCALL_SCHED |
kernel_sched(); |
#endif |
dispatch(); |
} |
|
/* Called by reset exception handler to initialize the kernel and start |
rolling first task. */ |
int kernel_init() |
{ |
tid_t t; |
int i; |
|
printf("Initializing kernel:\n"); |
|
printf(" Clearing kernel structures...\n"); |
memset(tasks, 0, sizeof(tasks)); |
memset(stacks, 0, sizeof(stacks)); |
memset(msgs, 0, sizeof(msgs)); |
|
printf(" Initializing MCBs... %d MCB(s)\n", MAX_MSGS); |
for(i = 0; i < (MAX_MSGS - 1); i++) |
msgs[i].next = &msgs[i+1]; |
free_mcbs = &msgs[0]; |
|
printf(" Initializing TCBs... %d user task(s)\n", MAX_TASKS); |
|
tasks_entries(); |
|
for(t = 0; t <= MAX_TASKS; t++) { |
tasks[t].regs.sp = (unsigned long)stacks[t] + STACK_SIZE - 4; |
/* Disable EXR for kernel context */ |
tasks[t].regs.sr |= (t == 0 ? SPR_SR_SM : SPR_SR_TEE | SPR_SR_IEE); |
tasks[t].regs.gprs[1] = t; |
} |
|
/* First task runs in seprvisor mode */ |
tasks[1].regs.sr |= SPR_SR_SM; |
|
/* TID=0 is reserved for kernel use */ |
kernel_context = (unsigned long *)&tasks[0].regs; |
|
/* First task to be scheduled is task TID=1 */ |
task_context = (unsigned long *)&tasks[1].regs; |
|
/* Initialize initrrupt controller */ |
int_init(); |
|
printf(" Exceptions will be enabled when first task is dispatched.\n"); |
printf("Kernel initalized. Starting first user task.\n"); |
|
#if KERNEL_SYSCALL_SCHED |
kernel_sched(); /* Lets schedule and dispatch our first task */ |
#else |
tick_init(TICK_PERIOD, kernel_sched); |
kernel_sched(); /* Lets schedule and dispatch our first task */ |
#endif |
/* ... */ /* We never get here */ |
} |
|
int main () |
{ |
kernel_init(); |
return 0; |
} |
/spr_defs.h
0,0 → 1,428
/* spr_defs.h -- Defines OR1K architecture specific special-purpose registers |
Copyright (C) 1999 Damjan Lampret, lampret@opencores.org |
|
This file is part of OpenRISC 1000 Architectural Simulator. |
|
This program is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License as published by |
the Free Software Foundation; either version 2 of the License, or |
(at your option) any later version. |
|
This program is distributed in the hope that it will be useful, |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
GNU General Public License for more details. |
|
You should have received a copy of the GNU General Public License |
along with this program; if not, write to the Free Software |
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ |
|
/* This file is also used by microkernel test bench. Among |
others it is also used in assembly file(s). */ |
|
/* Definition of special-purpose registers (SPRs) */ |
|
#define MAX_GRPS (32) |
#define MAX_SPRS_PER_GRP_BITS (11) |
#define MAX_SPRS_PER_GRP (1 << MAX_SPRS_PER_GRP_BITS) |
#define MAX_SPRS (0x10000) |
|
/* Base addresses for the groups */ |
#define SPRGROUP_SYS (0<< MAX_SPRS_PER_GRP_BITS) |
#define SPRGROUP_DMMU (1<< MAX_SPRS_PER_GRP_BITS) |
#define SPRGROUP_IMMU (2<< MAX_SPRS_PER_GRP_BITS) |
#define SPRGROUP_DC (3<< MAX_SPRS_PER_GRP_BITS) |
#define SPRGROUP_IC (4<< MAX_SPRS_PER_GRP_BITS) |
#define SPRGROUP_MAC (5<< MAX_SPRS_PER_GRP_BITS) |
#define SPRGROUP_D (6<< MAX_SPRS_PER_GRP_BITS) |
#define SPRGROUP_PC (7<< MAX_SPRS_PER_GRP_BITS) |
#define SPRGROUP_PM (8<< MAX_SPRS_PER_GRP_BITS) |
#define SPRGROUP_PIC (9<< MAX_SPRS_PER_GRP_BITS) |
#define SPRGROUP_TT (10<< MAX_SPRS_PER_GRP_BITS) |
|
/* System control and status group */ |
#define SPR_VR (SPRGROUP_SYS + 0) |
#define SPR_UPR (SPRGROUP_SYS + 1) |
#define SPR_CPUCFGR (SPRGROUP_SYS + 2) |
#define SPR_DMMUCFGR (SPRGROUP_SYS + 3) |
#define SPR_IMMUCFGR (SPRGROUP_SYS + 4) |
#define SPR_DCCFGR (SPRGROUP_SYS + 5) |
#define SPR_ICCFGR (SPRGROUP_SYS + 6) |
#define SPR_DCFGR (SPRGROUP_SYS + 7) |
#define SPR_PCCFGR (SPRGROUP_SYS + 8) |
#define SPR_NPC (SPRGROUP_SYS + 16) /* CZ 21/06/01 */ |
#define SPR_SR (SPRGROUP_SYS + 17) /* CZ 21/06/01 */ |
#define SPR_PPC (SPRGROUP_SYS + 18) /* CZ 21/06/01 */ |
#define SPR_EPCR_BASE (SPRGROUP_SYS + 32) /* CZ 21/06/01 */ |
#define SPR_EPCR_LAST (SPRGROUP_SYS + 47) /* CZ 21/06/01 */ |
#define SPR_EEAR_BASE (SPRGROUP_SYS + 48) |
#define SPR_EEAR_LAST (SPRGROUP_SYS + 63) |
#define SPR_ESR_BASE (SPRGROUP_SYS + 64) |
#define SPR_ESR_LAST (SPRGROUP_SYS + 79) |
|
/* Data MMU group */ |
#define SPR_DMMUCR (SPRGROUP_DMMU + 0) |
#define SPR_DTLBMR_BASE(WAY) (SPRGROUP_DMMU + 0x200 + (WAY) * 0x200) |
#define SPR_DTLBMR_LAST(WAY) (SPRGROUP_DMMU + 0x2ff + (WAY) * 0x200) |
#define SPR_DTLBTR_BASE(WAY) (SPRGROUP_DMMU + 0x300 + (WAY) * 0x200) |
#define SPR_DTLBTR_LAST(WAY) (SPRGROUP_DMMU + 0x3ff + (WAY) * 0x200) |
|
/* Instruction MMU group */ |
#define SPR_IMMUCR (SPRGROUP_IMMU + 0) |
#define SPR_ITLBMR_BASE(WAY) (SPRGROUP_IMMU + 0x200 + (WAY) * 0x200) |
#define SPR_ITLBMR_LAST(WAY) (SPRGROUP_IMMU + 0x2ff + (WAY) * 0x200) |
#define SPR_ITLBTR_BASE(WAY) (SPRGROUP_IMMU + 0x300 + (WAY) * 0x200) |
#define SPR_ITLBTR_LAST(WAY) (SPRGROUP_IMMU + 0x3ff + (WAY) * 0x200) |
|
/* Data cache group */ |
#define SPR_DCCR (SPRGROUP_DC + 0) |
#define SPR_DCBPR (SPRGROUP_DC + 1) |
#define SPR_DCBFR (SPRGROUP_DC + 2) |
#define SPR_DCBIR (SPRGROUP_DC + 3) |
#define SPR_DCBWR (SPRGROUP_DC + 4) |
#define SPR_DCBLR (SPRGROUP_DC + 5) |
#define SPR_DCR_BASE(WAY) (SPRGROUP_DC + 0x200 + (WAY) * 0x200) |
#define SPR_DCR_LAST(WAY) (SPRGROUP_DC + 0x3ff + (WAY) * 0x200) |
|
/* Instruction cache group */ |
#define SPR_ICCR (SPRGROUP_IC + 0) |
#define SPR_ICBPR (SPRGROUP_IC + 1) |
#define SPR_ICBIR (SPRGROUP_IC + 2) |
#define SPR_ICBLR (SPRGROUP_IC + 3) |
#define SPR_ICR_BASE(WAY) (SPRGROUP_IC + 0x200 + (WAY) * 0x200) |
#define SPR_ICR_LAST(WAY) (SPRGROUP_IC + 0x3ff + (WAY) * 0x200) |
|
/* MAC group */ |
#define SPR_MACLO (SPRGROUP_MAC + 1) |
#define SPR_MACHI (SPRGROUP_MAC + 2) |
|
/* Debug group */ |
#define SPR_DVR(N) (SPRGROUP_D + (N)) |
#define SPR_DCR(N) (SPRGROUP_D + 8 + (N)) |
#define SPR_DMR1 (SPRGROUP_D + 16) |
#define SPR_DMR2 (SPRGROUP_D + 17) |
#define SPR_DWCR0 (SPRGROUP_D + 18) |
#define SPR_DWCR1 (SPRGROUP_D + 19) |
#define SPR_DSR (SPRGROUP_D + 20) |
#define SPR_DRR (SPRGROUP_D + 21) |
|
/* Performance counters group */ |
#define SPR_PCCR(N) (SPRGROUP_PC + (N)) |
#define SPR_PCMR(N) (SPRGROUP_PC + 8 + (N)) |
|
/* Power management group */ |
#define SPR_PMR (SPRGROUP_PM + 0) |
|
/* PIC group */ |
#define SPR_PICMR (SPRGROUP_PIC + 0) |
#define SPR_PICPR (SPRGROUP_PIC + 1) |
#define SPR_PICSR (SPRGROUP_PIC + 2) |
|
/* Tick Timer group */ |
#define SPR_TTMR (SPRGROUP_TT + 0) |
#define SPR_TTCR (SPRGROUP_TT + 1) |
|
/* |
* Bit definitions for the Version Register |
* |
*/ |
#define SPR_VR_VER 0xffff0000 /* Processor version */ |
#define SPR_VR_REV 0x0000003f /* Processor revision */ |
|
/* |
* Bit definitions for the Unit Present Register |
* |
*/ |
#define SPR_UPR_UP 0x00000001 /* UPR present */ |
#define SPR_UPR_DCP 0x00000002 /* Data cache present */ |
#define SPR_UPR_ICP 0x00000004 /* Instruction cache present */ |
#define SPR_UPR_DMP 0x00000008 /* Data MMU present */ |
#define SPR_UPR_IMP 0x00000010 /* Instruction MMU present */ |
#define SPR_UPR_OB32P 0x00000020 /* ORBIS32 present */ |
#define SPR_UPR_OB64P 0x00000040 /* ORBIS64 present */ |
#define SPR_UPR_OF32P 0x00000080 /* ORFPX32 present */ |
#define SPR_UPR_OF64P 0x00000100 /* ORFPX64 present */ |
#define SPR_UPR_OV32P 0x00000200 /* ORVDX32 present */ |
#define SPR_UPR_OV64P 0x00000400 /* ORVDX64 present */ |
#define SPR_UPR_DUP 0x00000800 /* Debug unit present */ |
#define SPR_UPR_PCUP 0x00001000 /* Performance counters unit present */ |
#define SPR_UPR_PMP 0x00002000 /* Power management present */ |
#define SPR_UPR_PICP 0x00004000 /* PIC present */ |
#define SPR_UPR_TTP 0x00008000 /* Tick timer present */ |
#define SPR_UPR_SRP 0x00010000 /* Shadow registers present */ |
#define SPR_UPR_RES 0x00fe0000 /* ORVDX32 present */ |
#define SPR_UPR_CUST 0xff000000 /* Custom units */ |
|
/* |
* Bit definitions for the Supervision Register |
* |
*/ |
#define SPR_SR_CID 0xf0000000 /* Context ID */ |
#define SPR_SR_FO 0x00008000 /* Fixed one */ |
#define SPR_SR_EPH 0x00004000 /* Exception Prefixi High */ |
#define SPR_SR_DSX 0x00002000 /* Delay Slot Exception */ |
#define SPR_SR_OVE 0x00001000 /* Overflow flag Exception */ |
#define SPR_SR_OV 0x00000800 /* Overflow flag */ |
#define SPR_SR_CY 0x00000400 /* Carry flag */ |
#define SPR_SR_F 0x00000200 /* Condition Flag */ |
#define SPR_SR_CE 0x00000100 /* CID Enable */ |
#define SPR_SR_LEE 0x00000080 /* Little Endian Enable */ |
#define SPR_SR_IME 0x00000040 /* Instruction MMU Enable */ |
#define SPR_SR_DME 0x00000020 /* Data MMU Enable */ |
#define SPR_SR_ICE 0x00000010 /* Instruction Cache Enable */ |
#define SPR_SR_DCE 0x00000008 /* Data Cache Enable */ |
#define SPR_SR_IEE 0x00000004 /* Interrupt Exception Enable */ |
#define SPR_SR_TEE 0x00000002 /* Tick timer Exception Enable */ |
#define SPR_SR_SM 0x00000001 /* Supervisor Mode */ |
|
/* |
* Bit definitions for the Data MMU Control Register |
* |
*/ |
#define SPR_DMMUCR_P2S 0x0000003e /* Level 2 Page Size */ |
#define SPR_DMMUCR_P1S 0x000007c0 /* Level 1 Page Size */ |
#define SPR_DMMUCR_VADDR_WIDTH 0x0000f800 /* Virtual ADDR Width */ |
#define SPR_DMMUCR_PADDR_WIDTH 0x000f0000 /* Physical ADDR Width */ |
|
/* |
* Bit definitions for the Instruction MMU Control Register |
* |
*/ |
#define SPR_IMMUCR_P2S 0x0000003e /* Level 2 Page Size */ |
#define SPR_IMMUCR_P1S 0x000007c0 /* Level 1 Page Size */ |
#define SPR_IMMUCR_VADDR_WIDTH 0x0000f800 /* Virtual ADDR Width */ |
#define SPR_IMMUCR_PADDR_WIDTH 0x000f0000 /* Physical ADDR Width */ |
|
/* |
* Bit definitions for the Data TLB Match Register |
* |
*/ |
#define SPR_DTLBMR_V 0x00000001 /* Valid */ |
#define SPR_DTLBMR_PL1 0x00000002 /* Page Level 1 (if 0 then PL2) */ |
#define SPR_DTLBMR_CID 0x0000003c /* Context ID */ |
#define SPR_DTLBMR_LRU 0x000000c0 /* Least Recently Used */ |
#define SPR_DTLBMR_VPN 0xfffff000 /* Virtual Page Number */ |
|
/* |
* Bit definitions for the Data TLB Translate Register |
* |
*/ |
#define SPR_DTLBTR_CC 0x00000001 /* Cache Coherency */ |
#define SPR_DTLBTR_CI 0x00000002 /* Cache Inhibit */ |
#define SPR_DTLBTR_WBC 0x00000004 /* Write-Back Cache */ |
#define SPR_DTLBTR_WOM 0x00000008 /* Weakly-Ordered Memory */ |
#define SPR_DTLBTR_A 0x00000010 /* Accessed */ |
#define SPR_DTLBTR_D 0x00000020 /* Dirty */ |
#define SPR_DTLBTR_URE 0x00000040 /* User Read Enable */ |
#define SPR_DTLBTR_UWE 0x00000080 /* User Write Enable */ |
#define SPR_DTLBTR_SRE 0x00000100 /* Supervisor Read Enable */ |
#define SPR_DTLBTR_SWE 0x00000200 /* Supervisor Write Enable */ |
#define SPR_DTLBTR_PPN 0xfffff000 /* Physical Page Number */ |
|
/* |
* Bit definitions for the Instruction TLB Match Register |
* |
*/ |
#define SPR_ITLBMR_V 0x00000001 /* Valid */ |
#define SPR_ITLBMR_PL1 0x00000002 /* Page Level 1 (if 0 then PL2) */ |
#define SPR_ITLBMR_CID 0x0000003c /* Context ID */ |
#define SPR_ITLBMR_LRU 0x000000c0 /* Least Recently Used */ |
#define SPR_ITLBMR_VPN 0xfffff000 /* Virtual Page Number */ |
|
/* |
* Bit definitions for the Instruction TLB Translate Register |
* |
*/ |
#define SPR_ITLBTR_CC 0x00000001 /* Cache Coherency */ |
#define SPR_ITLBTR_CI 0x00000002 /* Cache Inhibit */ |
#define SPR_ITLBTR_WBC 0x00000004 /* Write-Back Cache */ |
#define SPR_ITLBTR_WOM 0x00000008 /* Weakly-Ordered Memory */ |
#define SPR_ITLBTR_A 0x00000010 /* Accessed */ |
#define SPR_ITLBTR_D 0x00000020 /* Dirty */ |
#define SPR_ITLBTR_SXE 0x00000040 /* User Read Enable */ |
#define SPR_ITLBTR_UXE 0x00000080 /* User Write Enable */ |
#define SPR_ITLBTR_PPN 0xfffff000 /* Physical Page Number */ |
|
/* |
* Bit definitions for Data Cache Control register |
* |
*/ |
#define SPR_DCCR_EW 0x000000ff /* Enable ways */ |
|
/* |
* Bit definitions for Insn Cache Control register |
* |
*/ |
#define SPR_ICCR_EW 0x000000ff /* Enable ways */ |
|
/* |
* Bit definitions for Debug Control registers |
* |
*/ |
#define SPR_DCR_DP 0x00000001 /* DVR/DCR present */ |
#define SPR_DCR_CC 0x0000000e /* Compare condition */ |
#define SPR_DCR_SC 0x00000010 /* Signed compare */ |
#define SPR_DCR_CT 0x000000e0 /* Compare to */ |
|
/* Bit results with SPR_DCR_CC mask */ |
#define SPR_DCR_CC_MASKED 0x00000000 |
#define SPR_DCR_CC_EQUAL 0x00000001 |
#define SPR_DCR_CC_LESS 0x00000002 |
#define SPR_DCR_CC_LESSE 0x00000003 |
#define SPR_DCR_CC_GREAT 0x00000004 |
#define SPR_DCR_CC_GREATE 0x00000005 |
#define SPR_DCR_CC_NEQUAL 0x00000006 |
|
/* Bit results with SPR_DCR_CT mask */ |
#define SPR_DCR_CT_DISABLED 0x00000000 |
#define SPR_DCR_CT_IFEA 0x00000020 |
#define SPR_DCR_CT_LEA 0x00000040 |
#define SPR_DCR_CT_SEA 0x00000060 |
#define SPR_DCR_CT_LD 0x00000080 |
#define SPR_DCR_CT_SD 0x000000a0 |
#define SPR_DCR_CT_LSEA 0x000000c0 |
|
/* |
* Bit definitions for Debug Mode 1 register |
* |
*/ |
#define SPR_DMR1_CW0 0x00000003 /* Chain watchpoint 0 */ |
#define SPR_DMR1_CW1 0x0000000c /* Chain watchpoint 1 */ |
#define SPR_DMR1_CW2 0x00000030 /* Chain watchpoint 2 */ |
#define SPR_DMR1_CW3 0x000000c0 /* Chain watchpoint 3 */ |
#define SPR_DMR1_CW4 0x00000300 /* Chain watchpoint 4 */ |
#define SPR_DMR1_CW5 0x00000c00 /* Chain watchpoint 5 */ |
#define SPR_DMR1_CW6 0x00003000 /* Chain watchpoint 6 */ |
#define SPR_DMR1_CW7 0x0000c000 /* Chain watchpoint 7 */ |
#define SPR_DMR1_CW8 0x00030000 /* Chain watchpoint 8 */ |
#define SPR_DMR1_CW9 0x000c0000 /* Chain watchpoint 9 */ |
#define SPR_DMR1_CW10 0x00300000 /* Chain watchpoint 10 */ |
#define SPR_DMR1_ST 0x00400000 /* Single-step trace*/ |
#define SPR_DMR1_BT 0x00800000 /* Branch trace */ |
#define SPR_DMR1_DXFW 0x01000000 /* Disable external force watchpoint */ |
|
/* |
* Bit definitions for Debug Mode 2 register |
* |
*/ |
#define SPR_DMR2_WCE0 0x00000001 /* Watchpoint counter 0 enable */ |
#define SPR_DMR2_WCE1 0x00000002 /* Watchpoint counter 0 enable */ |
#define SPR_DMR2_AWTC 0x00001ffc /* Assign watchpoints to counters */ |
#define SPR_DMR2_WGB 0x00ffe000 /* Watchpoints generating breakpoint */ |
|
/* |
* Bit definitions for Debug watchpoint counter registers |
* |
*/ |
#define SPR_DWCR_COUNT 0x0000ffff /* Count */ |
#define SPR_DWCR_MATCH 0xffff0000 /* Match */ |
|
/* |
* Bit definitions for Debug stop register |
* |
*/ |
#define SPR_DSR_RSTE 0x00000001 /* Reset exception */ |
#define SPR_DSR_BUSEE 0x00000002 /* Bus error exception */ |
#define SPR_DSR_DPFE 0x00000004 /* Data Page Fault exception */ |
#define SPR_DSR_IPFE 0x00000008 /* Insn Page Fault exception */ |
#define SPR_DSR_TTE 0x00000010 /* iTick Timer exception */ |
#define SPR_DSR_AE 0x00000020 /* Alignment exception */ |
#define SPR_DSR_IIE 0x00000040 /* Illegal Instruction exception */ |
#define SPR_DSR_IE 0x00000080 /* Interrupt exception */ |
#define SPR_DSR_DME 0x00000100 /* DTLB miss exception */ |
#define SPR_DSR_IME 0x00000200 /* ITLB miss exception */ |
#define SPR_DSR_RE 0x00000400 /* Range exception */ |
#define SPR_DSR_SCE 0x00000800 /* System call exception */ |
#define SPR_DSR_SSE 0x00001000 /* Single Step Exception */ |
#define SPR_DSR_TE 0x00002000 /* Trap exception */ |
|
/* |
* Bit definitions for Debug reason register |
* |
*/ |
#define SPR_DRR_RSTE 0x00000001 /* Reset exception */ |
#define SPR_DRR_BUSEE 0x00000002 /* Bus error exception */ |
#define SPR_DRR_DPFE 0x00000004 /* Data Page Fault exception */ |
#define SPR_DRR_IPFE 0x00000008 /* Insn Page Fault exception */ |
#define SPR_DRR_TTE 0x00000010 /* Tick Timer exception */ |
#define SPR_DRR_AE 0x00000020 /* Alignment exception */ |
#define SPR_DRR_IIE 0x00000040 /* Illegal Instruction exception */ |
#define SPR_DRR_IE 0x00000080 /* Interrupt exception */ |
#define SPR_DRR_DME 0x00000100 /* DTLB miss exception */ |
#define SPR_DRR_IME 0x00000200 /* ITLB miss exception */ |
#define SPR_DRR_RE 0x00000400 /* Range exception */ |
#define SPR_DRR_SCE 0x00000800 /* System call exception */ |
#define SPR_DRR_TE 0x00001000 /* Trap exception */ |
|
/* |
* Bit definitions for Performance counters mode registers |
* |
*/ |
#define SPR_PCMR_CP 0x00000001 /* Counter present */ |
#define SPR_PCMR_UMRA 0x00000002 /* User mode read access */ |
#define SPR_PCMR_CISM 0x00000004 /* Count in supervisor mode */ |
#define SPR_PCMR_CIUM 0x00000008 /* Count in user mode */ |
#define SPR_PCMR_LA 0x00000010 /* Load access event */ |
#define SPR_PCMR_SA 0x00000020 /* Store access event */ |
#define SPR_PCMR_IF 0x00000040 /* Instruction fetch event*/ |
#define SPR_PCMR_DCM 0x00000080 /* Data cache miss event */ |
#define SPR_PCMR_ICM 0x00000100 /* Insn cache miss event */ |
#define SPR_PCMR_IFS 0x00000200 /* Insn fetch stall event */ |
#define SPR_PCMR_LSUS 0x00000400 /* LSU stall event */ |
#define SPR_PCMR_BS 0x00000800 /* Branch stall event */ |
#define SPR_PCMR_DTLBM 0x00001000 /* DTLB miss event */ |
#define SPR_PCMR_ITLBM 0x00002000 /* ITLB miss event */ |
#define SPR_PCMR_DDS 0x00004000 /* Data dependency stall event */ |
#define SPR_PCMR_WPE 0x03ff8000 /* Watchpoint events */ |
|
/* |
* Bit definitions for the Power management register |
* |
*/ |
#define SPR_PMR_SDF 0x0000000f /* Slow down factor */ |
#define SPR_PMR_DME 0x00000010 /* Doze mode enable */ |
#define SPR_PMR_SME 0x00000020 /* Sleep mode enable */ |
#define SPR_PMR_DCGE 0x00000040 /* Dynamic clock gating enable */ |
#define SPR_PMR_SUME 0x00000080 /* Suspend mode enable */ |
|
/* |
* Bit definitions for PICMR |
* |
*/ |
#define SPR_PICMR_IUM 0xfffffffc /* Interrupt unmask */ |
|
/* |
* Bit definitions for PICPR |
* |
*/ |
#define SPR_PICPR_IPRIO 0xfffffffc /* Interrupt priority */ |
|
/* |
* Bit definitions for PICSR |
* |
*/ |
#define SPR_PICSR_IS 0xffffffff /* Interrupt status */ |
|
/* |
* Bit definitions for Tick Timer Control Register |
* |
*/ |
#define SPR_TTCR_PERIOD 0x0fffffff /* Time Period */ |
#define SPR_TTMR_PERIOD SPR_TTCR_PERIOD |
#define SPR_TTMR_IP 0x10000000 /* Interrupt Pending */ |
#define SPR_TTMR_IE 0x20000000 /* Interrupt Enable */ |
#define SPR_TTMR_RT 0x40000000 /* Restart tick */ |
#define SPR_TTMR_SR 0x80000000 /* Single run */ |
#define SPR_TTMR_CR 0xc0000000 /* Continuous run */ |
#define SPR_TTMR_M 0xc0000000 /* Tick mode */ |
|
/* |
* l.nop constants |
* |
*/ |
#define NOP_NOP 0x0000 /* Normal nop instruction */ |
#define NOP_EXIT 0x0001 /* End of simulation */ |
#define NOP_REPORT 0x0002 /* Simple report */ |
#define NOP_printf 0x0003 /* Simprintf instruction */ |
#define NOP_REPORT_FIRST 0x0400 /* Report with number */ |
#define NOP_REPORT_LAST 0x03ff /* Report with number */ |
spr_defs.h
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: except_or32.S
===================================================================
--- except_or32.S (nonexistent)
+++ except_or32.S (revision 1765)
@@ -0,0 +1,351 @@
+/* This file is part of test microkernel for OpenRISC 1000. */
+/* (C) 2000 Damjan Lampret, lampret@opencores.org */
+
+#include "spr_defs.h"
+#include "../board.h"
+
+#define MC_CSR (0x00)
+#define MC_POC (0x04)
+#define MC_BA_MASK (0x08)
+#define MC_CSC(i) (0x10 + (i) * 8)
+#define MC_TMS(i) (0x14 + (i) * 8)
+
+
+/*
+ * Context is saved to area pointed by pointer in R3. Original
+ * R3 is at memory location 0 and task's PC is at memory location 4.
+ */
+#define SAVEREGS \
+ l.lwz r3,0(r3); \
+ l.sw 4(r3),r1; \
+ l.sw 8(r3),r2; \
+ l.lwz r2,0(r0); /* saving original r3*/ \
+ l.sw 12(r3),r2; \
+ l.sw 16(r3),r4; \
+ l.sw 20(r3),r5; \
+ l.sw 24(r3),r6; \
+ l.sw 28(r3),r7; \
+ l.sw 32(r3),r8; \
+ l.sw 36(r3),r9; \
+ l.sw 40(r3),r10; \
+ l.sw 44(r3),r11; \
+ l.sw 48(r3),r12; \
+ l.sw 52(r3),r13; \
+ l.sw 56(r3),r14; \
+ l.sw 60(r3),r15; \
+ l.sw 64(r3),r16; \
+ l.sw 68(r3),r17; \
+ l.sw 72(r3),r18; \
+ l.sw 76(r3),r19; \
+ l.sw 80(r3),r20; \
+ l.sw 84(r3),r21; \
+ l.sw 88(r3),r22; \
+ l.sw 92(r3),r23; \
+ l.sw 96(r3),r24; \
+ l.sw 100(r3),r25; \
+ l.sw 104(r3),r26; \
+ l.sw 108(r3),r27; \
+ l.sw 112(r3),r28; \
+ l.sw 116(r3),r29; \
+ l.sw 120(r3),r30; \
+ l.sw 124(r3),r31; \
+ l.lwz r2,4(r0); /* saving original PC*/ \
+ l.sw 0(r3),r2; \
+ \
+ l.mfspr r2,r0,SPR_ESR_BASE; \
+ l.sw 128(r3),r2 /* saving SR */
+
+/*
+ * Pointer to context is in R3. All registers are loaded and execution is
+ * transfered to the loaded context's task
+ */
+#define LOADREGS_N_GO \
+ l.lwz r3,0(r3); \
+ l.lwz r2,0(r3); /* prepare PC*/ \
+ l.mtspr r0,r2,SPR_EPCR_BASE; \
+ \
+ l.lwz r2,128(r3); /* prepare SR*/ \
+ l.mtspr r0,r2,SPR_ESR_BASE; \
+ \
+ l.lwz r1,4(r3); \
+ l.lwz r2,8(r3); \
+ l.lwz r4,16(r3); \
+ l.lwz r5,20(r3); \
+ l.lwz r6,24(r3); \
+ l.lwz r7,28(r3); \
+ l.lwz r8,32(r3); \
+ l.lwz r9,36(r3); \
+ l.lwz r10,40(r3); \
+ l.lwz r11,44(r3); \
+ l.lwz r12,48(r3); \
+ l.lwz r13,52(r3); \
+ l.lwz r14,56(r3); \
+ l.lwz r15,60(r3); \
+ l.lwz r16,64(r3); \
+ l.lwz r17,68(r3); \
+ l.lwz r18,72(r3); \
+ l.lwz r19,76(r3); \
+ l.lwz r20,80(r3); \
+ l.lwz r21,84(r3); \
+ l.lwz r22,88(r3); \
+ l.lwz r23,92(r3); \
+ l.lwz r24,96(r3); \
+ l.lwz r25,100(r3); \
+ l.lwz r26,104(r3); \
+ l.lwz r27,108(r3); \
+ l.lwz r28,112(r3); \
+ l.lwz r29,116(r3); \
+ l.lwz r30,120(r3); \
+ l.lwz r31,124(r3); \
+ \
+ l.lwz r3,12(r3); /* prepare r3*/ \
+ \
+ l.rfe; /* Call task */ \
+ l.nop
+
+/*
+ * All registers are loaded from save area.
+ */
+#define LOADREGS \
+ l.lwz r3,0(r3); \
+ l.lwz r2,0(r3); /* prepare PC*/ \
+ l.mtspr r0,r2,SPR_EPCR_BASE; \
+ \
+ l.lwz r2,128(r3); /* prepare SR*/ \
+ l.mtspr r0,r2,SPR_ESR_BASE; \
+ \
+ l.lwz r1,4(r3); \
+ l.lwz r2,8(r3); \
+ l.lwz r4,16(r3); \
+ l.lwz r5,20(r3); \
+ l.lwz r6,24(r3); \
+ l.lwz r7,28(r3); \
+ l.lwz r8,32(r3); \
+ l.lwz r9,36(r3); \
+ l.lwz r10,40(r3); \
+ l.lwz r11,44(r3); \
+ l.lwz r12,48(r3); \
+ l.lwz r13,52(r3); \
+ l.lwz r14,56(r3); \
+ l.lwz r15,60(r3); \
+ l.lwz r16,64(r3); \
+ l.lwz r17,68(r3); \
+ l.lwz r18,72(r3); \
+ l.lwz r19,76(r3); \
+ l.lwz r20,80(r3); \
+ l.lwz r21,84(r3); \
+ l.lwz r22,88(r3); \
+ l.lwz r23,92(r3); \
+ l.lwz r24,96(r3); \
+ l.lwz r25,100(r3); \
+ l.lwz r26,104(r3); \
+ l.lwz r27,108(r3); \
+ l.lwz r28,112(r3); \
+ l.lwz r29,116(r3); \
+ l.lwz r30,120(r3); \
+ l.lwz r31,124(r3); \
+ \
+ l.lwz r3,12(r3); /* prepare r3*/
+
+/*
+ * Set new PC in saved context
+ */
+#define SET_CONTEXTPC(AREA,SUBROUTINE,TMPREG) \
+ l.lwz AREA,0(AREA); \
+ l.movhi TMPREG,hi(SUBROUTINE); \
+ l.addi TMPREG,r0,lo(SUBROUTINE); \
+ l.sw 0(AREA),TMPREG;
+
+/*
+ * Printf via or1ksim hook
+ */
+#if KERNEL_OUTPUT
+#define PRINTF(REG,STR) \
+ l.movhi REG,hi(STR); \
+ l.addi REG,r0,lo(STR); \
+ l.nop NOP_PRINTF
+#else
+#define PRINTF(REG,STR)
+#endif
+
+/*
+ * Reset Exception handler
+ */
+.org 0x100
+_reset_vector:
+
+ l.movhi r3,hi(MC_BASE_ADDR)
+ l.ori r3,r3,lo(MC_BASE_ADDR)
+
+ l.addi r4,r3,MC_CSC(0)
+ l.movhi r5,hi(FLASH_BASE_ADDR)
+ l.srai r5,r5,6
+ l.ori r5,r5,0x0025
+ l.sw 0(r4),r5
+
+ l.addi r4,r3,MC_TMS(0)
+ l.movhi r5,hi(FLASH_TMS_VAL)
+ l.ori r5,r5,lo(FLASH_TMS_VAL)
+ l.sw 0(r4),r5
+
+ l.addi r4,r3,MC_BA_MASK
+ l.addi r5,r0,MC_MASK_VAL
+ l.sw 0(r4),r5
+
+ l.addi r4,r3,MC_CSR
+ l.movhi r5,hi(MC_CSR_VAL)
+ l.ori r5,r5,lo(MC_CSR_VAL)
+ l.sw 0(r4),r5
+
+ l.addi r4,r3,MC_TMS(1)
+ l.movhi r5,hi(SDRAM_TMS_VAL)
+ l.ori r5,r5,lo(SDRAM_TMS_VAL)
+ l.sw 0(r4),r5
+
+ l.addi r4,r3,MC_CSC(1)
+ l.movhi r5,hi(SDRAM_BASE_ADDR)
+ l.srai r5,r5,6
+ l.ori r5,r5,0x0411
+ l.sw 0(r4),r5
+
+ l.jr r9
+ l.nop
+
+ /* Copy data section */
+ l.movhi r3,hi(_src_beg)
+ l.ori r3,r3,lo(_src_beg)
+ l.addi r4,r0,0x200
+ l.movhi r5,hi(_except_end)
+ l.ori r5,r5,lo(_except_end)
+ l.movhi r6,hi(_except_beg)
+ l.ori r6,r6,lo(_except_beg)
+ l.sub r5,r6,r5
+1:
+ l.lwz r6,0(r3)
+ l.sw 0(r4),r6
+ l.addi r3,r3,4
+ l.addi r4,r4,4
+ l.addi r5,r5,-4
+ l.sfgtsi r5,0
+ l.bf 1b
+ l.nop
+
+ l.movhi r4,hi(_dst_beg)
+ l.ori r4,r4,lo(_dst_beg)
+ l.movhi r5,hi(_dst_end)
+ l.ori r5,r5,lo(_dst_end)
+ l.sub r5,r5,r4
+ l.sfeqi r5,0
+ l.bf 2f
+ l.nop
+1:
+ l.lwz r6,0(r3)
+ l.sw 0(r4),r6
+ l.addi r3,r3,4
+ l.addi r4,r4,4
+ l.addi r5,r5,-4
+ l.sfgtsi r5,0
+ l.bf 1b
+ l.nop
+
+2:
+
+
+ l.movhi r2,hi(_reset)
+ l.ori r2,r2,lo(_reset)
+ l.jr r2
+ l.nop
+
+/*
+ * Switch to a new context pointed by _task_context
+ */
+.global _dispatch
+.align 4
+_dispatch:
+ /* load user task GPRs and PC */
+ l.movhi r3,hi(_task_context)
+ l.addi r3,r0,lo(_task_context)
+ LOADREGS_N_GO
+
+.section .except, "ax"
+
+/*
+ * Bus Error Exception handler
+ */
+.org 0x0200
+_buserr:
+ l.nop
+ l.sw 0(r0),r3 /* Save r3 */
+ PRINTF(r3, _buserr_str)
+_hang:
+ l.j _hang
+ l.nop
+
+_buserr_str:
+ .ascii "Bus error exception.\n\000"
+
+/*
+ * External Interrupt Exception handler
+ */
+.org 0x800
+_extint:
+ l.nop
+ l.sw 0(r0),r3 /* Save r3 */
+ PRINTF(r3,_extint_str)
+ l.mfspr r3,r0,SPR_EPCR_BASE /* Get EPCR */
+ l.sw 4(r0),r3 /* and save it */
+
+ /* now save user task context */
+ l.movhi r3,hi(_task_context)
+ l.addi r3,r0,lo(_task_context)
+ SAVEREGS
+
+ /* set kernel context's PC to kernel's scheduler */
+ l.movhi r3,hi(_kernel_context)
+ l.addi r3,r0,lo(_kernel_context)
+ SET_CONTEXTPC(r3,_int_main,r4)
+
+ /* load kernel context */
+ l.movhi r3,hi(_kernel_context)
+ l.addi r3,r0,lo(_kernel_context)
+ LOADREGS
+
+ l.movhi r3,hi(_int_main)
+ l.addi r3,r0,lo(_int_main)
+ l.jr r3
+ l.nop
+
+_extint_str:
+ .ascii "External interrupt exception.\n\000"
+
+/*
+ * System Call Exception handler
+ */
+.org 0x0c00
+_syscall:
+ l.nop
+ l.sw 0(r0),r3 /* Save r3 */
+ PRINTF(r3,_syscall_str)
+ l.mfspr r3,r0,SPR_EPCR_BASE /* Get EPCR */
+ l.addi r3,r3,4 /* increment because EPCR instruction was already executed */
+ l.sw 4(r0),r3 /* and save it */
+
+ /* now save user task context */
+ l.movhi r3,hi(_task_context)
+ l.addi r3,r0,lo(_task_context)
+ SAVEREGS
+
+ /* set kernel context's PC to kernel's syscall entry */
+ l.movhi r3,hi(_kernel_context)
+ l.addi r3,r0,lo(_kernel_context)
+ SET_CONTEXTPC(r3,_kernel_syscall,r4)
+
+ /* load kernel context */
+ l.movhi r3,hi(_kernel_context)
+ l.addi r3,r0,lo(_kernel_context)
+ LOADREGS_N_GO
+
+_syscall_str:
+ .ascii "System call exception.\n\000"
+
+
Index: tick.c
===================================================================
--- tick.c (nonexistent)
+++ tick.c (revision 1765)
@@ -0,0 +1,34 @@
+/* This file is part of test microkernel for OpenRISC 1000. */
+/* (C) 2001 Simon Srot, srot@opencores.org */
+
+#include "spr_defs.h"
+#include "support.h"
+
+/* Tick timer period */
+unsigned long tick_period;
+
+/* Inform of tick interrupt */
+void (*tick_inf)();
+
+/* Tick interrupt routine */
+void tick_int()
+{
+ /* Call inf routine */
+ (*tick_inf)();
+
+ /* Set new counter period iand clear inet pending bit */
+ mtspr(SPR_TTMR, SPR_TTMR_IE | SPR_TTMR_RT | (tick_period & SPR_TTMR_PERIOD));
+}
+
+/* Initialize routine */
+int tick_init(unsigned long period, void (* inf)())
+{
+ /* Save tick timer period and inform routine */
+ tick_period = period;
+ tick_inf = inf;
+
+ /* Set counter period, enable timer and interrupt */
+ mtspr(SPR_TTMR, SPR_TTMR_IE | SPR_TTMR_RT | (period & SPR_TTMR_PERIOD));
+
+ return 0;
+}
Index: Makefile.am
===================================================================
--- Makefile.am (nonexistent)
+++ Makefile.am (revision 1765)
@@ -0,0 +1,28 @@
+## Makefile for or1ksim subdirectory test
+## (c) Marko Mlinar, 2001
+## To add new test, edit between marked areas only
+#
+# 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.
+#
+
+LDADD = ../support/libsupport.a
+LDFLAGS = -T${top_srcdir}/default.ld
+
+bin_PROGRAMS = uos
+uos_SOURCES = except_or32.S support.h spr_defs.h task.c int.h ipc.h tick.c uos.h uos.c
+
+again: clean all
Makefile.am
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: ipc.h
===================================================================
--- ipc.h (nonexistent)
+++ ipc.h (revision 1765)
@@ -0,0 +1,27 @@
+/* This file is part of test microkernel for OpenRISC 1000. */
+/* (C) 2000 Damjan Lampret, lampret@opencores.org */
+
+/* Operation completed sucessfully. */
+#define IPC_NOERR 0
+
+/* Can't send any messages due to lack of free MCBs. */
+#define IPC_EOUTOFMCBS 1
+
+/* Sending message: No such destination task.
+ Receiving message: No such origin task. */
+#define IPC_ENOTASK 2
+
+/* Message to big to be sent or receive buffer is to small for
+ receiving message. If receiving then try again with bigger buffer. */
+#define IPC_ETOOBIG 3
+
+/* No messages waiting to be received. */
+#define IPC_ENOMSGS 4
+
+/* Send message in buffer buf of size len to task desttask. */
+int uos_msgsnd(tid_t desttask, char *buf, int len);
+
+/* Receive message of max size len from task origintask and put it
+ into buffer buf. If origintask is zero then get the first message
+ from the message queue. */
+int uos_msgrcv(tid_t origintask, char *buf, int len);
Index: uos.h
===================================================================
--- uos.h (nonexistent)
+++ uos.h (revision 1765)
@@ -0,0 +1,58 @@
+/* This file is part of test microkernel for OpenRISC 1000. */
+/* (C) 2000 Damjan Lampret, lampret@opencores.org */
+
+/* Length of the IPC message's useful data. */
+#define MAX_MSGLEN 100
+
+/* Number of user tasks in the system. */
+#define MAX_TASKS 8
+
+/* Number of IPC messages in the system. */
+#define MAX_MSGS 16
+
+/* Number of general purpose registers (not counting r0 and r1). */
+#define GPRS 30
+
+/* Size of kernel and user task stacks. Size for individual task. */
+#define STACK_SIZE 2048
+
+/* Define this if you want kernel debug output. Note that you must
+ assemble except_or32.S with KERNEL_OUTPUT defined in Makefile. This
+ definition is only for main uos.c. */
+#define KERNEL_OUTPUT 0
+
+/* Define this if you want task switch at every system call. */
+#define KERNEL_SYSCALL_SCHED 0
+
+/* System tick timer period */
+#define TICK_PERIOD 0x500
+
+/* Task ID type (if we would have processes then we would call it PID) */
+typedef int tid_t;
+
+/* System call numbers */
+#define IPC_MSGSND 1
+#define IPC_MSGRCV 2
+
+/* Message Control Block structure */
+struct mcb {
+ char msg[MAX_MSGLEN]; /* Message's data */
+ int length; /* Message's length */
+ tid_t origin; /* TID of message's origin task */
+ struct mcb *next; /* Next message in linked list */
+};
+
+/* Task Control Block structure */
+struct tcb {
+ struct regs {
+ unsigned long pc; /* Task's PC */
+ unsigned long sp; /* Task's stack (r1)*/
+ unsigned long gprs[GPRS]; /* Task's GPRs r2-r15 */
+ unsigned long sr; /* Task's supervision register */
+ } regs;
+ struct mcb *waiting_msgs; /* Waiting messages */
+};
+
+extern void dispatch();
+/* Called by kernel_init to collect all tasks entries. */
+extern void tasks_entries();
Index: README
===================================================================
--- README (nonexistent)
+++ README (revision 1765)
@@ -0,0 +1,18 @@
+
+This is the Micro OS (uOS) for testing operating system features of
+OpenRISC 1000 architecture. Specifically non reentrant, preemptive
+multitasking microkernel. Purpose of this code is not to be a true
+operating system but merely a testbench for testing the architecture,
+or1ksim and software development tools (GCC, Binutils, ...).
+
+This test OS has all necessary exception handlers to handle exceptions. There
+are two tasks: one task generates data and passes that data via IPC to the
+second task. Second task outputs the data via or1ksim syscall to the simulator.
+
+Currently only OR32 is supported (exception handlers are written in
+assembly). Tools required to compile sources are the latest
+or32-coff-gcc, or32-coff-as and or32-coff-ld. Also make sure you undefine
+VIRTUAL_MACHINE_ONLY when compiling or1ksim.
+
+--
+10/Jun/2000, Damjan Lampret, lampret@opencores.org
Index: .
===================================================================
--- . (nonexistent)
+++ . (revision 1765)
.
Property changes :
Added: svn:ignore
## -0,0 +1,3 ##
+Makefile
+uos
+.deps