]> rtime.felk.cvut.cz Git - fpga/plasma.git/commitdiff
Local copy of Plasma MIPS project. master
authorVladimir Burian <buriavl2@fel.cvut.cz>
Mon, 14 Feb 2011 13:09:49 +0000 (14:09 +0100)
committerVladimir Burian <buriavl2@fel.cvut.cz>
Mon, 14 Feb 2011 13:09:49 +0000 (14:09 +0100)
See project homepage at <http://opencores.org/project,plasma>.
Actual trunk directory is copied.

71 files changed:
kernel/dll.h [new file with mode: 0644]
kernel/dlltest.c [new file with mode: 0644]
kernel/ethernet.c [new file with mode: 0644]
kernel/filesys.c [new file with mode: 0644]
kernel/flash.c [new file with mode: 0644]
kernel/http.c [new file with mode: 0644]
kernel/libc.c [new file with mode: 0644]
kernel/makefile [new file with mode: 0644]
kernel/math.c [new file with mode: 0644]
kernel/netutil.c [new file with mode: 0644]
kernel/os_stubs.c [new file with mode: 0644]
kernel/rtos.c [new file with mode: 0644]
kernel/rtos.h [new file with mode: 0644]
kernel/rtos_test.c [new file with mode: 0644]
kernel/tcpip.c [new file with mode: 0644]
kernel/tcpip.h [new file with mode: 0644]
kernel/uart.c [new file with mode: 0644]
tools/bintohex.c [new file with mode: 0644]
tools/boot.asm [new file with mode: 0644]
tools/bootldr.c [new file with mode: 0644]
tools/convert.c [new file with mode: 0644]
tools/count.c [new file with mode: 0644]
tools/cpu.gif [new file with mode: 0644]
tools/ddr_init.c [new file with mode: 0644]
tools/etermip.c [new file with mode: 0644]
tools/makefile [new file with mode: 0644]
tools/mlite.c [new file with mode: 0644]
tools/no_os.c [new file with mode: 0644]
tools/opcodes.asm [new file with mode: 0644]
tools/output.txt [new file with mode: 0644]
tools/pi.c [new file with mode: 0644]
tools/plasma.h [new file with mode: 0644]
tools/ram_image.c [new file with mode: 0644]
tools/test.c [new file with mode: 0644]
tools/tracehex.c [new file with mode: 0644]
vhdl/alu.vhd [new file with mode: 0644]
vhdl/build_dir/ISE_scripts/.svn/all-wcprops [new file with mode: 0644]
vhdl/build_dir/ISE_scripts/.svn/entries [new file with mode: 0644]
vhdl/build_dir/ISE_scripts/.svn/text-base/loadprom.cmds.svn-base [new file with mode: 0644]
vhdl/build_dir/ISE_scripts/.svn/text-base/main.scrs.svn-base [new file with mode: 0644]
vhdl/build_dir/ISE_scripts/.svn/text-base/makeprom.cmds.svn-base [new file with mode: 0644]
vhdl/build_dir/ISE_scripts/loadprom.cmds [new file with mode: 0644]
vhdl/build_dir/ISE_scripts/main.scrs [new file with mode: 0644]
vhdl/build_dir/ISE_scripts/makeprom.cmds [new file with mode: 0644]
vhdl/build_dir/Makefile [new file with mode: 0644]
vhdl/bus_mux.vhd [new file with mode: 0644]
vhdl/cache.vhd [new file with mode: 0644]
vhdl/code.txt [new file with mode: 0644]
vhdl/control.vhd [new file with mode: 0644]
vhdl/ddr_ctrl.vhd [new file with mode: 0644]
vhdl/eth_dma.vhd [new file with mode: 0644]
vhdl/makefile [new file with mode: 0644]
vhdl/mem_ctrl.vhd [new file with mode: 0644]
vhdl/mlite_cpu.vhd [new file with mode: 0644]
vhdl/mlite_pack.vhd [new file with mode: 0644]
vhdl/mult.vhd [new file with mode: 0644]
vhdl/pc_next.vhd [new file with mode: 0644]
vhdl/pipeline.vhd [new file with mode: 0644]
vhdl/plasma.vhd [new file with mode: 0644]
vhdl/plasma_3e.vhd [new file with mode: 0644]
vhdl/plasma_S3E.npl [new file with mode: 0644]
vhdl/plasma_if.ucf [new file with mode: 0644]
vhdl/plasma_if.vhd [new file with mode: 0644]
vhdl/ram.vhd [new file with mode: 0644]
vhdl/ram_xilinx.vhd [new file with mode: 0644]
vhdl/reg_bank.vhd [new file with mode: 0644]
vhdl/shifter.vhd [new file with mode: 0644]
vhdl/simili.cmd [new file with mode: 0755]
vhdl/spartan3e.ucf [new file with mode: 0644]
vhdl/tbench.vhd [new file with mode: 0644]
vhdl/uart.vhd [new file with mode: 0644]

diff --git a/kernel/dll.h b/kernel/dll.h
new file mode 100644 (file)
index 0000000..4b902c7
--- /dev/null
@@ -0,0 +1,537 @@
+/*--------------------------------------------------------------------\r
+ * TITLE: Plasma Dynamic Link Library\r
+ * AUTHOR: Steve Rhoads (rhoadss@yahoo.com)\r
+ * DATE CREATED: 4/4/08\r
+ * FILENAME: dll.h\r
+ * PROJECT: Plasma CPU core\r
+ * COPYRIGHT: Software placed into the public domain by the author.\r
+ *    Software 'as is' without warranty.  Author liable for nothing.\r
+ * DESCRIPTION:\r
+ *    Dynamic Link Library \r
+ *--------------------------------------------------------------------*/\r
+#ifndef __DLL_H__\r
+#define __DLL_H__\r
+\r
+#define INCLUDE_FILESYS\r
+#include "rtos.h"\r
+#include "tcpip.h"\r
+\r
+typedef void *(*DllFunc)();\r
+\r
+// Included by Plasma Kernel to create array of function pointers\r
+#ifdef DLL_SETUP\r
+\r
+void *DllDummy(void) { printf("Dummy"); return NULL; }\r
+\r
+const DllFunc DllFuncList[] = {\r
+   (DllFunc)strcpy,\r
+   (DllFunc)strncpy,\r
+   (DllFunc)strcat,\r
+   (DllFunc)strncat,\r
+   (DllFunc)strcmp,\r
+   (DllFunc)strncmp,\r
+   (DllFunc)strstr,\r
+   (DllFunc)strlen,\r
+   (DllFunc)memcpy,\r
+   (DllFunc)memmove,\r
+   (DllFunc)memcmp,\r
+   (DllFunc)memset,\r
+   (DllFunc)abs,\r
+   (DllFunc)rand,\r
+   (DllFunc)srand,\r
+   (DllFunc)strtol,\r
+   (DllFunc)atoi,\r
+   (DllFunc)itoa,\r
+   (DllFunc)sprintf,\r
+   (DllFunc)sscanf,\r
+#ifdef INCLUDE_DUMP\r
+   (DllFunc)dump,\r
+#else //INCLUDE_DUMP\r
+   DllDummy,\r
+#endif //INCLUDE_DUMP\r
+#ifdef INCLUDE_QSORT\r
+   (DllFunc)qsort,\r
+   (DllFunc)bsearch,\r
+#else //INCLUDE_QSORT\r
+   DllDummy,\r
+   DllDummy,\r
+#endif //INCLUDE_QSORT\r
+#ifdef INCLUDE_TIMELIB\r
+   (DllFunc)mktime,\r
+   (DllFunc)gmtime_r,\r
+   (DllFunc)gmtimeDst,\r
+   (DllFunc)gmtimeDstSet,\r
+#else //INCLUDE_TIMELIB\r
+   DllDummy,\r
+   DllDummy,\r
+   DllDummy,\r
+   DllDummy,\r
+#endif //INCLUDE_TIMELIB\r
+   (DllFunc)OS_AsmInterruptEnable,\r
+   (DllFunc)OS_HeapCreate,\r
+   (DllFunc)OS_HeapDestroy,\r
+   (DllFunc)OS_HeapMalloc,\r
+   (DllFunc)OS_HeapFree,\r
+   (DllFunc)OS_HeapAlternate,\r
+   (DllFunc)OS_HeapRegister,\r
+   (DllFunc)OS_ThreadCreate,\r
+   (DllFunc)OS_ThreadExit,\r
+   (DllFunc)OS_ThreadSelf,\r
+   (DllFunc)OS_ThreadSleep,\r
+   (DllFunc)OS_ThreadTime,\r
+   (DllFunc)OS_ThreadInfoSet,\r
+   (DllFunc)OS_ThreadInfoGet,\r
+   (DllFunc)OS_ThreadPriorityGet,\r
+   (DllFunc)OS_ThreadPrioritySet,\r
+   (DllFunc)OS_ThreadProcessId,\r
+   (DllFunc)OS_ThreadCpuLock,\r
+   (DllFunc)OS_SemaphoreCreate,\r
+   (DllFunc)OS_SemaphoreDelete,\r
+   (DllFunc)OS_SemaphorePend,\r
+   (DllFunc)OS_SemaphorePost,\r
+   (DllFunc)OS_MutexCreate,\r
+   (DllFunc)OS_MutexDelete,\r
+   (DllFunc)OS_MutexPend,\r
+   (DllFunc)OS_MutexPost,\r
+   (DllFunc)OS_MQueueCreate,\r
+   (DllFunc)OS_MQueueDelete,\r
+   (DllFunc)OS_MQueueSend,\r
+   (DllFunc)OS_MQueueGet,\r
+   (DllFunc)OS_Job,\r
+   (DllFunc)OS_TimerCreate,\r
+   (DllFunc)OS_TimerDelete,\r
+   (DllFunc)OS_TimerCallback,\r
+   (DllFunc)OS_TimerStart,\r
+   (DllFunc)OS_TimerStop,\r
+   (DllFunc)OS_InterruptRegister,\r
+   (DllFunc)OS_InterruptStatus,\r
+   (DllFunc)OS_InterruptMaskSet,\r
+   (DllFunc)OS_InterruptMaskClear,\r
+   (DllFunc)UartPrintf,\r
+   (DllFunc)UartPrintfPoll,\r
+   (DllFunc)UartPrintfCritical,\r
+   (DllFunc)UartScanf,\r
+   (DllFunc)puts,\r
+   (DllFunc)getch,\r
+   (DllFunc)kbhit,\r
+   (DllFunc)Led,\r
+   (DllFunc)FP_Sqrt,\r
+   (DllFunc)FP_Cos,\r
+   (DllFunc)FP_Sin,\r
+   (DllFunc)FP_Atan,\r
+   (DllFunc)FP_Atan2,\r
+   (DllFunc)FP_Exp,\r
+   (DllFunc)FP_Log,\r
+   (DllFunc)FP_Pow,\r
+#ifdef INCLUDE_FILESYS\r
+   (DllFunc)OS_fopen,\r
+   (DllFunc)OS_fclose,\r
+   (DllFunc)OS_fread,\r
+   (DllFunc)OS_fwrite,\r
+   (DllFunc)OS_fseek,\r
+   (DllFunc)OS_fmkdir,\r
+   (DllFunc)OS_fdir,\r
+   (DllFunc)OS_fdelete,\r
+#else //INCLUDE_FILESYS\r
+   DllDummy,\r
+   DllDummy,\r
+   DllDummy,\r
+   DllDummy,\r
+   DllDummy,\r
+   DllDummy,\r
+   DllDummy,\r
+   DllDummy,\r
+#endif //INCLUDE_FILESYS\r
+#ifndef WIN32\r
+   (DllFunc)FlashRead,\r
+   (DllFunc)FlashWrite,\r
+   (DllFunc)FlashErase,\r
+#else //WIN32\r
+   DllDummy,\r
+   DllDummy,\r
+   DllDummy,\r
+#endif //WIN32\r
+   (DllFunc)IPOpen,\r
+   (DllFunc)IPWriteFlush,\r
+   (DllFunc)IPWrite,\r
+   (DllFunc)IPRead,\r
+   (DllFunc)IPClose,\r
+   (DllFunc)IPPrintf,\r
+   (DllFunc)IPResolve,\r
+   (DllFunc)IPAddressSelf,\r
+   (DllFunc)IPNameValue\r
+};\r
+\r
+#endif //DLL_SETUP\r
+\r
+// Included by DLL to call OS functions via array of function pointers\r
+#if defined(DLL_CALL) || !defined(DLL_SETUP)\r
+\r
+enum {\r
+   ENUM_strcpy,\r
+   ENUM_strncpy,\r
+   ENUM_strcat,\r
+   ENUM_strncat,\r
+   ENUM_strcmp,\r
+   ENUM_strncmp,\r
+   ENUM_strstr,\r
+   ENUM_strlen,\r
+   ENUM_memcpy,\r
+   ENUM_memmove,\r
+   ENUM_memcmp,\r
+   ENUM_memset,\r
+   ENUM_abs,\r
+   ENUM_rand,\r
+   ENUM_srand,\r
+   ENUM_strtol,\r
+   ENUM_atoi,\r
+   ENUM_itoa,\r
+   ENUM_sprintf,\r
+   ENUM_sscanf,\r
+   ENUM_dump,\r
+   ENUM_qsort,\r
+   ENUM_bsearch,\r
+   ENUM_mktime,\r
+   ENUM_gmtime_r,\r
+   ENUM_gmtimeDst,\r
+   ENUM_gmtimeDstSet,\r
+   ENUM_OS_AsmInterruptEnable,\r
+   ENUM_OS_HeapCreate,\r
+   ENUM_OS_HeapDestroy,\r
+   ENUM_OS_HeapMalloc,\r
+   ENUM_OS_HeapFree,\r
+   ENUM_OS_HeapAlternate,\r
+   ENUM_OS_HeapRegister,\r
+   ENUM_OS_ThreadCreate,\r
+   ENUM_OS_ThreadExit,\r
+   ENUM_OS_ThreadSelf,\r
+   ENUM_OS_ThreadSleep,\r
+   ENUM_OS_ThreadTime,\r
+   ENUM_OS_ThreadInfoSet,\r
+   ENUM_OS_ThreadInfoGet,\r
+   ENUM_OS_ThreadPriorityGet,\r
+   ENUM_OS_ThreadPrioritySet,\r
+   ENUM_OS_ThreadProcessId,\r
+   ENUM_OS_ThreadCpuLock,\r
+   ENUM_OS_SemaphoreCreate,\r
+   ENUM_OS_SemaphoreDelete,\r
+   ENUM_OS_SemaphorePend,\r
+   ENUM_OS_SemaphorePost,\r
+   ENUM_OS_MutexCreate,\r
+   ENUM_OS_MutexDelete,\r
+   ENUM_OS_MutexPend,\r
+   ENUM_OS_MutexPost,\r
+   ENUM_OS_MQueueCreate,\r
+   ENUM_OS_MQueueDelete,\r
+   ENUM_OS_MQueueSend,\r
+   ENUM_OS_MQueueGet,\r
+   ENUM_OS_Job,\r
+   ENUM_OS_TimerCreate,\r
+   ENUM_OS_TimerDelete,\r
+   ENUM_OS_TimerCallback,\r
+   ENUM_OS_TimerStart,\r
+   ENUM_OS_TimerStop,\r
+   ENUM_OS_InterruptRegister,\r
+   ENUM_OS_InterruptStatus,\r
+   ENUM_OS_InterruptMaskSet,\r
+   ENUM_OS_InterruptMaskClear,\r
+   ENUM_UartPrintf,\r
+   ENUM_UartPrintfPoll,\r
+   ENUM_UartPrintfCritical,\r
+   ENUM_UartScanf,\r
+   ENUM_puts,\r
+   ENUM_getch,\r
+   ENUM_kbhit,\r
+   ENUM_Led,\r
+   ENUM_FP_Sqrt,\r
+   ENUM_FP_Cos,\r
+   ENUM_FP_Sin,\r
+   ENUM_FP_Atan,\r
+   ENUM_FP_Atan2,\r
+   ENUM_FP_Exp,\r
+   ENUM_FP_Log,\r
+   ENUM_FP_Pow,\r
+   ENUM_OS_fopen,\r
+   ENUM_OS_fclose,\r
+   ENUM_OS_fread,\r
+   ENUM_OS_fwrite,\r
+   ENUM_OS_fseek,\r
+   ENUM_OS_fmkdir,\r
+   ENUM_OS_fdir,\r
+   ENUM_OS_fdelete,\r
+   ENUM_FlashRead,\r
+   ENUM_FlashWrite,\r
+   ENUM_FlashErase,\r
+   ENUM_IPOpen,\r
+   ENUM_IPWriteFlush,\r
+   ENUM_IPWrite,\r
+   ENUM_IPRead,\r
+   ENUM_IPClose,\r
+   ENUM_IPPrintf,\r
+   ENUM_IPResolve,\r
+   ENUM_IPAddressSelf,\r
+   ENUM_IPNameValue\r
+};\r
+\r
+extern const DllFunc *DllF;\r
+\r
+#undef strcpy\r
+#undef strcat\r
+#undef strncat\r
+#undef strcmp\r
+#undef strlen\r
+#undef memcpy\r
+#undef memcmp\r
+#undef memset\r
+#undef abs\r
+#undef atoi\r
+#undef puts\r
+#undef getch\r
+#undef kbhit\r
+\r
+#define strcpy DllF[ENUM_strcpy]\r
+#define strncpy DllF[ENUM_strncpy]\r
+#define strcat DllF[ENUM_strcat]\r
+#define strncat DllF[ENUM_strncat]\r
+#define strcmp (int)DllF[ENUM_strcmp]\r
+#define strncmp (int)DllF[ENUM_strncmp]\r
+#define strstr DllF[ENUM_strstr]\r
+#define strlen (int)DllF[ENUM_strlen]\r
+#define memcpy DllF[ENUM_memcpy]\r
+#define memmove DllF[ENUM_memmove]\r
+#define memcmp (int)DllF[ENUM_memcmp]\r
+#define memset DllF[ENUM_memset]\r
+#define abs (int)DllF[ENUM_abs]\r
+#define rand (int)DllF[ENUM_rand]\r
+#define srand DllF[ENUM_srand]\r
+#define strtol (int)DllF[ENUM_strtol]\r
+#define atoi (int)DllF[ENUM_atoi]\r
+#define itoa DllF[ENUM_itoa]\r
+#define sprintf DllF[ENUM_sprintf]\r
+#define sscanf DllF[ENUM_sscanf]\r
+#define dump DllF[ENUM_dump]\r
+#define qsort DllF[ENUM_qsort]\r
+#define bsearch DllF[ENUM_bsearch]\r
+#define mktime DllF[ENUM_mktime]\r
+#define gmtime_r DllF[ENUM_gmtime_r]\r
+#define gmtimeDst DllF[ENUM_gmtimeDst]\r
+#define gmtimeDstSet DllF[ENUM_gmtimeDstSet]\r
+#define OS_AsmInterruptEnable (int)DllF[ENUM_OS_AsmInterruptEnable]\r
+#define OS_HeapCreate DllF[ENUM_OS_HeapCreate]\r
+#define OS_HeapDestroy DllF[ENUM_OS_HeapDestroy]\r
+#define OS_HeapMalloc DllF[ENUM_OS_HeapMalloc]\r
+#define OS_HeapFree DllF[ENUM_OS_HeapFree]\r
+#define OS_HeapAlternate DllF[ENUM_OS_HeapAlternate]\r
+#define OS_HeapRegister DllF[ENUM_OS_HeapRegister]\r
+#define OS_ThreadCreate DllF[ENUM_OS_ThreadCreate]\r
+#define OS_ThreadExit DllF[ENUM_OS_ThreadExit]\r
+#define OS_ThreadSelf DllF[ENUM_OS_ThreadSelf]\r
+#define OS_ThreadSleep DllF[ENUM_OS_ThreadSleep]\r
+#define OS_ThreadTime DllF[ENUM_OS_ThreadTime]\r
+#define OS_ThreadInfoSet DllF[ENUM_OS_ThreadInfoSet]\r
+#define OS_ThreadInfoGet DllF[ENUM_OS_ThreadInfoGet]\r
+#define OS_ThreadPriorityGet (int)DllF[ENUM_OS_ThreadPriorityGet]\r
+#define OS_ThreadPrioritySet DllF[ENUM_OS_ThreadPrioritySet]\r
+#define OS_ThreadProcessId DllF[ENUM_OS_ThreadProcessId]\r
+#define OS_ThreadCpuLock DllF[ENUM_OS_ThreadCpuLock]\r
+#define OS_SemaphoreCreate DllF[ENUM_OS_SemaphoreCreate]\r
+#define OS_SemaphoreDelete DllF[ENUM_OS_SemaphoreDelete]\r
+#define OS_SemaphorePend (int)DllF[ENUM_OS_SemaphorePend]\r
+#define OS_SemaphorePost DllF[ENUM_OS_SemaphorePost]\r
+#define OS_MutexCreate DllF[ENUM_OS_MutexCreate]\r
+#define OS_MutexDelete DllF[ENUM_OS_MutexDelete]\r
+#define OS_MutexPend (int)DllF[ENUM_OS_MutexPend]\r
+#define OS_MutexPost DllF[ENUM_OS_MutexPost]\r
+#define OS_MQueueCreate DllF[ENUM_OS_MQueueCreate]\r
+#define OS_MQueueDelete DllF[ENUM_OS_MQueueDelete]\r
+#define OS_MQueueSend DllF[ENUM_OS_MQueueSend]\r
+#define OS_MQueueGet (int)DllF[ENUM_OS_MQueueGet]\r
+#define OS_Job DllF[ENUM_OS_Job]\r
+#define OS_TimerCreate DllF[ENUM_OS_TimerCreate]\r
+#define OS_TimerDelete DllF[ENUM_OS_TimerDelete]\r
+#define OS_TimerCallback DllF[ENUM_OS_TimerCallback]\r
+#define OS_TimerStart DllF[ENUM_OS_TimerStart]\r
+#define OS_TimerStop DllF[ENUM_OS_TimerStop]\r
+#define OS_InterruptRegister DllF[ENUM_OS_InterruptRegister]\r
+#define OS_InterruptStatus (int)DllF[ENUM_OS_InterruptStatus]\r
+#define OS_InterruptMaskSet DllF[ENUM_OS_InterruptMaskSet]\r
+#define OS_InterruptMaskClear DllF[ENUM_OS_InterruptMaskClear]\r
+#define UartPrintf DllF[ENUM_UartPrintf]\r
+#define UartPrintfPoll DllF[ENUM_UartPrintfPoll]\r
+#define UartPrintfCritical DllF[ENUM_UartPrintfCritical]\r
+#define UartScanf DllF[ENUM_UartScanf]\r
+#define puts DllF[ENUM_puts]\r
+#define getch (int)DllF[ENUM_getch]\r
+#define kbhit (int)DllF[ENUM_kbhit]\r
+#define Led DllF[ENUM_Led]\r
+#define FP_Sqrt (float)(int)DllF[ENUM_FP_Sqrt]\r
+#define FP_Cos (float)(int)DllF[ENUM_FP_Cos]\r
+#define FP_Sin (float)(int)DllF[ENUM_FP_Sin]\r
+#define FP_Atan (float)(int)DllF[ENUM_FP_Atan]\r
+#define FP_Atan2 (float)(int)DllF[ENUM_FP_Atan2]\r
+#define FP_Exp (float)(int)DllF[ENUM_FP_Exp]\r
+#define FP_Log (float)(int)DllF[ENUM_FP_Log]\r
+#define FP_Pow (float)(int)DllF[ENUM_FP_Pow]\r
+#define OS_fopen DllF[ENUM_OS_fopen]\r
+#define OS_fclose DllF[ENUM_OS_fclose]\r
+#define OS_fread (int)DllF[ENUM_OS_fread]\r
+#define OS_fwrite DllF[ENUM_OS_fwrite]\r
+#define OS_fseek DllF[ENUM_OS_fseek]\r
+#define OS_fmkdir DllF[ENUM_OS_fmkdir]\r
+#define OS_fdir DllF[ENUM_OS_fdir]\r
+#define OS_fdelete DllF[ENUM_OS_fdelete]\r
+#define FlashRead DllF[ENUM_FlashRead]\r
+#define FlashWrite DllF[ENUM_FlashWrite]\r
+#define FlashErase DllF[ENUM_FlashErase]\r
+#define IPOpen DllF[ENUM_IPOpen]\r
+#define IPWriteFlush DllF[ENUM_IPWriteFlush]\r
+#define IPWrite (int)DllF[ENUM_IPWrite]\r
+#define IPRead (int)DllF[ENUM_IPRead]\r
+#define IPClose DllF[ENUM_IPClose]\r
+#define IPPrintf DllF[ENUM_IPPrintf]\r
+#define IPResolve DllF[ENUM_IPResolve]\r
+#define IPAddressSelf (int)DllF[ENUM_IPAddressSelf]\r
+#define IPNameValue DllF[ENUM_IPNameValue]\r
+\r
+#endif //DLL_CALL\r
+\r
+\r
+#if defined(DLL_SETUP) && defined(DLL_CALL)\r
+const DllFunc *DllF = DllFuncList;\r
+#elif !defined(DLL_SETUP) && !defined(DLL_CALL) && !defined(DLL_ENTRY)\r
+#define DLL_ENTRY 1\r
+#endif //DLL_SETUP && DLL_CALL\r
+\r
+\r
+// Included by DLL to initialize the DLL\r
+#if defined(DLL_ENTRY) && !defined(NO_DLL_ENTRY)\r
+const DllFunc *DllF;            //array of function pointers\r
+extern void *__bss_start;\r
+extern void *_end;\r
+void Start(IPSocket *socket, char *argv[]);\r
+\r
+//Must be first function in file\r
+void *__start(DllFunc *DllFuncList)\r
+{\r
+   int *bss;\r
+   if(DllFuncList == NULL)\r
+      return (void*)__start;      //address where DLL should be loaded\r
+   for(bss = (int*)&__bss_start; bss < (int*)&_end; ++bss)\r
+      *bss = 0;\r
+   DllF = DllFuncList;\r
+   return (void*)Start;\r
+}\r
+#endif //DLL_ENTRY\r
+\r
+\r
+#ifdef DLL_STRINGS\r
+const char * const DllStrings[] = {\r
+   "strcpy",\r
+   "strncpy",\r
+   "strcat",\r
+   "strncat",\r
+   "strcmp",\r
+   "strncmp",\r
+   "strstr",\r
+   "strlen",\r
+   "memcpy",\r
+   "memmove",\r
+   "memcmp",\r
+   "memset",\r
+   "abs",\r
+   "rand",\r
+   "srand",\r
+   "strtol",\r
+   "atoi",\r
+   "itoa",\r
+   "sprintf",\r
+   "sscanf",\r
+   "dump",\r
+   "qsort",\r
+   "bsearch",\r
+   "mktime",\r
+   "gmtime_r",\r
+   "gmtimeDst",\r
+   "gmtimeDstSet",\r
+   "OS_AsmInterruptEnable",\r
+   "OS_HeapCreate",\r
+   "OS_HeapDestroy",\r
+   "OS_HeapMalloc",\r
+   "OS_HeapFree",\r
+   "OS_HeapAlternate",\r
+   "OS_HeapRegister",\r
+   "OS_ThreadCreate",\r
+   "OS_ThreadExit",\r
+   "OS_ThreadSelf",\r
+   "OS_ThreadSleep",\r
+   "OS_ThreadTime",\r
+   "OS_ThreadInfoSet",\r
+   "OS_ThreadInfoGet",\r
+   "OS_ThreadPriorityGet",\r
+   "OS_ThreadPrioritySet",\r
+   "OS_ThreadProcessId",\r
+   "OS_ThreadCpuLock",\r
+   "OS_SemaphoreCreate",\r
+   "OS_SemaphoreDelete",\r
+   "OS_SemaphorePend",\r
+   "OS_SemaphorePost",\r
+   "OS_MutexCreate",\r
+   "OS_MutexDelete",\r
+   "OS_MutexPend",\r
+   "OS_MutexPost",\r
+   "OS_MQueueCreate",\r
+   "OS_MQueueDelete",\r
+   "OS_MQueueSend",\r
+   "OS_MQueueGet",\r
+   "OS_Job",\r
+   "OS_TimerCreate",\r
+   "OS_TimerDelete",\r
+   "OS_TimerCallback",\r
+   "OS_TimerStart",\r
+   "OS_TimerStop",\r
+   "OS_InterruptRegister",\r
+   "OS_InterruptStatus",\r
+   "OS_InterruptMaskSet",\r
+   "OS_InterruptMaskClear",\r
+   "printf", //"UartPrintf",\r
+   "UartPrintfPoll",\r
+   "UartPrintfCritical",\r
+   "scanf", //"UartScanf",\r
+   "puts",\r
+   "getch",\r
+   "kbhit",\r
+   "Led",\r
+   "FP_Sqrt",\r
+   "FP_Cos",\r
+   "FP_Sin",\r
+   "FP_Atan",\r
+   "FP_Atan2",\r
+   "FP_Exp",\r
+   "FP_Log",\r
+   "FP_Pow",\r
+   "OS_fopen",\r
+   "OS_fclose",\r
+   "OS_fread",\r
+   "OS_fwrite",\r
+   "OS_fseek",\r
+   "OS_fmkdir",\r
+   "OS_fdir",\r
+   "OS_fdelete",\r
+   "FlashRead",\r
+   "FlashWrite",\r
+   "FlashErase",\r
+   "IPOpen",\r
+   "IPWriteFlush",\r
+   "IPWrite",\r
+   "IPRead",\r
+   "IPClose",\r
+   "IPPrintf",\r
+   "IPResolve",\r
+   "IPAddressSelf",\r
+   "IPNameValue",\r
+   NULL\r
+};\r
+#endif //DLL_STRINGS\r
+\r
+#endif //__DLL_H__\r
+\r
diff --git a/kernel/dlltest.c b/kernel/dlltest.c
new file mode 100644 (file)
index 0000000..12a4390
--- /dev/null
@@ -0,0 +1,38 @@
+// dlltest.c\r
+// Compile this program with "make dlltest".  \r
+// Then ftp test.bin to /flash/bin/dlltest.\r
+// Then from a telnet prompt type "dlltest".\r
+#include "dll.h"\r
+\r
+\r
+void SocketReceive(IPSocket *socket)\r
+{\r
+}\r
+\r
+\r
+void MyThread(void *sock)\r
+{\r
+   char buf[80];\r
+   int i, bytes;\r
+   IPSocket *socket = sock;\r
+\r
+   for(i = 0; i < 10; ++i)\r
+   {\r
+      bytes = IPRead(socket, buf, sizeof(buf)-1);\r
+      buf[bytes] = 0;\r
+      IPPrintf(socket, "%d %s\n", i, buf);\r
+      OS_ThreadSleep(100);\r
+   }\r
+   socket->funcPtr = socket->userFunc;  //restore socket receive function\r
+}\r
+\r
+\r
+// Function shouldn't block\r
+void Start(IPSocket *socket, char *argv[])\r
+{\r
+   IPPrintf(socket, "Hello from dlltest\n");\r
+   socket->userFunc = socket->funcPtr;  //remember prev socket receive func\r
+   socket->funcPtr = SocketReceive;     //new socket receive function\r
+   OS_ThreadCreate("MyThread", MyThread, socket, 100, 0);\r
+}\r
+\r
diff --git a/kernel/ethernet.c b/kernel/ethernet.c
new file mode 100644 (file)
index 0000000..752b55d
--- /dev/null
@@ -0,0 +1,428 @@
+/*--------------------------------------------------------------------
+ * TITLE: Plasma Ethernet MAC
+ * AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
+ * DATE CREATED: 1/12/08
+ * FILENAME: ethernet.c
+ * PROJECT: Plasma CPU core
+ * COPYRIGHT: Software placed into the public domain by the author.
+ *    Software 'as is' without warranty.  Author liable for nothing.
+ * DESCRIPTION:
+ *    Ethernet MAC implementation.
+ *    Data is received from the Ethernet PHY four bits at a time. 
+ *    After 32-bits are received they are written to 0x13ff0000 + N.  
+ *    The data is received LSB first for each byte which requires the
+ *    nibbles to be swapped.
+ *    Transmit data is read from 0x13fe0000.  Write length/4+1 to
+ *    ETHERNET_REG to start transfer.
+ *--------------------------------------------------------------------*/
+#include "plasma.h"
+#include "rtos.h"
+#include "tcpip.h"
+
+#define POLYNOMIAL  0x04C11DB7   //CRC bit 33 is truncated
+#define TOPBIT      (1<<31)
+#define BYTE_EMPTY  0xde         //Data copied into receive buffer
+#define COUNT_EMPTY 16           //Count to decide there isn't data
+#define INDEX_MASK  0xffff       //Size of receive buffer
+
+//void dump(const unsigned char *data, int length);
+
+static unsigned char gDestMac[]={0x5d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+static unsigned int CrcTable[256];
+static unsigned char reflect[256];
+static unsigned char reflectNibble[256];
+static OS_Semaphore_t *SemEthernet, *SemEthTransmit;
+static int gIndex;          //byte index into 0x13ff0000 receive buffer
+static int gCheckedBefore;
+static int gEmptyBefore;
+
+
+//Read received data from 0x13ff0000.  Data starts with 0x5d+MACaddress.
+//Data is being received while processing the data.  Therefore,
+//all errors require waiting and then re-processing the data
+//to see if the error is fixed by receiving the rest of the packet.
+int EthernetReceive(unsigned char *buffer, int length)
+{
+   int count;
+   int start, i, j, shift, offset;
+   int byte, byteNext;
+   unsigned long crc;
+   int byteCrc;
+   volatile unsigned char *buf = (unsigned char*)ETHERNET_RECEIVE;
+   int countEmpty, countEmptyGoal, countOk, needWait;
+   int packetExpected;
+
+   //Find the start of a frame
+   countEmpty = 0;
+   countOk = 0;
+   needWait = 0;
+   countEmptyGoal = COUNT_EMPTY;
+   packetExpected = MemoryRead(IRQ_STATUS) & IRQ_ETHERNET_RECEIVE;
+   if(packetExpected && buf[gIndex] == BYTE_EMPTY && gEmptyBefore)
+   {
+      //printf("Check ");
+      countEmptyGoal = 1500;
+   }
+   MemoryRead(ETHERNET_REG);        //clear receive interrupt
+   for(i = 0; i < INDEX_MASK; ++i)
+   {
+      //Check if partial packet possibly received
+      if(needWait && gCheckedBefore == 0 && countOk != i && countEmpty != i)
+      {
+         gCheckedBefore = 1;
+         //printf("W(%d,%d,%d)", i, countOk, countEmpty);
+         return 0;                  //Wait for more data
+      }
+
+      //Detect start of frame
+      byte = buf[(gIndex + i) & INDEX_MASK];
+      if(byte == gDestMac[countOk] || (countOk && byte == 0xff))
+      {
+         if(++countOk == sizeof(gDestMac))
+         {
+            //Set bytes before 0x5d to BYTE_EMPTY
+            offset = i - (int)sizeof(gDestMac);
+            //if(offset > 3)
+            //   printf("es%d ", offset);
+            for(j = 0; j <= offset; ++j)
+            {
+               buf[gIndex] = BYTE_EMPTY;
+               gIndex = (gIndex + 1) & INDEX_MASK;
+            }
+            break;
+         }
+      }
+      else
+      {
+         //if(countOk)
+         //   printf("N%d ", countOk);
+         if(countOk == 3 && byte == BYTE_EMPTY)
+            needWait = 1;
+         if(byte == 0x5d)
+            countOk = 1;
+         else
+            countOk = 0;
+      }
+
+      //Check if remainder of buffer is empty
+      if(byte == BYTE_EMPTY)
+      {
+         if(++countEmpty >= countEmptyGoal)
+         {
+            //Set skiped bytes to BYTE_EMPTY
+            //if(i - countEmpty > 3)
+            //{
+            //   printf("eb%d \n", i - countEmpty);
+            //   //dump((char*)buf+gIndex, 0x200);
+            //}
+            for(j = 0; j <= i - countEmpty; ++j)
+            {
+               buf[gIndex] = BYTE_EMPTY;
+               gIndex = (gIndex + 1) & INDEX_MASK;
+            }
+            gCheckedBefore = 0;
+            if(countEmpty >= i && packetExpected)
+               gEmptyBefore = 1;
+            return 0;
+         }
+      }
+      else
+      {
+         if(countEmpty > 2 || (countEmpty > 0 && countEmpty == i))
+            needWait = 1;
+         countEmpty = 0;
+         gEmptyBefore = 0;
+      }
+   }
+
+   //Found start of frame.  Now find end of frame and check CRC.
+   start = gIndex;
+   gIndex = (gIndex + 1) & INDEX_MASK;           //skip 0x5d byte
+   crc = 0xffffffff;
+   for(count = 0; count < length; )
+   {
+      byte = buf[gIndex];
+      gIndex = (gIndex + 1) & INDEX_MASK;
+
+      byte = ((byte << 4) & 0xf0) | (byte >> 4); //swap nibbles
+      buffer[count++] = (unsigned char)byte;
+      byte = reflect[byte] ^ (crc >> 24);        //calculate CRC32
+      crc = CrcTable[byte] ^ (crc << 8);
+      if(count >= 40)
+      {
+         //Check if CRC matches to detect end of frame
+         byteCrc = reflectNibble[crc >> 24];
+         byteNext = buf[gIndex];
+         if(byteCrc == byteNext)
+         {
+            for(i = 1; i < 4; ++i)
+            {
+               shift = 24 - (i << 3);
+               byteCrc = reflectNibble[(crc >> shift) & 0xff];
+               byteNext = buf[(gIndex + i) & 0xffff];
+               if(byteCrc != byteNext)
+               {
+                  //printf("nope %d %d 0x%x 0x%x\n", count, i, byteCrc, byteNext);
+                  i = 99;
+               }
+            }
+            if(i == 4)
+            {
+               //Found end of frame -- set used bytes to BYTE_EMPTY
+               //printf("Found it! %d\n", count);
+               gIndex = (gIndex + 4) & INDEX_MASK;
+               for(i = 0; i < count+5; ++i)
+                  buf[(start + i) & INDEX_MASK] = BYTE_EMPTY;
+               while(gIndex & 3)
+               {
+                  buf[gIndex] = BYTE_EMPTY;
+                  gIndex = (gIndex + 1) & INDEX_MASK;
+               }
+               gCheckedBefore = 0;
+               return count;
+            }
+         }
+      }
+   }
+   gIndex = start;
+   if(gCheckedBefore)
+   {
+      //printf("CRC failure\n");
+      buf[gIndex] = BYTE_EMPTY;
+   }
+   gCheckedBefore = 1;
+   return 0;        //wait for more data
+}
+
+
+//Copy transmit data to 0x13fe0000 with preamble and CRC32
+void EthernetTransmit(unsigned char *buffer, int length)
+{
+   int i, byte, shift;
+   unsigned long crc;
+   volatile unsigned char *buf = (unsigned char*)ETHERNET_TRANSMIT;
+
+   OS_SemaphorePend(SemEthTransmit, OS_WAIT_FOREVER);
+
+   //Wait for previous transfer to complete
+   for(i = 0; i < 10000; ++i)
+   {
+      if(MemoryRead(IRQ_STATUS) & IRQ_ETHERNET_TRANSMIT)
+         break;
+   }
+   //if(i > 100)
+   //   printf("wait=%d ", i);
+
+   Led(2, 2);
+   while(length < 60 || (length & 3) != 0)
+      buffer[length++] = 0;
+
+   //Start of Ethernet frame
+   for(i = 0; i < 7; ++i)
+      buf[i] = 0x55;
+   buf[7] = 0x5d;
+
+   //Calculate CRC32
+   crc = 0xffffffff;
+   for(i = 0; i < length; ++i)
+   {
+      byte = buffer[i];
+      buf[i + 8] = (unsigned char)((byte << 4) | (byte >> 4)); //swap nibbles
+      byte = reflect[byte] ^ (crc >> 24);        //calculate CRC32
+      crc = CrcTable[byte] ^ (crc << 8);
+   }
+
+   //Output CRC32
+   for(i = 0; i < 4; ++i)
+   {
+      shift = 24 - (i << 3);
+      byte = reflectNibble[(crc >> shift) & 0xff];
+      buf[length + 8 + i] = (unsigned char)byte;
+   }
+
+   //Start transfer
+   length = (length + 12 + 4) >> 2;
+   MemoryWrite(ETHERNET_REG, length);
+   Led(2, 0);
+
+   OS_SemaphorePost(SemEthTransmit);
+}
+
+
+void EthernetThread(void *arg)
+{
+   int length;
+   int rc;\r
+   unsigned int ticks, ticksLast=0;
+   IPFrame *ethFrame=NULL;\r
+   static int ethErrorCount=0;
+   (void)arg;
+
+   for(;;)
+   {\r
+      OS_InterruptMaskSet(IRQ_ETHERNET_RECEIVE);
+      OS_SemaphorePend(SemEthernet, 50);  //wait for interrupt\r
+
+      //Process all received packets
+      for(;;)
+      {
+         if(ethFrame == NULL)
+            ethFrame = IPFrameGet(FRAME_COUNT_RCV);
+         if(ethFrame == NULL)\r
+         {\r
+            OS_ThreadSleep(50);
+            break;\r
+         }
+         length = EthernetReceive(ethFrame->packet, PACKET_SIZE);
+         if(length == 0)\r
+         {\r
+#if 1       //Disable this on quiet networks\r
+            //No Ethernet packets seen for 60 seconds?\r
+            if(++ethErrorCount >= 120)\r
+            {\r
+               printf("\nEthernetInit\n");\r
+               ethErrorCount = 0;\r
+               EthernetInit(NULL);  //Need to re-initialize\r
+            }\r
+#endif\r
+            break;\r
+         }\r
+         ethErrorCount = 0;\r
+         Led(1, 1);
+         rc = IPProcessEthernetPacket(ethFrame, length);
+         Led(1, 0);
+         if(rc)
+            ethFrame = NULL;
+      }
+
+      ticks = OS_ThreadTime();
+      if(ticks - ticksLast >= 50)
+      {
+         IPTick();
+         ticksLast = ticks;
+      }
+   }
+}
+
+
+void EthernetIsr(void *arg)
+{
+   (void)arg;\r
+   OS_InterruptMaskClear(IRQ_ETHERNET_TRANSMIT | IRQ_ETHERNET_RECEIVE);
+   OS_SemaphorePost(SemEthernet);\r
+}
+
+
+/******************* CRC32 calculations **********************
+ * The CRC32 code is modified from Michale Barr's article in 
+ * Embedded Systems Programming January 2000.
+ * A CRC is really modulo-2 binary division.  Substraction means XOR. */
+static unsigned int Reflect(unsigned int value, int bits)
+{
+   unsigned int num=0;
+   int i;
+   for(i = 0; i < bits; ++i)
+   {
+      num = (num << 1) | (value & 1);
+      value >>= 1;
+   }
+   return num;
+}
+
+
+static void CrcInit(void)
+{
+   unsigned int remainder;
+   int dividend, bit, i;
+
+   //Compute the remainder of each possible dividend
+   for(dividend = 0; dividend < 256; ++dividend)
+   {
+      //Start with the dividend followed by zeros
+      remainder = dividend << 24;
+      //Perform modulo-2 division, a bit at a time
+      for(bit = 8; bit > 0; --bit)
+      {
+         //Try to divide the current data bit
+         if(remainder & TOPBIT)
+            remainder = (remainder << 1) ^ POLYNOMIAL;
+         else
+            remainder = remainder << 1;
+      }
+      CrcTable[dividend] = remainder;
+   }
+   for(i = 0; i < 256; ++i)
+   {
+      reflect[i] = (unsigned char)Reflect(i, 8);
+      reflectNibble[i] = (unsigned char)((Reflect((i >> 4) ^ 0xf, 4) << 4) | 
+         Reflect(i ^ 0xf, 4));
+   }
+}
+
+
+static void SpinWait(int clocks)
+{
+   int value = *(volatile int*)COUNTER_REG + clocks;
+   while(*(volatile int*)COUNTER_REG - value < 0)
+      ;
+}
+
+
+void EthernetInit(unsigned char MacAddress[6])
+{
+   //Format of SMI data: 0101 A4:A0 R4:R0 00 D15:D0
+   unsigned long data=0x5f800100; //SMI R0 = 10Mbps full duplex
+   //unsigned long data=0x5f800000; //SMI R0 = 10Mbps half duplex
+   int i, value;
+   volatile unsigned char *buf = (unsigned char*)ETHERNET_RECEIVE;
+
+   CrcInit();\r
+   if(MacAddress)\r
+   {
+      for(i = 0; i < 6; ++i)
+      {
+         value = MacAddress[i];
+         gDestMac[i+1] = (unsigned char)((value >> 4) | (value << 4));
+      }\r
+   }
+
+   //Configure Ethernet PHY for 10Mbps full duplex via SMI interface
+   MemoryWrite(GPIO0_OUT, ETHERNET_MDIO | ETHERNET_MDIO_WE | ETHERENT_MDC);
+   for(i = 0; i < 34; ++i)
+   {
+      MemoryWrite(GPIO0_OUT, ETHERENT_MDC);    //clock high
+      SpinWait(10);
+      MemoryWrite(GPIO0_CLEAR, ETHERENT_MDC);  //clock low
+      SpinWait(10);
+   }
+   for(i = 31; i >= 0; --i)
+   {
+      value = (data >> i) & 1;
+      if(value)
+         MemoryWrite(GPIO0_OUT, ETHERNET_MDIO);
+      else
+         MemoryWrite(GPIO0_CLEAR, ETHERNET_MDIO);
+      MemoryWrite(GPIO0_OUT, ETHERENT_MDC);    //clock high
+      SpinWait(10);
+      MemoryWrite(GPIO0_CLEAR, ETHERENT_MDC);  //clock low
+      SpinWait(10);
+   }
+   MemoryWrite(GPIO0_CLEAR, ETHERNET_MDIO_WE | ETHERNET_ENABLE);
+
+   //Clear receive buffer
+   for(i = 0; i <= INDEX_MASK; ++i)
+      buf[i] = BYTE_EMPTY;
+
+   if(SemEthernet == NULL)\r
+   {\r
+      SemEthernet = OS_SemaphoreCreate("eth", 0);
+      SemEthTransmit = OS_SemaphoreCreate("ethT", 1);
+      OS_ThreadCreate("eth", EthernetThread, NULL, 240, 0);
+   }
+
+   //Setup interrupts for receiving data
+   OS_InterruptRegister(IRQ_ETHERNET_RECEIVE, EthernetIsr);\r
+
+   //Start receive DMA
+   MemoryWrite(GPIO0_OUT, ETHERNET_ENABLE);
+}
diff --git a/kernel/filesys.c b/kernel/filesys.c
new file mode 100644 (file)
index 0000000..eefdf97
--- /dev/null
@@ -0,0 +1,767 @@
+/*--------------------------------------------------------------------
+ * TITLE: Plasma File System
+ * AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
+ * DATE CREATED: 4/26/07
+ * FILENAME: filesys.c
+ * PROJECT: Plasma CPU core
+ * COPYRIGHT: Software placed into the public domain by the author.
+ *    Software 'as is' without warranty.  Author liable for nothing.
+ * DESCRIPTION:
+ *    Plasma File System.  Supports RAM, flash, and disk file systems.
+ *    Possible call tree:
+ *      OS_fclose()
+ *        FileFindRecursive()      //find the existing file
+ *          FileOpen()             //open root file system
+ *          FileFind()             //find the next level of directory
+ *            OS_fread()           //read the directory file
+ *              BlockRead()        //read blocks of directory
+ *                MediaBlockRead() //low level read
+ *          FileOpen()             //open next directory
+ *        OS_fwrite()              //write file entry into directory
+ *        BlockRead()              //flush changes to directory
+ *--------------------------------------------------------------------*/
+#ifdef WIN32
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#define  _LIBC
+#endif
+#include "rtos.h"
+
+#define FLASH_SIZE        1024*1024*16
+#define FLASH_SECTOR_SIZE 1024*128
+#define FLASH_BLOCK_SIZE  512
+#define FLASH_LN2_SIZE    9                  //2^FLASH_LN2_SIZE == FLASH_BLOCK_SIZE
+#define FLASH_OFFSET      FLASH_SECTOR_SIZE  //offset to start of flash file system
+
+#define BLOCK_SIZE        512
+#define FILE_NAME_SIZE    40
+#define FULL_NAME_SIZE    128
+#define BLOCK_MALLOC      0x0
+#define BLOCK_EOF         0xffffffff
+
+typedef enum {
+   FILE_MEDIA_RAM,
+   FILE_MEDIA_FLASH,
+   FILE_MEDIA_DISK
+} OS_MediaType_e;
+
+typedef struct OS_FileEntry_s {
+   char name[FILE_NAME_SIZE];
+   uint32 blockIndex;       //first block of file
+   uint32 modifiedTime;
+   uint32 length;
+   uint8 isDirectory;
+   uint8 attributes;
+   uint8 valid;
+   uint8 mediaType;
+   uint16 blockSize;        //Normally BLOCK_SIZE
+} OS_FileEntry_t;
+
+typedef struct OS_Block_s {
+   uint32 next;
+   uint8 data[4];
+} OS_Block_t;
+
+struct OS_FILE_s {
+   OS_FileEntry_t fileEntry;  //written to directory upon OS_fclose()
+   uint8 fileModified;
+   uint8 blockModified;
+   uint32 blockIndex;         //index of block
+   uint32 blockOffset;        //byte offset into block
+   uint32 fileOffset;         //byte offset into file
+   char fullname[FULL_NAME_SIZE]; //includes full path
+   OS_Block_t *block;
+   OS_Block_t *blockLocal;    //local copy for flash or disk file system
+};
+
+static OS_FileEntry_t rootFileEntry;
+static OS_Mutex_t *mutexFilesys;
+
+// Public prototypes
+#ifndef _FILESYS_
+typedef struct OS_FILE_s OS_FILE;
+#endif
+OS_FILE *OS_fopen(char *name, char *mode);
+void OS_fclose(OS_FILE *file);
+int OS_fread(void *buffer, int size, int count, OS_FILE *file);
+int OS_fwrite(void *buffer, int size, int count, OS_FILE *file);
+int OS_fseek(OS_FILE *file, int offset, int mode);
+int OS_fmkdir(char *name);
+int OS_fdir(OS_FILE *dir, char name[64]);
+void OS_fdelete(char *name);
+
+
+/***************** Media Functions Start ***********************/
+#ifdef INCLUDE_FLASH
+#define FLASH_BLOCKS FLASH_SIZE/FLASH_BLOCK_SIZE
+#define FLASH_START  (FLASH_OFFSET+FLASH_BLOCKS/8*2)/FLASH_BLOCK_SIZE
+static unsigned char FlashBlockEmpty[FLASH_BLOCKS/8];
+static unsigned char FlashBlockUsed[FLASH_BLOCKS/8];
+static int FlashBlock;
+
+//Free unused flash blocks
+static int MediaBlockCleanup(void)
+{
+   int i, sector, block, count=0;
+   unsigned char *buf;
+
+   printf("FlashCleanup\n");
+   buf = (unsigned char*)malloc(FLASH_SECTOR_SIZE);
+   if(buf == NULL)
+      return 0;
+   for(sector = FLASH_OFFSET / FLASH_SECTOR_SIZE; sector < FLASH_SIZE / FLASH_SECTOR_SIZE; ++sector)
+   {
+      FlashRead((uint16*)buf, FLASH_SECTOR_SIZE*sector, FLASH_SECTOR_SIZE);
+      if(sector == FLASH_OFFSET / FLASH_SECTOR_SIZE)
+      {
+         for(i = 0; i < FLASH_BLOCKS/8; ++i)
+            FlashBlockEmpty[i] |= ~FlashBlockUsed[i];
+         memcpy(buf, FlashBlockEmpty, sizeof(FlashBlockEmpty));
+         memset(FlashBlockUsed, 0xff, sizeof(FlashBlockUsed));
+         memset(buf+sizeof(FlashBlockEmpty), 0xff, sizeof(FlashBlockUsed));
+      }
+      //Erase empty blocks
+      for(block = 0; block < FLASH_SECTOR_SIZE / FLASH_BLOCK_SIZE; ++block)
+      {
+         i = sector * FLASH_SECTOR_SIZE / FLASH_BLOCK_SIZE + block;
+         if(i < FLASH_BLOCKS/8 && (FlashBlockEmpty[i >> 3] & (1 << (i & 7))))
+         {
+            memset(buf + FLASH_BLOCK_SIZE*block, 0xff, FLASH_BLOCK_SIZE);
+            ++count;
+         }
+      }
+      FlashErase(FLASH_SECTOR_SIZE * sector);
+      FlashWrite((uint16*)buf, FLASH_SECTOR_SIZE * sector, FLASH_SECTOR_SIZE);
+   }
+   free(buf);
+   return count;
+}
+
+
+int MediaBlockInit(void)
+{
+   FlashRead((uint16*)FlashBlockEmpty, FLASH_OFFSET, sizeof(FlashBlockEmpty));
+   FlashRead((uint16*)FlashBlockUsed, FLASH_OFFSET+sizeof(FlashBlockEmpty), 
+             sizeof(FlashBlockUsed));
+   FlashBlock = FLASH_START;
+   return FlashBlockEmpty[FlashBlock >> 3] & (1 << (FlashBlock & 7));
+}
+#endif
+
+
+static uint32 MediaBlockMalloc(OS_FILE *file)
+{
+   int i, j;
+   (void)i; (void)j;
+
+   if(file->fileEntry.mediaType == FILE_MEDIA_RAM)
+      return (uint32)malloc(file->fileEntry.blockSize);
+#ifdef INCLUDE_FLASH
+   //Find empty flash block
+   for(i = FlashBlock; i < FLASH_BLOCKS; ++i)
+   {
+      if(FlashBlockEmpty[i >> 3] & (1 << (i & 7)))
+      {
+         FlashBlock = i + 1;
+         FlashBlockEmpty[i >> 3] &= ~(1 << (i & 7));
+         j = i >> 3;
+         j &= ~1;
+         FlashWrite((uint16*)(FlashBlockEmpty + j), FLASH_OFFSET + j, 2);
+         return i;
+      }
+   }
+
+   i = MediaBlockCleanup();
+   if(i == 0)
+      return 0;
+   FlashBlock = FLASH_START;
+   return MediaBlockMalloc(file);
+#else
+   return 0;
+#endif
+}
+
+
+static void MediaBlockFree(OS_FILE *file, uint32 blockIndex)
+{
+   if(file->fileEntry.mediaType == FILE_MEDIA_RAM)
+      free((void*)blockIndex);
+#ifdef INCLUDE_FLASH
+   else
+   {
+      int i=blockIndex, j;
+      FlashBlockUsed[i >> 3] &= ~(1 << (i & 7));
+      j = i >> 3;
+      j &= ~1;
+      FlashWrite((uint16*)(FlashBlockUsed + j), FLASH_OFFSET + sizeof(FlashBlockEmpty) + j, 2);
+   }
+#endif
+}
+
+
+static void MediaBlockRead(OS_FILE *file, uint32 blockIndex)
+{
+   if(file->fileEntry.mediaType == FILE_MEDIA_RAM)
+      file->block = (OS_Block_t*)blockIndex;
+#ifdef INCLUDE_FLASH
+   else
+   {
+      if(file->blockLocal == NULL)
+         file->blockLocal = (OS_Block_t*)malloc(FLASH_BLOCK_SIZE);
+      file->block = file->blockLocal;
+      FlashRead((uint16*)file->block, blockIndex << FLASH_LN2_SIZE, FLASH_BLOCK_SIZE);
+   }
+#endif
+}
+
+
+static void MediaBlockWrite(OS_FILE *file, uint32 blockIndex)
+{
+   (void)file;
+   (void)blockIndex;
+#ifdef INCLUDE_FLASH
+   if(file->fileEntry.mediaType != FILE_MEDIA_RAM)
+      FlashWrite((uint16*)file->block, blockIndex << FLASH_LN2_SIZE, FLASH_BLOCK_SIZE);
+#endif
+}
+
+/***************** Media Functions End *************************/
+
+// Get the next block and write the old block if it was modified
+static void BlockRead(OS_FILE *file, uint32 blockIndex)
+{
+   uint32 blockIndexSave = blockIndex;
+
+   OS_MutexPend(mutexFilesys);
+   if(blockIndex == BLOCK_MALLOC)
+   {
+      // Get a new block
+      blockIndex = MediaBlockMalloc(file);
+      if(blockIndex == 0)
+         blockIndex = BLOCK_EOF;
+      if(file->block)
+      {
+         // Set next pointer in previous block
+         file->block->next = blockIndex;
+         file->blockModified = 1;
+      }
+   }
+   if(file->block && file->blockModified)
+   {
+      // Write block back to flash or disk
+      MediaBlockWrite(file, file->blockIndex);
+      file->blockModified = 0;
+   }
+   if(blockIndex == BLOCK_EOF)
+   {
+      OS_MutexPost(mutexFilesys);
+      return;
+   }
+   file->blockIndex = blockIndex;
+   file->blockOffset = 0;
+   MediaBlockRead(file, blockIndex);
+   if(blockIndexSave == BLOCK_MALLOC)
+   {
+      memset(file->block, 0xff, file->fileEntry.blockSize);
+      file->blockModified = 1;
+   }
+   OS_MutexPost(mutexFilesys);
+}
+
+
+int OS_fread(void *buffer, int size, int count, OS_FILE *file)
+{
+   int items, bytes;
+   uint8 *buf = (uint8*)buffer;
+
+   for(items = 0; items < count; ++items)
+   {
+      for(bytes = 0; bytes < size; ++bytes)
+      {
+         if(file->fileOffset >= file->fileEntry.length && 
+            file->fileEntry.isDirectory == 0)
+            return items;
+         if(file->blockOffset >= file->fileEntry.blockSize - sizeof(uint32))
+         {
+            if(file->block->next == BLOCK_EOF)
+               return items;
+            BlockRead(file, file->block->next);
+         }
+         *buf++ = file->block->data[file->blockOffset++];
+         ++file->fileOffset;
+      }
+   }
+   return items;
+}
+
+
+int OS_fwrite(void *buffer, int size, int count, OS_FILE *file)
+{
+   int items, bytes;
+   uint8 *buf = (uint8*)buffer;
+
+   OS_MutexPend(mutexFilesys);
+   file->blockModified = 1;
+   for(items = 0; items < count; ++items)
+   {
+      for(bytes = 0; bytes < size; ++bytes)
+      {
+         if(file->blockOffset >= file->fileEntry.blockSize - sizeof(uint32))
+         {
+            if(file->block->next == BLOCK_EOF)
+               file->block->next = BLOCK_MALLOC;
+            BlockRead(file, file->block->next);
+            if(file->blockIndex == BLOCK_EOF)
+            {
+               count = 0;
+               --items;
+               break;
+            }
+            file->blockModified = 1;
+         }
+         file->block->data[file->blockOffset++] = *buf++;
+         ++file->fileOffset;
+      }
+   }
+   file->blockModified = 1;
+   file->fileModified = 1;
+   if(file->fileOffset > file->fileEntry.length)
+      file->fileEntry.length = file->fileOffset;
+   OS_MutexPost(mutexFilesys);
+   return items;
+}
+
+
+int OS_fseek(OS_FILE *file, int offset, int mode)
+{
+   if(mode == 1)      //SEEK_CUR
+      offset += file->fileOffset;
+   else if(mode == 2) //SEEK_END
+      offset += file->fileEntry.length;
+   file->fileOffset = offset;
+   BlockRead(file, file->fileEntry.blockIndex);
+   while(offset > (int)file->fileEntry.blockSize - (int)sizeof(uint32))
+   {
+      BlockRead(file, file->block->next);
+      offset -= file->fileEntry.blockSize - (int)sizeof(uint32);
+   }
+   file->blockOffset = offset;
+   return 0;
+}
+
+
+static int FileOpen(OS_FILE *file, char *name, OS_FileEntry_t *fileEntry)
+{
+   memset(file, 0, sizeof(OS_FILE));
+   if(fileEntry == NULL)
+   {
+      // Open root file
+      memcpy(&file->fileEntry, &rootFileEntry, sizeof(OS_FileEntry_t));
+   }
+   else if(fileEntry->valid == 1)
+   {
+      // Open existing file
+      memcpy(&file->fileEntry, fileEntry, sizeof(OS_FileEntry_t));
+   }
+   else
+   {
+      // Initialize new file
+      file->fileModified = 1;
+      file->blockModified = 1;
+      memset(&file->fileEntry, 0, sizeof(OS_FileEntry_t));
+      file->fileEntry.isDirectory = 0;
+      file->fileEntry.length = 0;
+      strncpy(file->fileEntry.name, name, FILE_NAME_SIZE-1);
+      file->fileEntry.blockIndex = 0;
+      file->fileEntry.valid = 1;
+      file->fileEntry.blockSize = fileEntry->blockSize;
+      file->fileEntry.mediaType = fileEntry->mediaType;
+   } 
+   BlockRead(file, file->fileEntry.blockIndex);    //Get first block
+   file->fileEntry.blockIndex = file->blockIndex;
+   file->fileOffset = 0;
+   if(file->blockIndex == BLOCK_EOF)
+      return -1;
+   return 0;
+}
+
+
+static int FileFind(OS_FILE *directory, char *name, OS_FileEntry_t *fileEntry)
+{
+   int count, rc = -1;
+   uint32 blockIndex, blockOffset;
+   uint32 blockIndexEmpty=BLOCK_EOF, blockOffsetEmpty=0;
+
+   // Loop through files in directory
+   for(;;)
+   {
+      blockIndex = directory->blockIndex;
+      blockOffset = directory->blockOffset;
+      count = OS_fread(fileEntry, sizeof(OS_FileEntry_t), 1, directory);
+      if(count == 0 || fileEntry->blockIndex == BLOCK_EOF)
+         break;
+      if(fileEntry->valid == 1 && strcmp(fileEntry->name, name) == 0)
+      {
+         rc = 0;  //Found the file in the directory
+         break;
+      }
+      if(fileEntry->valid != 1 && blockIndexEmpty == BLOCK_EOF)
+      {
+         blockIndexEmpty = blockIndex;
+         blockOffsetEmpty = blockOffset;
+      }
+   }
+   if(rc == 0 || directory->fileEntry.mediaType == FILE_MEDIA_FLASH || 
+      blockIndexEmpty == BLOCK_EOF)
+   {
+      // Backup to start of fileEntry or last entry in directory
+      if(directory->blockIndex != blockIndex)
+         BlockRead(directory, blockIndex);
+      directory->blockOffset = blockOffset;
+   }
+   else
+   {
+      // Backup to empty slot
+      if(directory->blockIndex != blockIndexEmpty)
+         BlockRead(directory, blockIndexEmpty);
+      directory->blockOffset = blockOffsetEmpty;
+   }
+   return rc;
+}
+
+
+static int FileFindRecursive(OS_FILE *directory, char *name, 
+                             OS_FileEntry_t *fileEntry, char *filename)
+{
+   int rc, length;
+
+   rc = FileOpen(directory, NULL, NULL);            //Open root directory
+   for(;;)
+   {
+      if(name[0] == '/')
+         ++name;
+      for(length = 0; length < FILE_NAME_SIZE; ++length)
+      {
+         if(name[length] == 0 || name[length] == '/')
+            break;
+         filename[length] = name[length];
+      }
+      filename[length] = 0;
+      rc = FileFind(directory, filename, fileEntry);  //Find file
+      if(rc)
+      {
+         // File not found
+         fileEntry->mediaType = directory->fileEntry.mediaType;
+         fileEntry->blockSize = directory->fileEntry.blockSize;
+         fileEntry->valid = 0;
+         if(strstr(name, "/") == NULL)
+            return rc;
+         else
+            return -2;  //can't find parent directory
+      }
+      name += length;
+      if(name[0])
+         rc = FileOpen(directory, filename, fileEntry);  //Open subdir
+      else
+         break;
+   }
+   return rc;
+}
+
+
+OS_FILE *OS_fopen(char *name, char *mode)
+{
+   OS_FILE *file;
+   OS_FileEntry_t fileEntry;
+   OS_FILE dir;
+   char filename[FILE_NAME_SIZE];  //Name without directories
+   int rc;
+
+   if(rootFileEntry.blockIndex == 0)
+   {
+      // Mount file system
+      mutexFilesys = OS_MutexCreate("filesys");
+      memset(&dir, 0, sizeof(OS_FILE));
+      dir.fileEntry.blockSize = BLOCK_SIZE;
+      //dir.fileEntry.mediaType = FILE_MEDIA_FLASH;  //Test flash
+      BlockRead(&dir, BLOCK_MALLOC);
+      strcpy(rootFileEntry.name, "/");
+      rootFileEntry.mediaType = dir.fileEntry.mediaType;
+      rootFileEntry.blockIndex = dir.blockIndex;
+      rootFileEntry.blockSize = dir.fileEntry.blockSize;
+      rootFileEntry.isDirectory = 1;
+      BlockRead(&dir, BLOCK_EOF);    //Flush data
+#ifdef INCLUDE_FLASH
+      file = OS_fopen("flash", "w+");
+      if(file == NULL)
+         return NULL;
+      file->fileEntry.isDirectory = 1;
+      file->fileEntry.mediaType = FILE_MEDIA_FLASH;
+      file->fileEntry.blockSize = FLASH_BLOCK_SIZE;
+      file->blockLocal = file->block;
+      file->block = NULL;
+      rc = MediaBlockInit();
+      if(rc == 1)
+         BlockRead(file, BLOCK_MALLOC);
+      else
+         BlockRead(file, FLASH_START);
+      file->fileEntry.blockIndex = file->blockIndex;
+      OS_fclose(file);
+#endif
+   }
+
+   file = (OS_FILE*)malloc(sizeof(OS_FILE));
+   if(file == NULL)
+      return NULL;
+   OS_MutexPend(mutexFilesys);
+   if(name[0] == 0 || strcmp(name, "/") == 0)
+   {
+      FileOpen(file, NULL, NULL);
+      OS_MutexPost(mutexFilesys);
+      return file;
+   }
+   if(mode[0] == 'w')
+   {
+      //Don't over write a directory
+      fileEntry.isDirectory = 0;
+      rc = FileFindRecursive(&dir, name, &fileEntry, filename);
+      if(dir.blockLocal)
+         free(dir.blockLocal);
+      if(rc == 0)
+      {
+         if(fileEntry.isDirectory)
+         {
+            free(file);
+            return NULL;
+         }
+         OS_fdelete(name);
+      }
+   }
+   rc = FileFindRecursive(&dir, name, &fileEntry, filename);
+   if(dir.blockLocal)
+      free(dir.blockLocal);
+   if(rc == -2 || (rc && mode[0] == 'r'))
+   {
+      free(file);
+      OS_MutexPost(mutexFilesys);
+      return NULL;
+   }
+   if(rc)
+      fileEntry.valid = 0;
+   rc = FileOpen(file, filename, &fileEntry);  //Open file
+   file->fullname[0] = 0;
+   strncat(file->fullname, name, FULL_NAME_SIZE);\r
+   OS_MutexPost(mutexFilesys);
+   if(mode[0] == 'a')\r
+      OS_fseek(file, 0, 2);  //goto end of file\r
+   return file;
+}
+
+
+void OS_fclose(OS_FILE *file)
+{
+   OS_FileEntry_t fileEntry;
+   OS_FILE dir;
+   char filename[FILE_NAME_SIZE];
+   int rc;
+
+   if(file->fileModified)
+   {
+      // Write file->fileEntry into parent directory
+      OS_MutexPend(mutexFilesys);
+      BlockRead(file, BLOCK_EOF);
+      rc = FileFindRecursive(&dir, file->fullname, &fileEntry, filename);
+      if(file->fileEntry.mediaType == FILE_MEDIA_FLASH && rc == 0)
+      {
+         // Invalidate old entry and add new entry at the end
+         fileEntry.valid = 0;
+         OS_fwrite(&fileEntry, sizeof(OS_FileEntry_t), 1, &dir);
+         FileFind(&dir, "endoffile", &fileEntry);
+      }
+      OS_fwrite(&file->fileEntry, sizeof(OS_FileEntry_t), 1, &dir);
+      BlockRead(&dir, BLOCK_EOF);  //flush data
+      if(dir.blockLocal)
+         free(dir.blockLocal);
+      OS_MutexPost(mutexFilesys);
+   }
+   if(file->blockLocal)
+      free(file->blockLocal);
+   free(file);
+}
+
+
+int OS_fmkdir(char *name)
+{
+   OS_FILE *file;
+   file = OS_fopen(name, "w+");
+   if(file == NULL)
+      return -1;
+   file->fileEntry.isDirectory = 1;
+   OS_fclose(file);
+   return 0;
+}
+
+
+void OS_fdelete(char *name)
+{
+   OS_FILE dir, file;
+   OS_FileEntry_t fileEntry;
+   int rc;
+   uint32 blockIndex;
+   char filename[FILE_NAME_SIZE];  //Name without directories
+
+   OS_MutexPend(mutexFilesys);
+   rc = FileFindRecursive(&dir, name, &fileEntry, filename);
+   if(rc == 0)
+   {
+      FileOpen(&file, NULL, &fileEntry);
+      for(blockIndex = file.blockIndex; file.block->next != BLOCK_EOF; blockIndex = file.blockIndex)
+      {
+         BlockRead(&file, file.block->next);
+         MediaBlockFree(&file, blockIndex);
+      }
+      MediaBlockFree(&file, blockIndex);
+      fileEntry.valid = 0;
+      OS_fwrite((char*)&fileEntry, sizeof(OS_FileEntry_t), 1, &dir);
+      BlockRead(&dir, BLOCK_EOF);
+      if(file.blockLocal)
+         free(file.blockLocal);
+   }
+   if(dir.blockLocal)
+      free(dir.blockLocal);
+   OS_MutexPost(mutexFilesys);
+}
+
+
+int OS_flength(char *entry)
+{
+   OS_FileEntry_t *entry2=(OS_FileEntry_t*)entry;
+   return entry2->length;
+}
+
+
+int OS_fdir(OS_FILE *dir, char name[64])
+{
+   OS_FileEntry_t *fileEntry = (OS_FileEntry_t*)name;
+   int count;
+   for(;;)
+   {
+      count = OS_fread(fileEntry, sizeof(OS_FileEntry_t), 1, dir);
+      if(count == 0 || fileEntry->blockIndex == BLOCK_EOF)
+         return -1;
+      if(fileEntry->valid == 1)
+         break;
+   }
+   return 0;
+}
+
+/*************************************************/
+#define TEST_FILES
+#ifdef TEST_FILES
+int DirRecursive(char *name)
+{
+   OS_FileEntry_t fileEntry;
+   OS_FILE *dir;
+   char fullname[FULL_NAME_SIZE];
+   int rc;
+
+   dir = OS_fopen(name, "r");
+   for(;;)
+   {
+      rc = OS_fdir(dir, (char*)&fileEntry);
+      if(rc)
+         break;
+      printf("%s %d\n", fileEntry.name, fileEntry.length);
+      if(fileEntry.isDirectory)
+      {
+         if(strcmp(name, "/") == 0)
+            sprintf(fullname, "/%s", fileEntry.name);
+         else
+            sprintf(fullname, "%s/%s", name, fileEntry.name);
+         DirRecursive(fullname);
+      }
+   }
+   OS_fclose(dir);
+   return 0;
+}
+
+int OS_ftest(void)
+{
+   OS_FILE *file;
+   char *buf;
+   int count;
+   int i, j;
+
+   buf = (char*)malloc(5000);
+   memset(buf, 0, 5000);
+   for(count = 0; count < 4000; ++count)
+      buf[count] = (char)('A' + (count % 26));
+   OS_fmkdir("dir");
+   OS_fmkdir("/dir/subdir");
+   file = OS_fopen("/dir/subdir/test.txt", "w");
+   count = OS_fwrite(buf, 1, 4000, file);
+   OS_fclose(file);
+   memset(buf, 0, 5000);
+   file = OS_fopen("/dir/subdir/test.txt", "r");
+   count = OS_fread(buf, 1, 5000, file);
+   OS_fclose(file);
+   printf("(%s)\n", buf);
+
+   DirRecursive("/");
+
+   for(i = 0; i < 5; ++i)
+   {
+      sprintf(buf, "/dir%d", i);
+      OS_fmkdir(buf);
+      for(j = 0; j < 5; ++j)
+      {
+         sprintf(buf, "/dir%d/file%d%d", i, i, j);
+         file = OS_fopen(buf, "w");
+         sprintf(buf, "i=%d j=%d", i, j);
+         OS_fwrite(buf, 1, 8, file);
+         OS_fclose(file);
+      }
+   }
+
+   OS_fdelete("/dir1/file12");
+   DirRecursive("/");
+   file = OS_fopen("/baddir/myfile.txt", "w");
+   if(file)
+      printf("ERROR!\n");
+
+   for(i = 0; i < 5; ++i)
+   {
+      for(j = 0; j < 5; ++j)
+      {
+         sprintf(buf, "/dir%d/file%d%d", i, i, j);
+         file = OS_fopen(buf, "r");
+         if(file)
+         {
+            count = OS_fread(buf, 1, 500, file);
+            printf("i=%d j=%d count=%d (%s)\n", i, j, count, buf);
+            OS_fclose(file);
+         }
+      }
+   }
+
+   OS_fdelete("/dir/subdir/test.txt");
+   OS_fdelete("/dir/subdir");
+   OS_fdelete("/dir");
+   for(i = 0; i < 5; ++i)
+   {
+      for(j = 0; j < 5; ++j)
+      {
+         sprintf(buf, "/dir%d/file%d%d", i, i, j);
+         OS_fdelete(buf);
+      }
+      sprintf(buf, "/dir%d", i);
+      OS_fdelete(buf);
+   }
+
+   DirRecursive("/");
+
+   free(buf);
+   return 0;
+}
+#endif  //TEST_FILES
diff --git a/kernel/flash.c b/kernel/flash.c
new file mode 100644 (file)
index 0000000..57f0a83
--- /dev/null
@@ -0,0 +1,52 @@
+/*--------------------------------------------------------------------
+ * TITLE: Plasma Flash
+ * AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
+ * DATE CREATED: 12/17/05
+ * FILENAME: plasma.h
+ * PROJECT: Plasma CPU core
+ * COPYRIGHT: Software placed into the public domain by the author.
+ *    Software 'as is' without warranty.  Author liable for nothing.
+ * DESCRIPTION:
+ *    Plasma flash controller
+ *    Only the lower 16-bits of each 32-bit word are connected --
+ *    this changes the address mapping to the flash.
+ *    ByteOffset and bytes must be a multiple of two.
+ *--------------------------------------------------------------------*/
+#include "plasma.h"
+#include "rtos.h"
+
+
+void FlashRead(uint16 *dst, uint32 byteOffset, int bytes)
+{
+   volatile uint32 *ptr=(uint32*)(FLASH_BASE + (byteOffset << 1));
+   *ptr = 0xff;                   //read mode
+   while(bytes > 0)
+   {
+      *dst++ = (uint16)*ptr++;
+      bytes -= 2;
+   }
+}
+
+
+void FlashWrite(uint16 *src, uint32 byteOffset, int bytes)
+{
+   volatile uint32 *ptr=(uint32*)(FLASH_BASE + (byteOffset << 1));
+   while(bytes > 0)
+   {
+      *ptr = 0x40;                //write mode
+      *ptr++ = *src++;            //write data
+      while((*ptr & 0x80) == 0)   //check status
+         ;
+      bytes -= 2;
+   }
+}
+
+
+void FlashErase(uint32 byteOffset)
+{
+   volatile uint32 *ptr=(uint32*)(FLASH_BASE + (byteOffset << 1));
+   *ptr = 0x20;                   //erase block
+   *ptr = 0xd0;                   //confirm
+   while((*ptr & 0x80) == 0)      //check status
+      ;
+}
diff --git a/kernel/http.c b/kernel/http.c
new file mode 100644 (file)
index 0000000..e1462fa
--- /dev/null
@@ -0,0 +1,230 @@
+/*--------------------------------------------------------------------
+ * TITLE: Plasma TCP/IP HTTP Server
+ * AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
+ * DATE CREATED: 4/22/06
+ * FILENAME: http.c
+ * PROJECT: Plasma CPU core
+ * COPYRIGHT: Software placed into the public domain by the author.
+ *    Software 'as is' without warranty.  Author liable for nothing.
+ * DESCRIPTION:
+ *    Plasma TCP/IP HTTP Server
+ *--------------------------------------------------------------------*/
+#ifdef WIN32
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#define _LIBC
+#endif
+#include "rtos.h"
+#include "tcpip.h"
+#ifdef WIN32
+#define UartPrintf printf
+#define OS_MQueueCreate(A,B,C) 0
+#define OS_MQueueGet(A,B,C) 0
+#define OS_ThreadCreate(A,B,C,D,E) 0
+#endif
+
+static const char pageGif[]=
+{
+   "HTTP/1.0 200 OK\r\n"
+   "Content-Length: %d\r\n"
+   "Content-Type: binary/gif\r\n\r\n"
+};
+static const char pageGif2[]=
+{
+   "HTTP/1.0 200 OK\r\n"
+   "Content-Type: binary/gif\r\n\r\n"
+};
+static const char pageBinary[]=
+{
+   "HTTP/1.0 200 OK\r\n"
+   "Content-Length: %d\r\n"
+   "Content-Type: binary/binary\r\n\r\n"
+};
+static const char pageBinary2[]=
+{
+   "HTTP/1.0 200 OK\r\n"
+   "Content-Type: binary/binary\r\n\r\n"
+};
+static const char pageHtml[]={
+   "HTTP/1.0 200 OK\r\n"
+   "Content-Length: %d\r\n"
+   "Content-Type: text/html\r\n\r\n"
+};
+static const char pageHtml2[]={
+   "HTTP/1.0 200 OK\r\n"
+   "Content-Type: text/html\r\n\r\n"
+};
+static const char pageText[]={
+   "HTTP/1.0 200 OK\r\n"
+   "Content-Length: %d\r\n"
+   "Content-Type: text/text\r\n\r\n"
+};
+static const char pageEmpty[]=
+{
+   "HTTP/1.0 404 OK\r\n"
+   "Content-Length: 0\r\n"
+   "Content-Type: text/html\r\n\r\n"
+};
+
+static const PageEntry_t *HtmlPages;
+static int HtmlFiles;
+
+
+void HttpServer(IPSocket *socket)
+{
+   uint8 buf[600];
+   char filename[80];
+   int bytes, i, length, len, needFooter;
+   char *name=NULL, *page=NULL;
+   const char *header, *header2;
+
+   if(socket == NULL)
+      return;
+   if(socket->funcPtr != HttpServer && socket->funcPtr)
+   {
+      socket->funcPtr(socket);
+      return;
+   }
+   bytes = IPRead(socket, buf, sizeof(buf)-1);
+   if(bytes)
+   {
+      buf[bytes] = 0;
+      if(strncmp((char*)buf, "GET /", 5) == 0)
+      {
+         for(i = 0; ; ++i)
+         {
+            length = HtmlPages[i].length;
+            if(length == -1)
+               break;
+            name = (char*)HtmlPages[i].name;
+            page = (char*)HtmlPages[i].page;
+            len = (int)strlen(name);
+            if(strncmp((char*)buf+4, name, len) == 0)
+               break;
+         }
+#if defined(WIN32) || defined(INCLUDE_FILESYS)
+         if(length == HTML_LENGTH_LIST_END && HtmlFiles)
+         {
+            FILE *file;
+            char *ptr;
+
+            name = (char*)buf + 5;
+            ptr = strstr(name, " ");
+            if(ptr)
+               *ptr = 0;
+            strcpy(filename, "/web/");
+            strncat(filename, name, 60);
+            file = fopen(filename, "rb");
+            if(file == NULL)
+            {
+               strcpy(filename, "/flash/web/");
+               strncat(filename, name, 60);
+               file = fopen(filename, "rb");
+            }
+            if(file)
+            {
+               if(strstr(name, ".htm"))
+                  IPWrite(socket, (uint8*)pageHtml2, sizeof(pageHtml2)-1);
+               else if(strstr(name, ".gif"))
+                  IPWrite(socket, (uint8*)pageGif2, sizeof(pageGif2)-1);
+               else
+                  IPWrite(socket, (uint8*)pageBinary2, sizeof(pageBinary2)-1);
+               for(;;)
+               {
+                  len = fread(buf, 1, sizeof(buf), file);
+                  if(len == 0)
+                     break;
+                  IPWrite(socket, (uint8*)buf, len);
+               }
+               fclose(file);
+               IPWriteFlush(socket);
+               IPClose(socket);
+               return;
+            }
+         }
+#endif
+         if(length != HTML_LENGTH_LIST_END)
+         {
+            if(length == HTML_LENGTH_CALLBACK)
+            {
+               IPFuncPtr funcPtr = (IPFuncPtr)(uint32)page;
+               funcPtr(socket, buf, bytes);
+               return;
+            }
+            if(length == 0)
+               length = (int)strlen(page);
+            needFooter = 0;
+            header2 = NULL;
+            if(strstr(name, ".html"))
+               header = pageHtml;
+            else if(strstr(name, ".htm") || strcmp(name, "/ ") == 0)
+            {
+               header = pageHtml;
+               header2 = HtmlPages[0].page;
+               needFooter = 1;
+            }
+            else if(strstr(HtmlPages[i].name, ".gif"))
+               header = pageGif;
+            else
+               header = pageBinary;
+            len = 0;
+            if(header2)
+               len += (int)strlen(header2) + (int)strlen(HtmlPages[1].page);
+            sprintf((char*)buf, header, length + len);
+            IPWrite(socket, buf, (int)strlen((char*)buf));
+            if(header2)
+               IPWrite(socket, (uint8*)header2, (int)strlen(header2));
+            IPWrite(socket, (uint8*)page, length);
+            if(needFooter)
+               IPWrite(socket, (uint8*)HtmlPages[1].page, (int)strlen(HtmlPages[1].page));
+         }
+         else
+         {
+            IPWrite(socket, (uint8*)pageEmpty, (int)strlen(pageEmpty));
+         }
+         IPClose(socket);
+      }
+   }
+}
+
+
+void HttpInit(const PageEntry_t *Pages, int UseFiles)
+{
+   HtmlPages = Pages;
+   HtmlFiles = UseFiles;
+   IPOpen(IP_MODE_TCP, 0, 80, HttpServer);
+   IPOpen(IP_MODE_TCP, 0, 8080, HttpServer);
+}
+
+
+#ifdef EXAMPLE_HTML
+//Example test code
+static void MyProg(IPSocket *socket, char *request, int bytes)
+{
+   char *text="HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n"
+              "<html><body>Hello World!</body></html>";
+   (void)request; (void)bytes;
+   IPWrite(socket, (uint8*)text, (int)strlen(text));
+   IPClose(socket);
+}
+static const PageEntry_t pageEntry[]=
+{  //name, length, htmlText
+   {"/Header", 0, "<HTML><HEAD><TITLE>Plasma CPU</TITLE></HEAD>\n<BODY>"},
+   {"/Footer", 0, "</BODY></HTML>"},
+   {"/ ", 0, "<h2>Home Page</h2>Welcome!  <a href='/other.htm'>Other</a>"
+             " <a href='/cgi/myprog'>myprog</a>"},
+   {"/other.htm ", 0, "<h2>Other</h2>Other."},
+   //{"/binary/plasma.gif ", 1945, PlasmaGif},
+   {"/cgi/myprog", HTML_LENGTH_CALLBACK, (char*)MyProg},
+   {"", HTML_LENGTH_LIST_END, NULL}
+};
+void HtmlInit(int UseFiles)
+{
+   (void)UseFiles;
+   HttpInit(pageEntry, 1);
+}
+#endif
+
+
diff --git a/kernel/libc.c b/kernel/libc.c
new file mode 100644 (file)
index 0000000..23c0c98
--- /dev/null
@@ -0,0 +1,658 @@
+/*--------------------------------------------------------------------
+ * TITLE: ANSI C Library
+ * AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
+ * DATE CREATED: 12/17/05
+ * FILENAME: libc.c
+ * PROJECT: Plasma CPU core
+ * COPYRIGHT: Software placed into the public domain by the author.
+ *    Software 'as is' without warranty.  Author liable for nothing.
+ * DESCRIPTION:
+ *    Subset of the ANSI C library
+ *--------------------------------------------------------------------*/
+#define NO_ELLIPSIS
+#include "rtos.h"
+
+
+char *strcpy(char *dst, const char *src)
+{
+   char *dstSave=dst;
+   int c;
+   do
+   {
+      c = *dst++ = *src++;
+   } while(c);
+   return dstSave;
+}
+
+
+char *strncpy(char *dst, const char *src, int count)
+{
+   int c=1;
+   char *dstSave=dst;
+   while(count-- > 0 && c)
+      c = *dst++ = *src++;
+   *dst = 0;
+   return dstSave;
+}
+
+
+char *strcat(char *dst, const char *src)
+{
+   int c;
+   char *dstSave=dst;
+   while(*dst)
+      ++dst;
+   do
+   {
+      c = *dst++ = *src++;
+   } while(c);
+   return dstSave;
+}
+
+
+char *strncat(char *dst, const char *src, int count)
+{
+   int c=1;
+   char *dstSave=dst;
+   while(*dst && --count > 0)
+      ++dst;
+   while(--count > 0 && c)
+      c = *dst++ = *src++;
+   *dst = 0;
+   return dstSave;
+}
+
+
+int strcmp(const char *string1, const char *string2)
+{
+   int diff, c;
+   for(;;)
+   {
+      diff = *string1++ - (c = *string2++);
+      if(diff)
+         return diff;
+      if(c == 0)
+         return 0;
+   }
+}
+
+
+int strncmp(const char *string1, const char *string2, int count)
+{
+   int diff, c;
+   while(count-- > 0)
+   {
+      diff = *string1++ - (c = *string2++);
+      if(diff)
+         return diff;
+      if(c == 0)
+         return 0;
+   }
+   return 0;
+}
+
+
+char *strstr(const char *string, const char *find)
+{
+   int i;
+   for(;;)
+   {
+      for(i = 0; string[i] == find[i] && find[i]; ++i) ;
+      if(find[i] == 0)
+         return (char*)string;
+      if(*string++ == 0)
+         return NULL;
+   }
+}
+
+
+int strlen(const char *string)
+{
+   const char *base=string;
+   while(*string++) ;
+   return string - base - 1;
+}
+
+
+void *memcpy(void *dst, const void *src, unsigned long bytes)
+{
+   if(((uint32)dst | (uint32)src | bytes) & 3)
+   {
+      uint8 *Dst = (uint8*)dst, *Src = (uint8*)src;
+      while((int)bytes-- > 0)
+         *Dst++ = *Src++;
+   }
+   else
+   {
+      uint32 *Dst32 = (uint32*)dst, *Src32 = (uint32*)src;
+      bytes >>= 2;
+      while((int)bytes-- > 0)
+         *Dst32++ = *Src32++;
+   }
+   return dst;
+}
+
+
+void *memmove(void *dst, const void *src, unsigned long bytes)
+{
+   uint8 *Dst = (uint8*)dst;
+   uint8 *Src = (uint8*)src;
+   if(Dst < Src)
+   {
+      while((int)bytes-- > 0)
+         *Dst++ = *Src++;
+   }
+   else
+   {
+      Dst += bytes;
+      Src += bytes;
+      while((int)bytes-- > 0)
+         *--Dst = *--Src;
+   }
+   return dst;
+}
+
+
+int memcmp(const void *cs, const void *ct, unsigned long bytes)
+{
+   uint8 *Dst = (uint8*)cs;
+   uint8 *Src = (uint8*)ct;
+   int diff;
+   while((int)bytes-- > 0)
+   {
+      diff = *Dst++ - *Src++;
+      if(diff)
+         return diff;
+   }
+   return 0;
+}
+
+
+void *memset(void *dst, int c, unsigned long bytes)
+{
+   uint8 *Dst = (uint8*)dst;
+   while((int)bytes-- > 0)
+      *Dst++ = (uint8)c;
+   return dst;
+}
+
+
+int abs(int n)
+{
+   return n>=0 ? n : -n;
+}
+
+
+static uint32 Rand1=0x1f2bcda3;
+int rand(void)
+{
+   Rand1 = 1664525 * Rand1 + 1013904223;  //from D.E. Knuth and H.W. Lewis
+   return Rand1;
+}
+
+
+void srand(unsigned int seed)
+{
+   Rand1 = seed;
+}
+
+
+long strtol(const char *s, char **end, int base)
+{
+   int i;
+   unsigned long ch, value=0, neg=0;
+
+   if(s[0] == '-')
+   {
+      neg = 1;
+      ++s;
+   }
+   if(s[0] == '0' && s[1] == 'x')
+   {
+      base = 16;
+      s += 2;
+   }
+   for(i = 0; i <= 8; ++i)
+   {
+      ch = *s++;
+      if('0' <= ch && ch <= '9')
+         ch -= '0';
+      else if('A' <= ch && ch <= 'Z')
+         ch = ch - 'A' + 10;
+      else if('a' <= ch && ch <= 'z')
+         ch = ch - 'a' + 10;
+      else
+         break;
+      value = value * base + ch;
+   }
+   if(end)
+      *end = (char*)s - 1;
+   if(neg)
+      value = -(int)value;
+   return value;
+}
+
+
+int atoi(const char *s)
+{
+   return strtol(s, NULL, 10);
+}
+
+
+char *itoa(int num, char *dst, int base)
+{
+   int digit, negate=0, place;
+   char c, text[20];
+
+   if(base == 10 && num < 0)
+   {
+      num = -num;
+      negate = 1;
+   }
+   text[16] = 0;
+   for(place = 15; place >= 0; --place)
+   {
+      digit = (unsigned int)num % (unsigned int)base;
+      if(num == 0 && place < 15 && base == 10 && negate)
+      {
+         c = '-';
+         negate = 0;
+      }
+      else if(digit < 10)
+         c = (char)('0' + digit);
+      else
+         c = (char)('a' + digit - 10);
+      text[place] = c;
+      num = (unsigned int)num / (unsigned int)base;
+      if(num == 0 && negate == 0)
+         break;
+   }
+   strcpy(dst, text + place);
+   return dst;
+}
+
+
+int sprintf(char *s, const char *format, 
+            int arg0, int arg1, int arg2, int arg3,
+            int arg4, int arg5, int arg6, int arg7)
+{
+   int argv[8];
+   int argc=0, width, length;
+   char f, text[20], fill;
+
+   argv[0] = arg0; argv[1] = arg1; argv[2] = arg2; argv[3] = arg3;
+   argv[4] = arg4; argv[5] = arg5; argv[6] = arg6; argv[7] = arg7;
+
+   for(;;)
+   {
+      f = *format++;
+      if(f == 0)
+         return argc;
+      else if(f == '%')
+      {
+         width = 0;
+         fill = ' ';
+         f = *format++;
+         while('0' <= f && f <= '9')
+         {
+            width = width * 10 + f - '0';
+            f = *format++;
+         }
+         if(f == '.')
+         {
+            fill = '0';
+            f = *format++;
+         }
+         if(f == 0)
+            return argc;
+
+         if(f == 'd')
+         {
+            memset(s, fill, width);
+            itoa(argv[argc++], text, 10);
+            length = (int)strlen(text);
+            if(width < length)
+               width = length;
+            strcpy(s + width - length, text);
+         }
+         else if(f == 'x' || f == 'f')
+         {
+            memset(s, '0', width);
+            itoa(argv[argc++], text, 16);
+            length = (int)strlen(text);
+            if(width < length)
+               width = length;
+            strcpy(s + width - length, text);
+         }
+         else if(f == 'c')
+         {
+            *s++ = (char)argv[argc++];
+            *s = 0;
+         }
+         else if(f == 's')
+         {
+            length = strlen((char*)argv[argc]);
+            if(width > length)
+            {
+               memset(s, ' ', width - length);
+               s += width - length;
+            }
+            strcpy(s, (char*)argv[argc++]);
+         }
+         s += strlen(s);
+      }
+      else
+      {
+         if(f == '\n')
+            *s++ = '\r';
+         *s++ = f;
+         if(f == '\r' && *format == '\n')
+            *s++ = *format++;
+      }
+      *s = 0;
+   }
+}
+
+
+int sscanf(const char *s, const char *format,
+           int arg0, int arg1, int arg2, int arg3,
+           int arg4, int arg5, int arg6, int arg7)
+{
+   int argv[8];
+   int argc=0;
+   char f, *ptr;
+
+   argv[0] = arg0; argv[1] = arg1; argv[2] = arg2; argv[3] = arg3;
+   argv[4] = arg4; argv[5] = arg5; argv[6] = arg6; argv[7] = arg7;
+
+   for(;;)
+   {
+      if(*s == 0)
+         return argc;
+      f = *format++;
+      if(f == 0)
+         return argc;
+      else if(f == '%')
+      {
+         while(isspace(*s))
+            ++s;
+         f = *format++;
+         if(f == 0)
+            return argc;
+         if(f == 'd')
+            *(int*)argv[argc++] = strtol(s, (char**)&s, 10);
+         else if(f == 'x')
+            *(int*)argv[argc++] = strtol(s, (char**)&s, 16);
+         else if(f == 'c')
+            *(char*)argv[argc++] = *s++;
+         else if(f == 's')
+         {
+            ptr = (char*)argv[argc++];
+            while(!isspace(*s))
+               *ptr++ = *s++;
+            *ptr = 0;
+         }
+      }
+      else 
+      {
+         while(*s && *s != f)
+            ++s;
+         if(*s)
+            ++s;
+      }
+   }
+}
+
+
+#ifdef INCLUDE_DUMP
+/*********************** dump ***********************/
+void dump(const unsigned char *data, int length)
+{
+   int i, index=0, value;
+   char string[80];
+   memset(string, 0, sizeof(string));
+   for(i = 0; i < length; ++i)
+   {
+      if((i & 15) == 0)
+      {
+         if(strlen(string))
+            printf("%s\n", string);
+         printf("%4x ", i);
+         memset(string, 0, sizeof(string));
+         index = 0;
+      }
+      value = data[i];
+      printf("%2x ", value);
+      if(isprint(value))
+         string[index] = (char)value;
+      else
+         string[index] = '.';
+      ++index;
+   }
+   for(; index < 16; ++index)
+      printf("   ");
+   printf("%s\n", string);
+}
+#endif //INCLUDE_DUMP
+
+
+#ifdef INCLUDE_QSORT
+/*********************** qsort ***********************/
+static void QsortSwap(char *base, long left, long right, long size)
+{
+   int temp, i;
+   char *ptrLeft, *ptrRight;
+   ptrLeft = base + left * size;
+   ptrRight = base + right * size;
+   for(i = 0; i < size; ++i)
+   {
+      temp = ptrLeft[i];
+      ptrLeft[i] = ptrRight[i];
+      ptrRight[i] = (char)temp;
+   }
+}
+
+
+//Modified from K&R
+static void qsort2(void *base, long left, long right, long size,
+      int (*cmp)(const void *,const void *))
+{
+   int i, last;
+   char *base2=(char*)base, *pivot;
+   if(left >= right) 
+      return;
+   QsortSwap(base2, left, (left + right)/2, size);
+   last = left;
+   pivot = &base2[left*size];
+   for(i = left + 1; i <= right; ++i) 
+   {
+      if(cmp(&base2[i*size], pivot) < 0) 
+         QsortSwap(base2, ++last, i, size);
+   }
+   QsortSwap(base2, left, last, size);
+   qsort2(base, left, last-1, size, cmp);
+   qsort2(base, last+1, right, size, cmp);
+}
+
+
+void qsort(void *base, 
+           long n, 
+           long size, 
+           int (*cmp)(const void *,const void *))
+{ 
+   qsort2(base, 0, n-1, size, cmp); 
+}
+
+
+void *bsearch(const void *key,
+              const void *base,
+              long n,
+              long size,
+              int (*cmp)(const void *,const void *))
+{
+   long cond, low=0, high=n-1, mid;
+   char *base2=(char*)base;
+   while(low <= high) 
+   {
+      mid = (low + high)/2;
+      cond = cmp(key, &base2[mid*size]);
+      if(cond < 0) 
+         high = mid - 1;
+      else if(cond > 0) 
+         low = mid + 1;
+      else 
+         return &base2[mid * size];
+   }
+   return NULL;
+}
+#endif //INCLUDE_QSORT
+
+
+#ifdef INCLUDE_TIMELIB
+/************************* time.h ***********************/
+#define SEC_PER_YEAR (365L*24*60*60)
+#define SEC_PER_DAY (24L*60*60)
+//typedef unsigned long time_t;  //start at 1/1/80
+//struct tm {
+//   int tm_sec;      //(0,59)
+//   int tm_min;      //(0,59)
+//   int tm_hour;     //(0,23)
+//   int tm_mday;     //(1,31)
+//   int tm_mon;      //(0,11)
+//   int tm_year;     //(0,n) from 1900
+//   int tm_wday;     //(0,6)     calculated
+//   int tm_yday;     //(0,365)   calculated
+//   int tm_isdst;    //hour adjusted for day light savings
+//};
+static const unsigned short DaysUntilMonth[]=
+   {0,31,59,90,120,151,181,212,243,273,304,334,365}; 
+static const unsigned short DaysInMonth[]=
+   {31,28,31,30,31,30,31,31,30,31,30,31};
+static time_t DstTimeIn, DstTimeOut;
+
+
+/* Leap year if divisible by 4.  Centenary years should only be 
+   leap-years if they were divisible by 400. */
+static int IsLeapYear(int year)
+{
+   return(((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0));
+}
+
+time_t mktime(struct tm *tp)
+{
+   time_t seconds;
+   unsigned long days, y, year;
+
+   days = tp->tm_mday - 1 + DaysUntilMonth[tp->tm_mon] + 
+      365 * (tp->tm_year - 80);
+   seconds = (unsigned long)tp->tm_sec + 60L * (tp->tm_min + 
+      60L * (tp->tm_hour + 24L * days));
+   if(tp->tm_isdst)
+      seconds -= 60 * 60;
+   year = 1900 + tp->tm_year - (tp->tm_mon < 2);
+   for(y = 1980; y <= year; y += 4)
+   {
+      if(y % 100 != 0 || y % 400 == 0)
+         seconds += SEC_PER_DAY;
+   }
+   return seconds;
+}
+
+
+void gmtime_r(const time_t *tp, struct tm *out)
+{
+   time_t seconds, delta, secondsIn=*tp;
+   int isLeapYear; 
+   unsigned long year, month;
+
+   out->tm_isdst = 0;
+   if(DstTimeIn <= secondsIn && secondsIn < DstTimeOut)
+   {
+      secondsIn += 60 * 60;
+      out->tm_isdst = 1;
+   }
+   seconds = secondsIn;
+   for(year = 0; ; ++year) 
+   {
+      delta = SEC_PER_YEAR + IsLeapYear(1980 + year) * SEC_PER_DAY;
+      if(seconds >= delta) 
+         seconds -= delta;
+      else 
+         break;
+   }
+   out->tm_year = year + 80;
+   isLeapYear = IsLeapYear(1980 + year);
+   for(month = 0; ; ++month) 
+   {
+      delta = SEC_PER_DAY * (DaysInMonth[month] + (isLeapYear && (month == 1)));
+      if(seconds >= delta) 
+         seconds -= delta;
+      else 
+         break;
+   }
+   out->tm_mon = month;
+   out->tm_mday = seconds / SEC_PER_DAY;
+   out->tm_yday = DaysUntilMonth[month] + out->tm_mday;
+   seconds -= out->tm_mday * SEC_PER_DAY;
+   ++out->tm_mday;
+   out->tm_hour = seconds / (60 * 60);
+   seconds -= out->tm_hour * (60 * 60);
+   out->tm_min = seconds / 60;
+   seconds -= out->tm_min * 60;
+   out->tm_sec = seconds;
+   seconds = secondsIn % (SEC_PER_DAY * 7);
+   out->tm_wday = (seconds / SEC_PER_DAY + 2) % 7; /* 1/1/80 is a Tue */
+   //printf("%4.d/%2.d/%2.d:%2.d:%2.d:%2.d\n", 
+   //         out->tm_year+1900, out->tm_mon+1, out->tm_mday,
+   //         out->tm_hour, out->tm_min, out->tm_sec);
+}
+
+
+void gmtimeDst(time_t dstTimeIn, time_t dstTimeOut)
+{
+   DstTimeIn = dstTimeIn;
+   DstTimeOut = dstTimeOut;
+}
+
+
+//DST from 2am on the second Sunday in March to 2am first Sunday in November
+void gmtimeDstSet(time_t *tp, time_t *dstTimeIn, time_t *dstTimeOut)
+{
+   time_t seconds, timeIn, timeOut;
+   struct tm tmDate;
+   int year, days;
+
+   DstTimeIn = 0;
+   DstTimeOut = 0;
+   gmtime_r(tp, &tmDate);
+   year = tmDate.tm_year;
+
+   //March 1, year, 2AM -> second Sunday
+   tmDate.tm_year = year;
+   tmDate.tm_mon = 2;
+   tmDate.tm_mday = 1;
+   tmDate.tm_hour = 2;
+   tmDate.tm_min = 0;
+   tmDate.tm_sec = 0;
+   seconds = mktime(&tmDate);
+   gmtime_r(&seconds, &tmDate);
+   days = 7 - tmDate.tm_wday + 7;
+   *dstTimeIn = timeIn = seconds + days * SEC_PER_DAY;
+
+   //November 1, year, 2AM -> first Sunday
+   tmDate.tm_year = year;
+   tmDate.tm_mon = 10;
+   tmDate.tm_mday = 1;
+   tmDate.tm_hour = 2;
+   tmDate.tm_min = 0;
+   tmDate.tm_sec = 0;
+   seconds = mktime(&tmDate);
+   gmtime_r(&seconds, &tmDate);
+   days = 7 - tmDate.tm_wday;
+   *dstTimeOut = timeOut = seconds + days * SEC_PER_DAY;
+
+   DstTimeIn = timeIn;
+   DstTimeOut = timeOut;
+}
+#endif //INCLUDE_TIMELIB
+
diff --git a/kernel/makefile b/kernel/makefile
new file mode 100644 (file)
index 0000000..7ac265e
--- /dev/null
@@ -0,0 +1,192 @@
+# Makefile for Plasma RTOS and Plasma TCP/IP stack\r
+\r
+ifeq ($(LANG),)\r
+\r
+# Customize for Windows\r
+# The MIPS gcc compiler must use the cygwin1.dll that came with the compiler.\r
+CC_X86 = cl /O1 /nologo /I..\tools\r
+CP = copy\r
+RM = del\r
+DWIN32 = -DWIN32\r
+BIN_MIPS = ..\gccmips_elf\r
+TOOLS_DIR = ..\tools\\\r
+TOOLS2_DIR = ..\tools\r
+APP_DIR = ..\App\\\r
+LINUX_PWD =\r
+ALIASING  =\r
+GCC_MIPS  = $(BIN_MIPS)\gcc $(CFLAGS)\r
+AS_MIPS   = $(BIN_MIPS)\as\r
+LD_MIPS   = $(BIN_MIPS)\ld\r
+DUMP_MIPS = $(BIN_MIPS)\objdump\r
+CONVERT_BIN = $(TOOLS_DIR)convert_bin.exe\r
+OBJ = obj\r
+CFLAGS_X86 = /c /DWIN32\r
+LFLAGS_X86 =\r
+\r
+else\r
+\r
+# Customized for Linux\r
+# See the GNU GCC tab on the Opencores Plasma page\r
+CC_X86 = gcc -Wall -O -g -I../tools\r
+CP = cp\r
+RM = rm -rf \r
+DWIN32 =\r
+TOOLS_DIR = ../tools/\r
+TOOLS2_DIR = ../tools\r
+APP_DIR = ../App/\r
+LINUX_PWD = ./\r
+ALIASING  = -fno-strict-aliasing\r
+GCC_MIPS  = $(BIN_MIPS)mips-elf-gcc $(CFLAGS)\r
+AS_MIPS   = $(BIN_MIPS)mips-elf-as\r
+LD_MIPS   = $(BIN_MIPS)mips-elf-ld\r
+DUMP_MIPS = $(BIN_MIPS)mips-elf-objdump\r
+CONVERT_BIN = $(TOOLS_DIR)convert_bin.exe\r
+#CONVERT_BIN = $(BIN_MIPS)mips-elf-objcopy -I elf32-big -O binary test.axf test.bin\r
+OBJ = o\r
+CFLAGS_X86 = -c -DWIN32 -DLINUX\r
+LFLAGS_X86 = -lm\r
+\r
+endif\r
+\r
+# Use software multiplier (don't use mult.vhd)\r
+CFLAGS_SW_MULT = -mno-mul -DUSE_SW_MULT\r
+\r
+# Use 16 fewer registers (make reg_bank.vhd smaller)\r
+CFLAGS_FEW_REGS = -ffixed-t0 -ffixed-t1 -ffixed-t2 -ffixed-t3 -ffixed-t4 -ffixed-t5 -ffixed-t6 -ffixed-t7 -ffixed-s0 -ffixed-s1 -ffixed-s2 -ffixed-s3 -ffixed-s4 -ffixed-s5 -ffixed-s6 -ffixed-s7 \r
+\r
+CFLAGS = -O2 -Wall -c -s -I$(TOOLS2_DIR) -msoft-float -fno-builtin\r
+#CFLAGS += $(CFLAGS_SW_MULT)\r
+#CFLAGS += $(CFLAGS_FEW_REGS)\r
+\r
+# Build just the Plasma RTOS for Plasma CPU\r
+rtos: \r
+       $(AS_MIPS) -o boot.o $(TOOLS_DIR)boot.asm\r
+       $(GCC_MIPS) rtos.c\r
+       $(GCC_MIPS) libc.c\r
+       $(GCC_MIPS) uart.c\r
+       $(GCC_MIPS) rtos_test.c\r
+       $(GCC_MIPS) math.c $(ALIASING)\r
+       $(LD_MIPS) -Ttext 0x10000000 -eentry -Map test.map -s -N -o test.axf \\r
+       boot.o rtos.o libc.o uart.o rtos_test.o math.o \r
+       $(CONVERT_BIN)\r
+       @sort <test.map >test2.map\r
+       @$(DUMP_MIPS) --disassemble test.axf > test.lst\r
+\r
+# Build the Plasma RTOS, Plasma TCP/IP stack, and web server for the Plasma CPU\r
+# Use the serial port and etermip for TCP/IP packets\r
+rtos_tcpip:\r
+       $(AS_MIPS) -o boot.o $(TOOLS_DIR)boot.asm\r
+       $(GCC_MIPS) rtos.c\r
+       $(GCC_MIPS) libc.c\r
+       $(GCC_MIPS) uart.c\r
+       $(GCC_MIPS) rtos_test.c -DINCLUDE_HTML -DINCLUDE_CONSOLE\r
+       $(GCC_MIPS) math.c $(ALIASING)\r
+       $(GCC_MIPS) tcpip.c -DINCLUDE_FILESYS\r
+       $(GCC_MIPS) http.c -DINCLUDE_FILESYS -DEXAMPLE_HTML\r
+       $(GCC_MIPS) netutil.c\r
+       $(GCC_MIPS) filesys.c\r
+       $(LD_MIPS) -Ttext 0x10000000 -eentry -Map test.map -s -N -o test.axf \\r
+       boot.o rtos.o libc.o uart.o rtos_test.o math.o tcpip.o \\r
+       http.o netutil.o filesys.o\r
+       $(CONVERT_BIN)\r
+       @sort <test.map >test2.map\r
+       @$(DUMP_MIPS) --disassemble test.axf > test.lst\r
+\r
+# Use Ethernet for TCP/IP packets, use flash file system\r
+rtos_tcpip_eth:\r
+       $(AS_MIPS) -o boot.o $(TOOLS_DIR)boot.asm\r
+       $(GCC_MIPS) rtos.c\r
+       $(GCC_MIPS) libc.c\r
+       $(GCC_MIPS) uart.c -DNO_PACKETS\r
+       $(GCC_MIPS) rtos_test.c -DINCLUDE_ETH -DINCLUDE_CONSOLE\r
+       $(GCC_MIPS) math.c $(ALIASING)\r
+       $(GCC_MIPS) tcpip.c -DINCLUDE_FILESYS\r
+       $(GCC_MIPS) http.c -DINCLUDE_FILESYS -DEXAMPLE_HTML\r
+       $(GCC_MIPS) netutil.c -DINCLUDE_FLASH -DDLL_SETUP\r
+       $(GCC_MIPS) filesys.c -DINCLUDE_FLASH\r
+       $(GCC_MIPS) ethernet.c\r
+       $(GCC_MIPS) flash.c\r
+       $(LD_MIPS) -Ttext 0x10000000 -eentry -Map test.map -s -N -o test.axf \\r
+       boot.o rtos.o libc.o uart.o rtos_test.o math.o tcpip.o \\r
+       http.o netutil.o filesys.o ethernet.o flash.o\r
+       $(CONVERT_BIN)\r
+       @sort <test.map >test2.map\r
+       @$(DUMP_MIPS) --disassemble test.axf > test.lst\r
+\r
+# Build full test application.  (Use rtos_tcpip_eth instead.) \r
+rtosfull: \r
+       $(AS_MIPS) -o boot.o $(TOOLS_DIR)boot.asm\r
+       $(GCC_MIPS) rtos.c\r
+       $(GCC_MIPS) libc.c\r
+       $(GCC_MIPS) uart.c -DNO_PACKETS\r
+       $(GCC_MIPS) rtos_test.c -DINCLUDE_ETH -DINCLUDE_CONSOLE\r
+       $(GCC_MIPS) math.c $(ALIASING)\r
+       $(GCC_MIPS) tcpip.c -DINCLUDE_FILESYS\r
+       $(GCC_MIPS) http.c -DINCLUDE_FILESYS\r
+       $(GCC_MIPS) netutil.c -DINCLUDE_FLASH -DDLL_SETUP\r
+       $(GCC_MIPS) filesys.c -DINCLUDE_FLASH\r
+       $(GCC_MIPS) ethernet.c\r
+       $(GCC_MIPS) flash.c\r
+       $(GCC_MIPS) -I. $(APP_DIR)html.c -DMainThread=HtmlThread\r
+       $(GCC_MIPS) -I. $(APP_DIR)image.c\r
+       $(GCC_MIPS) -I. $(APP_DIR)tictac.c\r
+       $(GCC_MIPS) -I. $(APP_DIR)tic3d.c\r
+       $(GCC_MIPS) -I. $(APP_DIR)connect4.c\r
+       $(LD_MIPS) -Ttext 0x10000000 -eentry -Map test.map -s -N -o test.axf \\r
+       boot.o rtos.o libc.o uart.o rtos_test.o math.o tcpip.o \\r
+       http.o netutil.o filesys.o ethernet.o flash.o \\r
+       html.o image.o tictac.o tic3d.o connect4.o \r
+       $(CONVERT_BIN)\r
+       @sort <test.map >test2.map\r
+       @$(DUMP_MIPS) --disassemble test.axf > test.lst\r
+\r
+# Create a separate Dynamically Linked Library executable\r
+# ftp test.bin to /flash/web/dlltest\r
+# telnet to board and execute "dlltest"\r
+dlltest:\r
+       $(GCC_MIPS) -G0 dlltest.c\r
+       $(LD_MIPS) -Ttext 0x10100000 -s -N -o test.axf dlltest.o\r
+       $(CONVERT_BIN)\r
+       @$(DUMP_MIPS) --disassemble test.axf > test.lst\r
+\r
+# Test the RTOS running on a PC\r
+testrtos:\r
+       @$(CC_X86) $(CFLAGS_X86) rtos.c\r
+       @$(CC_X86) $(CFLAGS_X86) libc.c \r
+       @$(CC_X86) $(CFLAGS_X86) uart.c\r
+       @$(CC_X86) $(CFLAGS_X86) rtos_test.c\r
+       @$(CC_X86) $(CFLAGS_X86) math.c $(ALIASING)\r
+       @$(CC_X86) $(LFLAGS_X86) -o testrtos.exe rtos.$(OBJ) libc.$(OBJ) uart.$(OBJ) rtos_test.$(OBJ) math.$(OBJ) \r
+       $(LINUX_PWD)testrtos.exe\r
+\r
+# Test the TCP/IP protocol stack running on a PC (requires Windows)\r
+testip:\r
+       @$(CC_X86) $(CFLAGS_X86) tcpip.c\r
+       @$(CC_X86) $(CFLAGS_X86) http.c /DEXAMPLE_HTML\r
+       @$(CC_X86) $(CFLAGS_X86) netutil.c\r
+       @$(CC_X86) $(CFLAGS_X86) filesys.c\r
+       @$(CC_X86) $(CFLAGS_X86) libc.c /I$(TOOLS_DIR) \r
+       @$(CC_X86) $(CFLAGS_X86) /DSIMULATE_PLASMA $(TOOLS_DIR)etermip.c\r
+       @$(CC_X86) $(CFLAGS_X86) os_stubs.c\r
+       @$(CC_X86) -o testip.exe etermip.obj $(TOOLS_DIR)wpcap.lib \\r
+       tcpip.obj http.obj netutil.obj filesys.obj libc.obj os_stubs.obj\r
+       @echo Try http://plasmb/.  Try telnet plasmb.  Try ftp plasmb.\r
+       $(LINUX_PWD)testip.exe\r
+\r
+clean:\r
+       -$(RM) *.o *.obj *.axf *.map *.lst *.hex *.txt *.bin *.exe\r
+\r
+# Run a Plasma CPU opcode simulator (can execute rtos target)\r
+run: \r
+       @$(TOOLS_DIR)mlite.exe test.bin \r
+\r
+disassemble:\r
+       -@$(TOOLS_DIR)mlite.exe test.bin BD > test.txt\r
+\r
+# Start the EtermIP terminal program to download the code to the Plasma CPU\r
+# and permit an Ethernet packets to be transfered.\r
+download:\r
+       @echo Reset board before downloading code\r
+       $(TOOLS_DIR)etermip.exe\r
+\r
+\r
diff --git a/kernel/math.c b/kernel/math.c
new file mode 100644 (file)
index 0000000..976f5d4
--- /dev/null
@@ -0,0 +1,692 @@
+/*--------------------------------------------------------------------
+ * TITLE: Plasma Floating Point Library
+ * AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
+ * DATE CREATED: 3/2/06
+ * FILENAME: math.c
+ * PROJECT: Plasma CPU core
+ * COPYRIGHT: Software placed into the public domain by the author.
+ *    Software 'as is' without warranty.  Author liable for nothing.
+ * DESCRIPTION:
+ *    Plasma Floating Point Library
+ *--------------------------------------------------------------------
+ * IEEE_fp = sign(1) | exponent(8) | fraction(23)
+ * cos(x)=1-x^2/2!+x^4/4!-x^6/6!+...
+ * exp(x)=1+x+x^2/2!+x^3/3!+...
+ * ln(1+x)=x-x^2/2+x^3/3-x^4/4+...
+ * atan(x)=x-x^3/3+x^5/5-x^7/7+...
+ * pow(x,y)=exp(y*ln(x))
+ * x=tan(a+b)=(tan(a)+tan(b))/(1-tan(a)*tan(b))
+ * atan(x)=b+atan((x-atan(b))/(1+x*atan(b)))
+ * ln(a*x)=ln(a)+ln(x); ln(x^n)=n*ln(x)
+ *--------------------------------------------------------------------*/
+#include "rtos.h"
+
+//#define USE_SW_MULT
+#if !defined(WIN32) && !defined(USE_SW_MULT)
+#define USE_MULT64
+#endif
+
+#define PI ((float)3.1415926)
+#define PI_2 ((float)(PI/2.0))
+#define PI2 ((float)(PI*2.0))
+
+#define FtoL(X) (*(unsigned long*)&(X))
+#define LtoF(X) (*(float*)&(X))
+
+
+float FP_Neg(float a_fp)
+{
+   unsigned long a;
+   a = FtoL(a_fp);
+   a ^= 0x80000000;
+   return LtoF(a);
+}
+
+
+float FP_Add(float a_fp, float b_fp)
+{
+   unsigned long a, b, c;
+   unsigned long as, bs, cs;     //sign
+   long ae, af, be, bf, ce, cf;  //exponent and fraction
+   a = FtoL(a_fp);
+   b = FtoL(b_fp);
+   as = a >> 31;                        //sign
+   ae = (a >> 23) & 0xff;               //exponent
+   af = 0x00800000 | (a & 0x007fffff);  //fraction
+   bs = b >> 31;
+   be = (b >> 23) & 0xff;
+   bf = 0x00800000 | (b & 0x007fffff);
+   if(ae > be) 
+   {
+      if(ae - be < 30) 
+         bf >>= ae - be;
+      else 
+         bf = 0;
+      ce = ae;
+   } 
+   else 
+   {
+      if(be - ae < 30) 
+         af >>= be - ae;
+      else 
+         af = 0;
+      ce = be;
+   }
+   cf = (as ? -af : af) + (bs ? -bf : bf);
+   cs = cf < 0;
+   cf = cf>=0 ? cf : -cf;
+   if(cf == 0) 
+      return LtoF(cf);
+   while(cf & 0xff000000) 
+   {
+      ++ce;
+      cf >>= 1;
+   }
+   while((cf & 0xff800000) == 0) 
+   {
+      --ce;
+      cf <<= 1;
+   }
+   c = (cs << 31) | (ce << 23) | (cf & 0x007fffff);
+   if(ce < 1) 
+      c = 0;
+   return LtoF(c);
+}
+
+
+float FP_Sub(float a_fp, float b_fp)
+{
+   return FP_Add(a_fp, FP_Neg(b_fp));
+}
+
+
+float FP_Mult(float a_fp, float b_fp)
+{
+   unsigned long a, b, c;
+   unsigned long as, af, bs, bf, cs, cf;
+   long ae, be, ce;
+#ifndef USE_MULT64
+   unsigned long a2, a1, b2, b1, med1, med2;
+#endif
+   unsigned long hi, lo;
+   a = FtoL(a_fp);
+   b = FtoL(b_fp);
+   as = a >> 31;
+   ae = (a >> 23) & 0xff;
+   af = 0x00800000 | (a & 0x007fffff);
+   bs = b >> 31;
+   be = (b >> 23) & 0xff;
+   bf = 0x00800000 | (b & 0x007fffff);
+   cs = as ^ bs;
+#ifndef USE_MULT64
+   a1 = af & 0xffff;
+   a2 = af >> 16;
+   b1 = bf & 0xffff;
+   b2 = bf >> 16;
+   lo = a1 * b1;
+   med1 = a2 * b1 + (lo >> 16);
+   med2 = a1 * b2;
+   hi = a2 * b2 + (med1 >> 16) + (med2 >> 16);
+   med1 = (med1 & 0xffff) + (med2 & 0xffff);
+   hi += (med1 >> 16);
+   lo = (med1 << 16) | (lo & 0xffff);
+#else
+   lo = OS_AsmMult(af, bf, &hi);
+#endif
+   cf = (hi << 9) | (lo >> 23);
+   ce = ae + be - 0x80 + 1;
+   if(cf == 0) 
+      return LtoF(cf);
+   while(cf & 0xff000000) 
+   {
+      ++ce;
+      cf >>= 1;
+   }
+   c = (cs << 31) | (ce << 23) | (cf & 0x007fffff);
+   if(ce < 1) 
+      c = 0;
+   return LtoF(c);
+}
+
+
+float FP_Div(float a_fp, float b_fp)
+{
+   unsigned long a, b, c;
+   unsigned long as, af, bs, bf, cs, cf;
+   unsigned long a1, b1;
+#ifndef USE_MULT64
+   unsigned long a2, b2, med1, med2;
+#endif
+   unsigned long hi, lo;
+   long ae, be, ce, d;
+   a = FtoL(a_fp);
+   b = FtoL(b_fp);
+   as = a >> 31;
+   ae = (a >> 23) & 0xff;
+   af = 0x00800000 | (a & 0x007fffff);
+   bs = b >> 31;
+   be = (b >> 23) & 0xff;
+   bf = 0x00800000 | (b & 0x007fffff);
+   cs = as ^ bs;
+   ce = ae - (be - 0x80) + 6 - 8;
+   a1 = af << 4; //8
+   b1 = bf >> 8;
+   cf = a1 / b1;
+   cf <<= 12; //8
+#if 1                  /*non-quick*/
+#ifndef USE_MULT64
+   a1 = cf & 0xffff;
+   a2 = cf >> 16;
+   b1 = bf & 0xffff;
+   b2 = bf >> 16;
+   lo = a1 * b1;
+   med1 =a2 * b1 + (lo >> 16);
+   med2 = a1 * b2;
+   hi = a2 * b2 + (med1 >> 16) + (med2 >> 16);
+   med1 = (med1 & 0xffff) + (med2 & 0xffff);
+   hi += (med1 >> 16);
+   lo = (med1 << 16) | (lo & 0xffff);
+#else
+   lo = OS_AsmMult(cf, bf, &hi);
+#endif
+   lo = (hi << 8) | (lo >> 24);
+   d = af - lo;    //remainder
+   assert(-0xffff < d && d < 0xffff);
+   d <<= 16;
+   b1 = bf >> 8;
+   d = d / (long)b1;
+   cf += d;
+#endif
+   if(cf == 0) 
+      return LtoF(cf);
+   while(cf & 0xff000000) 
+   {
+      ++ce;
+      cf >>= 1;
+   }
+   if(ce < 0) 
+      ce = 0;
+   c = (cs << 31) | (ce << 23) | (cf & 0x007fffff);
+   if(ce < 1) 
+      c = 0;
+   return LtoF(c);
+}
+
+
+long FP_ToLong(float a_fp)
+{
+   unsigned long a;
+   unsigned long as;
+   long ae;
+   long af, shift;
+   a = FtoL(a_fp);
+   as = a >> 31;
+   ae = (a >> 23) & 0xff;
+   af = 0x00800000 | (a & 0x007fffff);
+   af <<= 7;
+   shift = -(ae - 0x80 - 29);
+   if(shift > 0) 
+   {
+      if(shift < 31) 
+         af >>= shift;
+      else 
+         af = 0;
+   }
+   af = as ? -af: af;
+   return af;
+}
+
+
+float FP_ToFloat(long af)
+{
+   unsigned long a;
+   unsigned long as, ae;
+   as = af>=0 ? 0: 1;
+   af = af>=0 ? af: -af;
+   ae = 0x80 + 22;
+   if(af == 0) 
+      return LtoF(af);
+   while(af & 0xff000000) 
+   {
+      ++ae;
+      af >>= 1;
+   }
+   while((af & 0xff800000) == 0) 
+   {
+      --ae;
+      af <<= 1;
+   }
+   a = (as << 31) | (ae << 23) | (af & 0x007fffff);
+   return LtoF(a);
+}
+
+
+//0 iff a==b; 1 iff a>b; -1 iff a<b
+int FP_Cmp(float a_fp, float b_fp)
+{
+   unsigned long a, b;
+   unsigned long as, ae, af, bs, be, bf;
+   int gt;
+   a = FtoL(a_fp);
+   b = FtoL(b_fp);
+   if(a == b)
+      return 0;
+   as = a >> 31;
+   bs = b >> 31;
+   if(as > bs)
+      return -1;
+   if(as < bs)
+      return 1;
+   gt = as ? -1 : 1;
+   ae = (a >> 23) & 0xff;
+   be = (b >> 23) & 0xff;
+   if(ae > be)
+      return gt;
+   if(ae < be)
+      return -gt;
+   af = 0x00800000 | (a & 0x007fffff);
+   bf = 0x00800000 | (b & 0x007fffff);
+   if(af > bf)
+      return gt;
+   return -gt;
+}
+
+
+int __ltsf2(float a, float b)
+{
+   return FP_Cmp(a, b);
+}
+
+int __lesf2(float a, float b)
+{
+   return FP_Cmp(a, b);
+}
+
+int __gtsf2(float a, float b)
+{
+   return FP_Cmp(a, b);
+}
+
+int __gesf2(float a, float b)
+{
+   return FP_Cmp(a, b);
+}
+
+int __eqsf2(float a, float b)
+{
+   return FtoL(a) != FtoL(b);
+}
+
+int __nesf2(float a, float b)
+{
+   return FtoL(a) != FtoL(b);
+}
+
+
+float FP_Sqrt(float a)
+{
+   float x1, y1, x2, y2, x3;
+   long i;
+   x1 = FP_ToFloat(1);
+   y1 = FP_Sub(FP_Mult(x1, x1), a);  //y1=x1*x1-a;
+   x2 = FP_ToFloat(100);
+   y2 = FP_Sub(FP_Mult(x2, x2), a);
+   for(i = 0; i < 10; ++i) 
+   {
+      if(FtoL(y1) == FtoL(y2)) 
+         return x2;     
+      //x3=x2-(x1-x2)*y2/(y1-y2);
+      x3 = FP_Sub(x2, FP_Div(FP_Mult(FP_Sub(x1, x2), y2), FP_Sub(y1, y2)));
+      x1 = x2;
+      y1 = y2;
+      x2 = x3;
+      y2 = FP_Sub(FP_Mult(x2, x2), a);
+   }
+   return x2;
+}
+
+
+float FP_Cos(float rad)
+{
+   int n;
+   float answer, x2, top, bottom, sign;
+   while(FP_Cmp(rad, PI2) > 0) 
+      rad = FP_Sub(rad, PI2);
+   while(FP_Cmp(rad, (float)0.0) < 0) 
+      rad = FP_Add(rad, PI2);
+   answer = 1.0;
+   sign = 1.0;
+   if(FP_Cmp(rad, PI) >= 0) 
+   {
+      rad = FP_Sub(rad, PI);
+      sign = FP_ToFloat(-1);
+   }
+   if(FP_Cmp(rad, PI_2) >= 0)
+   {
+      rad = FP_Sub(PI, rad);
+      sign = FP_Neg(sign);
+   }
+   x2 = FP_Mult(rad, rad);
+   top = 1.0;
+   bottom = 1.0;
+   for(n = 2; n < 12; n += 2) 
+   {
+      top = FP_Mult(top, FP_Neg(x2));
+      bottom = FP_Mult(bottom, FP_ToFloat((n - 1) * n));
+      answer = FP_Add(answer, FP_Div(top, bottom));
+   }
+   return FP_Mult(answer, sign);
+}
+
+
+float FP_Sin(float rad)
+{
+   const float pi_2=(float)(PI/2.0);
+   return FP_Cos(FP_Sub(rad, pi_2));
+}
+
+
+float FP_Atan(float x)
+{
+   const float b=(float)(PI/8.0);
+   const float atan_b=(float)0.37419668; //atan(b);
+   int n;
+   float answer, x2, top;
+   if(FP_Cmp(x, (float)0.0) >= 0) 
+   {
+      if(FP_Cmp(x, (float)1.0) > 0) 
+         return FP_Sub(PI_2, FP_Atan(FP_Div((float)1.0, x)));
+   } 
+   else 
+   {
+      if(FP_Cmp(x, (float)-1.0) > 0) 
+         return FP_Sub(-PI_2, FP_Atan(FP_Div((float)1.0, x)));
+   }
+   if(FP_Cmp(x, (float)0.45) > 0) 
+   {
+      //answer = (x - atan_b) / (1 + x * atan_b);
+      answer = FP_Div(FP_Sub(x, atan_b), FP_Add(1.0, FP_Mult(x, atan_b)));
+      //answer = b + FP_Atan(answer) - (float)0.034633; /*FIXME fudge?*/
+      answer = FP_Sub(FP_Add(b, FP_Atan(answer)), (float)0.034633);
+      return answer;
+   }
+   if(FP_Cmp(x, (float)-0.45) < 0)
+   {
+      x = FP_Neg(x);
+      //answer = (x - atan_b) / (1 + x * atan_b);
+      answer = FP_Div(FP_Sub(x, atan_b), FP_Add(1.0, FP_Mult(x, atan_b)));
+      //answer = b + FP_Atan(answer) - (float)0.034633; /*FIXME*/
+      answer = FP_Sub(FP_Add(b, FP_Atan(answer)), (float)0.034633);
+      return FP_Neg(answer);
+   }
+   answer = x;
+   x2 = FP_Mult(FP_Neg(x), x);
+   top = x;
+   for(n = 3; n < 14; n += 2) 
+   {
+      top = FP_Mult(top, x2);
+      answer = FP_Add(answer, FP_Div(top, FP_ToFloat(n)));
+   }
+   return answer;
+}
+
+
+float FP_Atan2(float y, float x)
+{
+   float answer,r;
+   r = y / x;
+   answer = FP_Atan(r);
+   if(FP_Cmp(x, (float)0.0) < 0) 
+   {
+      if(FP_Cmp(y, (float)0.0) > 0) 
+         answer = FP_Add(answer, PI);
+      else 
+         answer = FP_Sub(answer, PI);
+   }
+   return answer;
+}
+
+
+float FP_Exp(float x)
+{
+   const float e2=(float)7.389056099;
+   const float inv_e2=(float)0.135335283;
+   float answer, top, bottom, mult;
+   int n;
+
+   mult = 1.0;
+   while(FP_Cmp(x, (float)2.0) > 0) 
+   {
+      mult = FP_Mult(mult, e2);
+      x = FP_Add(x, (float)-2.0);
+   }
+   while(FP_Cmp(x, (float)-2.0) < 0)
+   {
+      mult = FP_Mult(mult, inv_e2);
+      x = FP_Add(x, (float)2.0);
+   }
+   answer = FP_Add((float)1.0, x);
+   top = x;
+   bottom = 1.0;
+   for(n = 2; n < 15; ++n) 
+   {
+      top = FP_Mult(top, x);
+      bottom = FP_Mult(bottom, FP_ToFloat(n));
+      answer = FP_Add(answer, FP_Div(top, bottom));
+   }
+   return FP_Mult(answer, mult);
+}
+
+
+float FP_Log(float x)
+{
+   const float log_2=(float)0.69314718; /*log(2.0)*/
+   int n;
+   float answer, top, add;
+   add = 0.0;
+   while(FP_Cmp(x, 16.0) > 0)
+   {
+      x = FP_Mult(x, (float)0.0625);
+      add = FP_Add(add, (float)(log_2 * 4));
+   }
+   while(FP_Cmp(x, 1.5) > 0)
+   {
+      x = FP_Mult(x, 0.5);
+      add = FP_Add(add, log_2);
+   }
+   while(FP_Cmp(x, 0.5) < 0)
+   {
+      x = FP_Mult(x, 2.0);
+      add = FP_Sub(add, log_2);
+   }
+   x = FP_Sub(x, 1.0);
+   answer = 0.0;
+   top = -1.0;
+   for(n = 1; n < 14; ++n) 
+   {
+      top = FP_Mult(top, FP_Neg(x));
+      answer = FP_Add(answer, FP_Div(top, FP_ToFloat(n)));
+   }
+   return FP_Add(answer, add);
+}
+
+
+float FP_Pow(float x, float y)
+{
+   return FP_Exp(y * FP_Log(x));
+}
+
+
+/********************************************/
+//These five functions will only be used if the flag "-mno-mul" is enabled
+#ifdef USE_SW_MULT
+unsigned long __mulsi3(unsigned long a, unsigned long b)
+{
+   unsigned long answer = 0;
+   while(b)
+   {
+      if(b & 1)
+         answer += a;
+      a <<= 1;
+      b >>= 1;
+   }
+   return answer;
+}
+
+
+static unsigned long DivideMod(unsigned long a, unsigned long b, int doMod)
+{
+   unsigned long upper=a, lower=0;
+   int i;
+   a = b << 31;
+   for(i = 0; i < 32; ++i)
+   {
+      lower = lower << 1;
+      if(upper >= a && a && b < 2)
+      {
+         upper = upper - a;
+         lower |= 1;
+      }
+      a = ((b&2) << 30) | (a >> 1);
+      b = b >> 1;
+   }
+   if(!doMod)
+      return lower;
+   return upper;
+}
+
+
+unsigned long __udivsi3(unsigned long a, unsigned long b)
+{
+   return DivideMod(a, b, 0);
+}
+
+
+long __divsi3(long a, long b)
+{
+   long answer, negate=0;
+   if(a < 0)
+   {
+      a = -a;
+      negate = !negate;
+   }
+   if(b < 0)
+   {
+      b = -b;
+      negate = !negate;
+   }
+   answer = DivideMod(a, b, 0);
+   if(negate)
+      answer = -answer;
+   return answer;
+}
+
+
+unsigned long __umodsi3(unsigned long a, unsigned long b)
+{
+   return DivideMod(a, b, 1);
+}
+#endif
+
+
+/*************** Test *****************/
+#ifdef WIN32
+#undef _LIBC
+#include <math.h>
+#undef printf
+#undef getch
+int printf(const char *, ...);
+struct {
+   char *name;
+   float low, high;
+   double (*func1)(double);
+   float (*func2)(float);
+} test_info[]={
+   {"cos", -2*PI, 2*PI, cos, FP_Cos},
+   {"sin", -2*PI, 2*PI, sin, FP_Sin},
+   {"atan", -3.0, 2.0, atan, FP_Atan},
+   {"log", (float)0.01, (float)4.0, log, FP_Log},
+   {"exp", (float)-5.01, (float)30.0, exp, FP_Exp},
+   {"sqrt", (float)0.01, (float)1000.0, sqrt, FP_Sqrt}
+};
+
+
+void TestMathFull(void)
+{
+   float a, b, c, d;
+   float error1, error2, error3, error4, error5;
+   int test;
+
+   a = PI * PI;
+   b = PI;
+   c = FP_Div(a, b);
+   printf("%10f %10f %10f %10f %10f\n",
+      (double)a, (double)b, (double)(a/b), (double)c, (double)(a/b-c));
+   a = a * 200;
+   for(b = -(float)2.718281828*100; b < 300; b += (float)23.678) 
+   {
+      c = FP_Div(a, b);
+      d = a / b - c;
+      printf("%10f %10f %10f %10f %10f\n",
+         (double)a, (double)b, (double)(a/b), (double)c, (double)(a/b-c));
+   }
+   //getch();
+
+   for(test = 0; test < 6; ++test) 
+   {
+      printf("\nTesting %s\n", test_info[test].name);
+      for(a = test_info[test].low; 
+          a <= test_info[test].high;
+          a += (test_info[test].high-test_info[test].low)/(float)20.0) 
+      {
+         b = (float)test_info[test].func1(a);
+         c = test_info[test].func2(a);
+         d = b - c;
+         printf("%s %10f %10f %10f %10f\n", test_info[test].name, a, b, c, d);
+      }
+      //getch();
+   }
+
+   a = FP_ToFloat((long)6.0);
+   b = FP_ToFloat((long)2.0);
+   printf("%f %f\n", (double)a, (double)b);
+   c = FP_Add(a, b);
+   printf("add %f %f\n", (double)(a + b), (double)c);
+   c = FP_Sub(a, b);
+   printf("sub %f %f\n", (double)(a - b), (double)c);
+   c = FP_Mult(a, b);
+   printf("mult %f %f\n", (double)(a * b), (double)c);
+   c = FP_Div(a, b);
+   printf("div %f %f\n", (double)(a / b), (double)c);
+   //getch();
+
+   for(a = (float)-13756.54; a < (float)17400.0; a += (float)64.45) 
+   {
+      for(b = (float)-875.36; b < (float)935.8; b += (float)36.7) 
+      {
+         error1 = (float)1.0 - (a + b) / FP_Add(a, b);
+         error2 = (float)1.0 - (a * b) / FP_Mult(a, b);
+         error3 = (float)1.0 - (a / b) / FP_Div(a, b);
+         error4 = (float)1.0 - a / FP_ToFloat(FP_ToLong(a));
+         error5 = error1 + error2 + error3 + error4;
+         if(error5 < 0.00005) 
+            continue;
+         printf("ERROR!\n");
+         printf("a=%f b=%f\n", (double)a, (double)b);
+         printf("  a+b=%f %f\n", (double)(a+b), (double)FP_Add(a, b));
+         printf("  a*b=%f %f\n", (double)(a*b), (double)FP_Mult(a, b));
+         printf("  a/b=%f %f\n", (double)(a/b), (double)FP_Div(a, b));
+         printf("  a=%f %ld %f\n", (double)a, FP_ToLong(a),
+                                   (double)FP_ToFloat((long)a));
+         printf("  %f %f %f %f\n", (double)error1, (double)error2,
+            (double)error3, (double)error4);
+         //if(error5 > 0.001) 
+         //   getch();
+      }
+   }
+   printf("done.\n");
+   //getch();
+}
+#endif
+
+
diff --git a/kernel/netutil.c b/kernel/netutil.c
new file mode 100644 (file)
index 0000000..88095dc
--- /dev/null
@@ -0,0 +1,1159 @@
+/*--------------------------------------------------------------------\r
+ * TITLE: Plasma TCP/IP Network Utilities\r
+ * AUTHOR: Steve Rhoads (rhoadss@yahoo.com)\r
+ * DATE CREATED: 4/20/07\r
+ * FILENAME: netutil.c\r
+ * PROJECT: Plasma CPU core\r
+ * COPYRIGHT: Software placed into the public domain by the author.\r
+ *    Software 'as is' without warranty.  Author liable for nothing.\r
+ * DESCRIPTION:\r
+ *    Plasma FTP server and FTP client and TFTP server and client \r
+ *    and Telnet server.\r
+ *--------------------------------------------------------------------*/\r
+#undef INCLUDE_FILESYS\r
+#define INCLUDE_FILESYS\r
+#ifdef WIN32\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include <ctype.h>\r
+#define _LIBC\r
+#endif\r
+#include "rtos.h"\r
+#include "tcpip.h"\r
+\r
+#ifdef DLL_SETUP\r
+static void ConsoleRun(IPSocket *socket, char *argv[]);\r
+#endif\r
+\r
+//******************* FTP Server ************************\r
+typedef struct {\r
+   IPSocket *socket;\r
+   int ip, port, bytes, done, canReceive;\r
+   FILE *file;\r
+} FtpdInfo;\r
+\r
+static void FtpdSender(IPSocket *socket)\r
+{\r
+   unsigned char buf[600];\r
+   int i, bytes, bytes2;\r
+   FtpdInfo *info = (FtpdInfo*)socket->userPtr;\r
+\r
+   if(info == NULL || info->done)\r
+      return;\r
+   fseek(info->file, info->bytes, 0);\r
+   for(i = 0; i < 100000; ++i)\r
+   {\r
+      bytes = fread(buf, 1, 512, info->file);\r
+      bytes2 = IPWrite(socket, buf, bytes);\r
+      info->bytes += bytes2;\r
+      if(bytes != bytes2)\r
+         return;\r
+      if(bytes < 512)\r
+      {\r
+         fclose(info->file);\r
+         IPClose(socket);\r
+         info->done = 1;\r
+         IPPrintf(info->socket, "226 Done\r\n");\r
+         return;\r
+      }\r
+   }\r
+}\r
+\r
+\r
+static void FtpdReceiver(IPSocket *socket)\r
+{\r
+   unsigned char buf[600];\r
+   int bytes, state = socket->state;\r
+   FtpdInfo *info = (FtpdInfo*)socket->userPtr;\r
+\r
+   if(info == NULL || info->done)\r
+      return;\r
+   do\r
+   {\r
+      bytes = IPRead(socket, buf, sizeof(buf));\r
+      fwrite(buf, 1, bytes, info->file);\r
+   } while(bytes);\r
+\r
+   if(state > IP_TCP)\r
+   {\r
+      fclose(info->file);\r
+      info->done = 1;\r
+      IPPrintf(info->socket, "226 Done\r\n");\r
+      IPClose(socket);\r
+      return;\r
+   }\r
+}\r
+\r
+\r
+static void FtpdServer(IPSocket *socket)\r
+{\r
+   uint8 buf[600];\r
+   int bytes;\r
+   int ip0, ip1, ip2, ip3, port0, port1;\r
+   IPSocket *socketOut;\r
+   FtpdInfo *info = (FtpdInfo*)socket->userPtr;\r
+\r
+   if(socket == NULL)\r
+      return;\r
+   bytes = IPRead(socket, buf, sizeof(buf)-1);\r
+   buf[bytes] = 0;\r
+   //printf("(%s)\n", buf);\r
+   if(socket->userPtr == NULL)\r
+   {\r
+      info = (FtpdInfo*)malloc(sizeof(FtpdInfo));\r
+      if(info == NULL)\r
+         return;\r
+      memset(info, 0, sizeof(FtpdInfo));\r
+      socket->userPtr = info;\r
+      info->socket = socket;\r
+      socket->timeoutReset = 60;\r
+      IPPrintf(socket, "220 Connected to Plasma\r\n");\r
+   }\r
+   else if(socket->userPtr == (void*)-1)\r
+   {\r
+      return;\r
+   }\r
+   else if(strstr((char*)buf, "USER"))\r
+   {\r
+      if(strstr((char*)buf, "PlasmaSend"))\r
+         info->canReceive = 1;\r
+      IPPrintf(socket, "331 Password?\r\n");\r
+   }\r
+   else if(strstr((char*)buf, "PASS"))\r
+   {\r
+      IPPrintf(socket, "230 Logged in\r\n");\r
+   }\r
+   else if(strstr((char*)buf, "PORT"))\r
+   {\r
+      sscanf((char*)buf + 5, "%d,%d,%d,%d,%d,%d", &ip0, &ip1, &ip2, &ip3, &port0, &port1);\r
+      info->ip = (ip0 << 24) | (ip1 << 16) | (ip2 << 8) | ip3;\r
+      info->port = (port0 << 8) | port1;\r
+      //printf("ip=0x%x port=%d\n", info->ip, info->port);\r
+      IPPrintf(socket, "200 OK\r\n");\r
+   }\r
+   else if(strstr((char*)buf, "RETR") || strstr((char*)buf, "STOR"))\r
+   {\r
+      char *ptr = strstr((char*)buf, "\r");\r
+      if(ptr)\r
+         *ptr = 0;\r
+      info->file = NULL;\r
+      info->bytes = 0;\r
+      info->done = 0;\r
+      if(strstr((char*)buf, "RETR"))\r
+         info->file = fopen((char*)buf + 5, "rb");\r
+      else if(info->canReceive)\r
+         info->file = fopen((char*)buf + 5, "wb");\r
+      if(info->file)\r
+      {\r
+         IPPrintf(socket, "150 File ready\r\n");\r
+         if(strstr((char*)buf, "RETR"))\r
+            socketOut = IPOpen(IP_MODE_TCP, info->ip, info->port, FtpdSender);\r
+         else\r
+            socketOut = IPOpen(IP_MODE_TCP, info->ip, info->port, FtpdReceiver);\r
+         if(socketOut)\r
+            socketOut->userPtr = info;\r
+      }\r
+      else\r
+      {\r
+         IPPrintf(socket, "500 Error\r\n");\r
+      }\r
+   }\r
+   else if(strstr((char*)buf, "QUIT"))\r
+   {\r
+      if(socket->userPtr)\r
+         free(socket->userPtr);\r
+      socket->userPtr = (void*)-1;\r
+      IPPrintf(socket, "221 Bye\r\n");\r
+      IPClose(socket);\r
+   }\r
+   else if(bytes)\r
+   {\r
+      IPPrintf(socket, "500 Error\r\n");\r
+   }\r
+}\r
+\r
+\r
+void FtpdInit(int UseFiles)\r
+{\r
+   (void)UseFiles;\r
+   IPOpen(IP_MODE_TCP, 0, 21, FtpdServer);\r
+}\r
+\r
+\r
+//******************* FTP Client ************************\r
+\r
+typedef struct {\r
+   uint32 ip, port;\r
+   char user[80], passwd[80], filename[80];\r
+   uint8 *buf;\r
+   int size, bytes, send, state;\r
+} FtpInfo;\r
+\r
+\r
+static void FtpCallbackTransfer(IPSocket *socket)\r
+{\r
+   int bytes, state = socket->state;\r
+   FtpInfo *info = (FtpInfo*)socket->userPtr;\r
+\r
+   //printf("FtpCallbackTransfer\n");\r
+   if(info == NULL)\r
+      return;\r
+   bytes = info->size - info->bytes;\r
+   if(info->send == 0)\r
+      bytes = IPRead(socket, info->buf + info->bytes, bytes);\r
+   else\r
+      bytes = IPWrite(socket, info->buf + info->bytes, bytes);\r
+   info->bytes += bytes;\r
+   if(info->bytes == info->size || (bytes == 0 && state > IP_TCP))\r
+   {\r
+      socket->userFunc(info->buf, info->bytes);\r
+      free(info);\r
+      socket->userPtr = NULL;\r
+      IPClose(socket);\r
+   }\r
+}\r
+\r
+\r
+static void FtpCallback(IPSocket *socket)\r
+{\r
+   char buf[600];\r
+   FtpInfo *info = (FtpInfo*)socket->userPtr;\r
+   int bytes, value;\r
+\r
+   bytes = IPRead(socket, (uint8*)buf, sizeof(buf)-1);\r
+   if(bytes == 0)\r
+      return;\r
+   buf[bytes] = 0;\r
+   sscanf(buf, "%d", &value);\r
+   if(bytes > 2)\r
+      buf[bytes-2] = 0;\r
+   //printf("FtpCallback(%d:%s)\n", socket->userData, buf);\r
+   if(value / 100 != 2 && value / 100 != 3)\r
+      return;\r
+   buf[0] = 0;\r
+   switch(socket->userData) {\r
+   case 0:\r
+      sprintf(buf, "USER %s\r\n", info->user);\r
+      socket->userData = 1;\r
+      break;\r
+   case 1:\r
+      sprintf(buf, "PASS %s\r\n", info->passwd);\r
+      socket->userData = 2;\r
+      if(value == 331)\r
+         break;  //possible fall-through\r
+   case 2:\r
+      sprintf(buf, "PORT %d,%d,%d,%d,%d,%d\r\n",\r
+         info->ip >> 24, (uint8)(info->ip >> 16),\r
+         (uint8)(info->ip >> 8), (uint8)info->ip,\r
+         (uint8)(info->port >> 8), (uint8)info->port);\r
+      socket->userData = 3;\r
+      break;\r
+   case 3:\r
+      if(info->send == 0)\r
+         sprintf(buf, "RETR %s\r\n", info->filename);\r
+      else\r
+         sprintf(buf, "STOR %s\r\n", info->filename);\r
+      socket->userData = 4;\r
+      break;\r
+   case 4:\r
+      sprintf(buf, "QUIT\r\n");\r
+      socket->userData = 9;\r
+      break;\r
+   }\r
+   IPWrite(socket, (uint8*)buf, strlen(buf));\r
+   IPWriteFlush(socket);\r
+   if(socket->userData == 9)\r
+      IPClose(socket);\r
+}\r
+\r
+\r
+IPSocket *FtpTransfer(uint32 ip, char *user, char *passwd, \r
+                      char *filename, uint8 *buf, int size, \r
+                      int send, void (*callback)(uint8 *data, int size))\r
+{\r
+   IPSocket *socket, *socketTransfer;\r
+   FtpInfo *info;\r
+   uint8 *ptr;\r
+   info = (FtpInfo*)malloc(sizeof(FtpInfo));\r
+   if(info == NULL)\r
+      return NULL;\r
+   strncpy(info->user, user, 80);\r
+   strncpy(info->passwd, passwd, 80);\r
+   strncpy(info->filename, filename, 80);\r
+   info->buf = buf;\r
+   info->size = size;\r
+   info->send = send;\r
+   info->bytes = 0;\r
+   info->state = 0;\r
+   info->port = 2000;\r
+   socketTransfer = IPOpen(IP_MODE_TCP, 0, info->port, FtpCallbackTransfer);\r
+   socketTransfer->userPtr = info;\r
+   socketTransfer->userFunc = callback;\r
+   socket = IPOpen(IP_MODE_TCP, ip, 21, FtpCallback);\r
+   socket->userPtr = info;\r
+   socket->userFunc = callback;\r
+   ptr = socket->headerSend;\r
+   info->ip = IPAddressSelf();\r
+   return socket;\r
+}\r
+\r
+\r
+//******************* TFTP Server ************************\r
+\r
+\r
+static void TftpdCallback(IPSocket *socket)\r
+{\r
+   unsigned char buf[512+4];\r
+   int bytes, blockNum;\r
+   FILE *file = (FILE*)socket->userPtr;\r
+   bytes = IPRead(socket, buf, sizeof(buf));\r
+   //printf("TfptdCallback bytes=%d\n", bytes);\r
+   if(bytes < 4 || buf[0])\r
+      return;\r
+   if(buf[1] == 1)  //RRQ = Read Request\r
+   {\r
+      if(file)\r
+         fclose(file);\r
+      file = fopen((char*)buf+2, "rb");\r
+      socket->userPtr = file;\r
+      if(file == NULL)\r
+      {\r
+         buf[0] = 0;\r
+         buf[1] = 5;   //ERROR\r
+         buf[2] = 0;\r
+         buf[3] = 0;\r
+         buf[4] = 'X'; //Error string\r
+         buf[5] = 0;\r
+         IPWrite(socket, buf, 6);\r
+         return;\r
+      }\r
+   }\r
+   if(buf[1] == 1 || buf[1] == 4) //ACK\r
+   {\r
+      if(file == NULL)\r
+         return;\r
+      if(buf[1] == 1)\r
+         blockNum = 0;\r
+      else\r
+         blockNum = (buf[2] << 8) | buf[3];\r
+      ++blockNum;\r
+      buf[0] = 0;\r
+      buf[1] = 3;  //DATA\r
+      buf[2] = (uint8)(blockNum >> 8);\r
+      buf[3] = (uint8)blockNum;\r
+      fseek(file, (blockNum-1)*512, 0);\r
+      bytes = fread(buf+4, 1, 512, file);\r
+      IPWrite(socket, buf, bytes+4);\r
+   }\r
+}\r
+\r
+\r
+void TftpdInit(void)\r
+{\r
+   IPSocket *socket;\r
+   socket = IPOpen(IP_MODE_UDP, 0, 69, TftpdCallback);\r
+}\r
+\r
+\r
+//******************* TFTP Client ************************\r
+\r
+\r
+static void TftpCallback(IPSocket *socket)\r
+{\r
+   unsigned char buf[512+4];\r
+   int bytes, blockNum, length;\r
+\r
+   bytes = IPRead(socket, buf, sizeof(buf));\r
+   if(bytes < 4 || buf[0])\r
+      return;\r
+   blockNum = (buf[2] << 8) | buf[3];\r
+   length = blockNum * 512 - 512 + bytes - 4;\r
+   //printf("TftpCallback(%d,%d)\n", buf[1], blockNum);\r
+   if(length > (int)socket->userData)\r
+   {\r
+      bytes -= length - (int)socket->userData;\r
+      length = (int)socket->userData;\r
+   }\r
+   if(buf[1] == 3) //DATA\r
+   {\r
+      memcpy((uint8*)socket->userPtr + blockNum * 512 - 512, buf+4, bytes-4);\r
+      buf[1] = 4; //ACK\r
+      IPWrite(socket, buf, 4);\r
+      if(bytes-4 < 512)\r
+      {\r
+         socket->userFunc(socket->userPtr, length);\r
+         IPClose(socket);\r
+      }\r
+   }\r
+}\r
+\r
+\r
+IPSocket *TftpTransfer(uint32 ip, char *filename, uint8 *buffer, int size,\r
+                       void (*callback)(uint8 *data, int bytes))\r
+{\r
+   IPSocket *socket;\r
+   uint8 buf[512+4];\r
+   int bytes;\r
+   socket = IPOpen(IP_MODE_UDP, ip, 69, TftpCallback);\r
+   socket->userPtr = buffer;\r
+   socket->userData = size;\r
+   socket->userFunc = callback;\r
+   buf[0] = 0;\r
+   buf[1] = 1; //read\r
+   strcpy((char*)buf+2, filename);\r
+   bytes = strlen(filename);\r
+   strcpy((char*)buf+bytes+3, "octet");\r
+   IPWrite(socket, buf, bytes+9);\r
+   return socket;\r
+}\r
+\r
+\r
+//******************* Telnet Server ************************\r
+\r
+#define COMMAND_BUFFER_SIZE 80\r
+#define COMMAND_BUFFER_COUNT 10\r
+static char CommandHistory[400];\r
+static char *CommandPtr[COMMAND_BUFFER_COUNT];\r
+static int CommandIndex;\r
+\r
+typedef void (*ConsoleFunc)(IPSocket *socket, char *argv[]);\r
+typedef struct {\r
+   char *name;\r
+   ConsoleFunc func;\r
+} TelnetFunc_t;\r
+static TelnetFunc_t *TelnetFuncList;\r
+\r
+\r
+static void TelnetServer(IPSocket *socket)\r
+{\r
+   uint8 buf[COMMAND_BUFFER_SIZE+4];\r
+   char bufOut[32];\r
+   int bytes, i, j, k, length, found;\r
+   char *ptr, *command = socket->userPtr;\r
+   char *argv[10];\r
+\r
+   if(socket->state > IP_TCP)\r
+      return;\r
+   for(;;)\r
+   {\r
+      bytes = IPRead(socket, buf, sizeof(buf)-1);\r
+      if(command == NULL)\r
+      {\r
+         socket->userPtr = command = (char*)malloc(COMMAND_BUFFER_SIZE);\r
+         if(command == NULL)\r
+         {\r
+            IPClose(socket);\r
+            return;\r
+         }\r
+         socket->timeoutReset = 300;\r
+         buf[0] = 255; //IAC\r
+         buf[1] = 251; //WILL\r
+         buf[2] = 3;   //suppress go ahead\r
+         buf[3] = 255; //IAC\r
+         buf[4] = 251; //WILL\r
+         buf[5] = 1;   //echo\r
+         strcpy((char*)buf+6, "Welcome to Plasma.\r\n-> ");\r
+         IPWrite(socket, buf, 6+23);\r
+         IPWriteFlush(socket);\r
+         command[0] = 0;\r
+         return;\r
+      }\r
+      if(bytes == 0)\r
+         return;\r
+      socket->dontFlush = 0;\r
+      buf[bytes] = 0;\r
+      length = (int)strlen(command);\r
+      for(j = 0; j < bytes; ++j)\r
+      {\r
+         if(buf[j] == 255)\r
+            return;\r
+         if(buf[j] == 8 || (buf[j] == 27 && buf[j+2] == 'D'))\r
+         {\r
+            if(buf[j] == 27)\r
+               j += 2;\r
+            if(length)\r
+            {\r
+               // Backspace\r
+               command[--length] = 0;\r
+               bufOut[0] = 8;\r
+               bufOut[1] = ' ';\r
+               bufOut[2] = 8;\r
+               IPWrite(socket, (uint8*)bufOut, 3);\r
+            }\r
+         }\r
+         else if(buf[j] == 27)\r
+         {\r
+            // Command History\r
+            if(buf[j+2] == 'A')\r
+            {\r
+               if(++CommandIndex > COMMAND_BUFFER_COUNT)\r
+                  CommandIndex = COMMAND_BUFFER_COUNT;\r
+            }\r
+            else if(buf[j+2] == 'B')\r
+            {\r
+               if(--CommandIndex < 0)\r
+                  CommandIndex = 0;\r
+            }\r
+            else \r
+               return;\r
+            bufOut[0] = 8;\r
+            bufOut[1] = ' ';\r
+            bufOut[2] = 8;\r
+            for(i = 0; i < length; ++i)\r
+               IPWrite(socket, (uint8*)bufOut, 3);\r
+            command[0] = 0;\r
+            if(CommandIndex && CommandPtr[CommandIndex-1])\r
+               strncat(command, CommandPtr[CommandIndex-1], COMMAND_BUFFER_SIZE-1);\r
+            length = (int)strlen(command);\r
+            IPWrite(socket, (uint8*)command, length);\r
+            j += 2;\r
+         }\r
+         else\r
+         {\r
+            if(buf[j] == 0)\r
+               buf[j] = '\n';  //Linux support\r
+            if(length < COMMAND_BUFFER_SIZE-4 || (length < \r
+               COMMAND_BUFFER_SIZE-2 && (buf[j] == '\r' || buf[j] == '\n')))\r
+            {\r
+               IPWrite(socket, buf+j, 1);\r
+               command[length] = buf[j];\r
+               command[++length] = 0;\r
+            }\r
+         }\r
+         ptr = strstr(command, "\r\n");\r
+         if(ptr)\r
+         {\r
+            // Save command in CommandHistory\r
+            ptr[0] = 0;\r
+            length = (int)strlen(command);\r
+            if(length == 0)\r
+            {\r
+               IPPrintf(socket, "-> ");\r
+               continue;\r
+            }\r
+            if(length < COMMAND_BUFFER_SIZE)\r
+            {\r
+               memmove(CommandHistory + length + 1, CommandHistory,\r
+                  sizeof(CommandHistory) - length - 1);\r
+               strcpy(CommandHistory, command);\r
+               CommandHistory[sizeof(CommandHistory)-1] = 0;\r
+               for(i = COMMAND_BUFFER_COUNT-2; i >= 0; --i)\r
+               {\r
+                  if(CommandPtr[i] == NULL || CommandPtr[i] + length + 1 >= \r
+                     CommandHistory + sizeof(CommandHistory))\r
+                     CommandPtr[i+1] = NULL;\r
+                  else\r
+                     CommandPtr[i+1] = CommandPtr[i] + length + 1;\r
+               }\r
+               CommandPtr[0] = CommandHistory;\r
+            }\r
+   \r
+            //Start command\r
+            for(i = 0; i < 10; ++i)\r
+               argv[i] = "";\r
+            i = 0;\r
+            argv[i++] = command;\r
+            for(ptr = command; *ptr && i < 10; ++ptr)\r
+            {\r
+               if(*ptr == ' ')\r
+               {\r
+                  *ptr = 0;\r
+                  argv[i++] = ptr + 1;\r
+               }\r
+            }\r
+            if(argv[0][0] == 0)\r
+            {\r
+               IPPrintf(socket, "-> ");\r
+               continue;\r
+            }\r
+            found = 0;\r
+            for(i = 0; TelnetFuncList[i].name; ++i)\r
+            {\r
+               if(strcmp(command, TelnetFuncList[i].name) == 0 &&\r
+                  TelnetFuncList[i].func)\r
+               {\r
+                  found = 1;\r
+                  for(k = 1; k < 10; ++k)\r
+                  {\r
+                     if(argv[k][0] == '>' && argv[k][1]) //stdout to file?\r
+                     {\r
+                        socket->fileOut = fopen(&argv[k][1], "a");\r
+                        argv[k] = "";\r
+                     }\r
+                     if(argv[k][0] == '<' && argv[k][1]) //stdin from file?\r
+                     {\r
+                        socket->fileIn = fopen(&argv[k][1], "r");\r
+                        argv[k] = "";\r
+                     }\r
+                  }\r
+                  TelnetFuncList[i].func(socket, argv);\r
+                  if(socket->fileOut)\r
+                  {\r
+                     fwrite("\r\n", 1, 2, socket->fileOut);\r
+                     fclose(socket->fileOut);\r
+                  }\r
+                  socket->fileOut = NULL;\r
+                  break;\r
+               }\r
+            }\r
+#ifdef DLL_SETUP\r
+            if(found == 0)\r
+            {\r
+               strcpy((char*)buf, "/flash/bin/");\r
+               strcat((char*)buf, argv[0]);\r
+               argv[0] = (char*)buf;\r
+               ConsoleRun(socket, argv);\r
+            }\r
+#endif\r
+            if(socket->state > IP_TCP)\r
+               return;\r
+            command[0] = 0;\r
+            length = 0;\r
+            CommandIndex = 0;\r
+            if(socket->dontFlush == 0)\r
+               IPPrintf(socket, "\r\n-> ");\r
+         } //command entered\r
+      } //bytes\r
+      IPWriteFlush(socket);\r
+   } \r
+}\r
+\r
+\r
+void TelnetInit(TelnetFunc_t *funcList)\r
+{\r
+   IPSocket *socket;\r
+   TelnetFuncList = funcList;\r
+   socket = IPOpen(IP_MODE_TCP, 0, 23, TelnetServer);\r
+}\r
+\r
+\r
+//******************* Console ************************\r
+\r
+#define STORAGE_SIZE 1024*64\r
+static uint8 *myStorage;\r
+static IPSocket *socketTelnet;\r
+static char storageFilename[60];\r
+\r
+\r
+static void ConsoleHelp(IPSocket *socket, char *argv[])\r
+{\r
+   char buf[200];\r
+   int i;\r
+   (void)argv;\r
+   strcpy(buf, "Commands: ");\r
+   for(i = 0; TelnetFuncList[i].name; ++i)\r
+   {\r
+      if(TelnetFuncList[i].func)\r
+      {\r
+         if(i)\r
+            strcat(buf, ", ");\r
+         strcat(buf, TelnetFuncList[i].name);\r
+      }\r
+   }\r
+   IPPrintf(socket, buf);\r
+}\r
+\r
+\r
+static void ConsoleExit(IPSocket *socket, char *argv[])\r
+{\r
+   free(argv[0]);\r
+   socket->userPtr = NULL;\r
+   IPClose(socket);\r
+}\r
+\r
+\r
+static void ConsoleCat(IPSocket *socket, char *argv[])\r
+{\r
+   FILE *file;\r
+   uint8 buf[200];\r
+   int bytes;\r
+\r
+   file = fopen(argv[1], "r");\r
+   if(file == NULL)\r
+      return;\r
+   for(;;)\r
+   {\r
+      bytes = fread(buf, 1, sizeof(buf), file);\r
+      if(bytes == 0)\r
+         break;\r
+      IPWrite(socket, buf, bytes);\r
+   }\r
+   fclose(file);\r
+}\r
+\r
+\r
+static void ConsoleCp(IPSocket *socket, char *argv[])\r
+{\r
+   FILE *fileIn, *fileOut;\r
+   uint8 buf[200];\r
+   int bytes;\r
+   (void)socket;\r
+\r
+   fileIn = fopen(argv[1], "r");\r
+   if(fileIn == NULL)\r
+      return;\r
+   fileOut = fopen(argv[2], "w");\r
+   if(fileOut)\r
+   {\r
+      for(;;)\r
+      {\r
+         bytes = fread(buf, 1, sizeof(buf), fileIn);\r
+         if(bytes == 0)\r
+            break;\r
+         fwrite(buf, 1, bytes, fileOut);\r
+      }\r
+      fclose(fileOut);\r
+   }\r
+   fclose(fileIn);\r
+}\r
+\r
+\r
+static void ConsoleRm(IPSocket *socket, char *argv[])\r
+{\r
+   (void)socket;\r
+   OS_fdelete(argv[1]);\r
+}\r
+\r
+\r
+static void ConsoleMkdir(IPSocket *socket, char *argv[])\r
+{\r
+   (void)socket;\r
+   OS_fmkdir(argv[1]);\r
+}\r
+\r
+\r
+static void ConsoleLs(IPSocket *socket, char *argv[])\r
+{\r
+   FILE *file;\r
+   char buf[200], buf2[80];\r
+   int bytes, width;\r
+\r
+   file = fopen(argv[1], "r");\r
+   if(file == NULL)\r
+      return;\r
+   width = 0;\r
+   for(;;)\r
+   {\r
+      bytes = OS_fdir(file, buf);\r
+      if(bytes)\r
+         break;\r
+      if(buf[0] == 255)\r
+         continue;\r
+      bytes = OS_flength(buf);\r
+      sprintf(buf2, "%s:%d                    ", buf, bytes);\r
+      bytes = strlen(buf2);\r
+      bytes -= bytes % 20;\r
+      buf2[bytes] = 0;\r
+      width += bytes;\r
+      if(width == 80)\r
+         --bytes;\r
+      if(width > 80)\r
+      {\r
+         IPPrintf(socket, "\n");\r
+         width = bytes;\r
+      }\r
+      IPPrintf(socket, "%s", buf2);\r
+   }\r
+   fclose(file);\r
+}\r
+\r
+\r
+#ifdef INCLUDE_FLASH\r
+static void ConsoleFlashErase(IPSocket *socket, char *argv[])\r
+{\r
+   int bytes;\r
+   (void)argv;\r
+   IPPrintf(socket, "\r\nErasing");\r
+   for(bytes = 1024*128; bytes < 1024*1024*16; bytes += 1024*128)\r
+   {\r
+      IPPrintf(socket, ".");\r
+      FlashErase(bytes);\r
+   }\r
+   IPPrintf(socket, "\r\nMust Reboot\r\n");\r
+   OS_ThreadSleep(OS_WAIT_FOREVER);\r
+}\r
+#endif\r
+\r
+\r
+static void ConsoleMath(IPSocket *socket, char *argv[])\r
+{\r
+   int v1, v2, ch;\r
+   if(argv[3][0] == 0)\r
+   {\r
+      IPPrintf(socket, "Usage: math <number> <operator> <value>\r\n");\r
+      return;\r
+   }\r
+   v1 = atoi(argv[1]);\r
+   ch = argv[2][0];\r
+   v2 = atoi(argv[3]);\r
+   if(ch == '+')\r
+      v1 += v2;\r
+   else if(ch == '-')\r
+      v1 -= v2;\r
+   else if(ch == '*')\r
+      v1 *= v2;\r
+   else if(ch == '/')\r
+   {\r
+      if(v2 != 0)\r
+         v1 /= v2;\r
+   }\r
+   IPPrintf(socket, "%d", v1);\r
+}\r
+\r
+\r
+static void PingCallback(IPSocket *socket)\r
+{\r
+   IPSocket *socket2 = socket->userPtr;\r
+   IPClose(socket);\r
+   if(socket2)\r
+      IPPrintf(socket2, "Ping Reply");\r
+   else\r
+      printf("Ping Reply\n");\r
+}\r
+\r
+\r
+static void DnsResultCallback(IPSocket *socket, uint32 ip, void *arg)\r
+{\r
+   char buf[COMMAND_BUFFER_SIZE];\r
+   IPSocket *socketTelnet = arg;\r
+   IPSocket *socketPing;\r
+   (void)socket;\r
+\r
+   sprintf(buf,  "ip=%d.%d.%d.%d\r\n", \r
+      (uint8)(ip >> 24), (uint8)(ip >> 16), (uint8)(ip >> 8), (uint8)ip);\r
+   IPPrintf(socketTelnet, buf);\r
+   socketPing = IPOpen(IP_MODE_PING, ip, 0, PingCallback);\r
+   socketPing->userPtr = socketTelnet;\r
+   buf[0] = 'A';\r
+   IPWrite(socketPing, (uint8*)buf, 1);\r
+}\r
+\r
+\r
+static void ConsolePing(IPSocket *socket, char *argv[])\r
+{\r
+   int ip0, ip1, ip2, ip3;\r
+\r
+   if('0' <= argv[1][0] && argv[1][0] <= '9')\r
+   {\r
+      sscanf(argv[1], "%d.%d.%d.%d", &ip0, &ip1, &ip2, &ip3);\r
+      ip0 = (ip0 << 24) | (ip1 << 16) | (ip2 << 8) | ip3;\r
+      DnsResultCallback(socket, ip0, socket);\r
+   }\r
+   else\r
+   {\r
+      IPResolve(argv[1], DnsResultCallback, socket);\r
+      IPPrintf(socket, "Sent DNS request");\r
+   }\r
+}\r
+\r
+\r
+static void ConsoleTransferDone(uint8 *data, int length)\r
+{\r
+   FILE *file;\r
+   IPPrintf(socketTelnet, "Transfer Done");\r
+   file = fopen(storageFilename, "w");\r
+   if(file)\r
+   {\r
+      fwrite(data, 1, length, file);\r
+      fclose(file);\r
+   }\r
+   if(myStorage)\r
+      free(myStorage);\r
+   myStorage = NULL;\r
+}\r
+\r
+\r
+static void ConsoleFtp(IPSocket *socket, char *argv[])\r
+{\r
+   int ip0, ip1, ip2, ip3;\r
+   if(argv[1][0] == 0)\r
+   {\r
+      IPPrintf(socket, "ftp #.#.#.# User Password File");\r
+      return;\r
+   }\r
+   sscanf(argv[1], "%d.%d.%d.%d", &ip0, &ip1, &ip2, &ip3);\r
+   ip0 = (ip0 << 24) | (ip1 << 16) | (ip2 << 8) | ip3;\r
+   socketTelnet = socket;\r
+   if(myStorage == NULL)\r
+      myStorage = (uint8*)malloc(STORAGE_SIZE);\r
+   if(myStorage == NULL)\r
+      return;\r
+   strcpy(storageFilename, argv[4]);\r
+   FtpTransfer(ip0, argv[2], argv[3], argv[4], myStorage, STORAGE_SIZE-1, \r
+      0, ConsoleTransferDone);\r
+}\r
+\r
+\r
+static void ConsoleTftp(IPSocket *socket, char *argv[])\r
+{\r
+   int ip0, ip1, ip2, ip3;\r
+   if(argv[1][0] == 0)\r
+   {\r
+      IPPrintf(socket, "tftp #.#.#.# File");\r
+      return;\r
+   }\r
+   sscanf(argv[1], "%d.%d.%d.%d", &ip0, &ip1, &ip2, &ip3);\r
+   ip0 = (ip0 << 24) | (ip1 << 16) | (ip2 << 8) | ip3;\r
+   socketTelnet = socket;\r
+   if(myStorage == NULL)\r
+      myStorage = (uint8*)malloc(STORAGE_SIZE);\r
+   if(myStorage == NULL)\r
+      return;\r
+   strcpy(storageFilename, argv[2]);\r
+   TftpTransfer(ip0, argv[2], myStorage, STORAGE_SIZE-1, ConsoleTransferDone);\r
+}\r
+\r
+\r
+static void ConsoleMkfile(IPSocket *socket, char *argv[])\r
+{\r
+   OS_FILE *file;\r
+   (void)argv;\r
+   file = fopen("myfile.txt", "w");\r
+   fwrite("Hello World!", 1, 12, file);\r
+   fclose(file);\r
+   IPPrintf(socket, "Created myfile.txt");\r
+}\r
+\r
+\r
+static void ConsoleUptime(IPSocket *socket, char *argv[])\r
+{\r
+   int days, hours, minutes, seconds;\r
+   (void)argv;\r
+   //ticks per sec = 25E6/2^18 = 95.36743 -> 10.48576 ms/tick\r
+   seconds = OS_ThreadTime() / 95;\r
+   minutes = seconds / 60 % 60;\r
+   hours = seconds / 3600 % 24;\r
+   days = seconds / 3600 / 24;\r
+   seconds %= 60;\r
+   IPPrintf(socket, "%d days %2d:%2d:%2d\n", days, hours, minutes, seconds);\r
+}\r
+\r
+\r
+static void ConsoleDump(IPSocket *socket, char *argv[])\r
+{\r
+   FILE *fileIn;\r
+   uint8 buf[16];\r
+   int bytes, i, j;\r
+\r
+   fileIn = fopen(argv[1], "r");\r
+   if(fileIn == NULL)\r
+      return;\r
+   for(j = 0; j < 1024*1024*16; j += 16)\r
+   {\r
+      bytes = fread(buf, 1, 16, fileIn);\r
+      if(bytes == 0)\r
+         break;\r
+      IPPrintf(socket, "%8x ", j);\r
+      for(i = 0; i < bytes; ++i)\r
+         IPPrintf(socket, "%2x ", buf[i]);\r
+      for( ; i < 16; ++i)\r
+         IPPrintf(socket, "   ");\r
+      for(i = 0; i < bytes; ++i)\r
+      {\r
+         if(isprint(buf[i]))\r
+            IPPrintf(socket, "%c", buf[i]);\r
+         else\r
+            IPPrintf(socket, ".");\r
+      }\r
+      IPPrintf(socket, "\n");\r
+   }\r
+   fclose(fileIn);\r
+}\r
+\r
+\r
+static void ConsoleGrep(IPSocket *socket, char *argv[])\r
+{\r
+   FILE *fileIn;\r
+   char buf[200];\r
+   int bytes;\r
+   char *ptr, *ptrEnd;\r
+\r
+   if(argv[1][0] == 0 || argv[2][0] == 0)\r
+   {\r
+      IPPrintf(socket, "Usage: grep pattern file\n");\r
+      return;\r
+   }\r
+   fileIn = fopen(argv[2], "r");\r
+   if(fileIn == NULL)\r
+      return;\r
+   bytes = 0;\r
+   for(;;)\r
+   {\r
+      bytes += fread(buf + bytes, 1, sizeof(buf) - bytes - 1, fileIn);\r
+      if(bytes == 0)\r
+         break;\r
+      buf[bytes] = 0;\r
+      ptrEnd = strstr(buf, "\r");\r
+      if(ptrEnd == NULL)\r
+         ptrEnd = strstr(buf, "\n");\r
+      if(ptrEnd)\r
+      {\r
+         *ptrEnd = 0;\r
+         if(*++ptrEnd == '\n')\r
+            ++ptrEnd;\r
+      }\r
+      ptr = strstr(buf, argv[1]);\r
+      if(ptr)\r
+         IPPrintf(socket, "%s\n", buf);\r
+      if(ptrEnd)\r
+      {\r
+         bytes = strlen(ptrEnd);\r
+         memcpy(buf, ptrEnd, bytes);\r
+      }\r
+      else\r
+      {\r
+         bytes = 0;\r
+      }\r
+   }\r
+   fclose(fileIn);\r
+}\r
+\r
+\r
+#ifdef DLL_SETUP\r
+#include "dll.h"\r
+\r
+static void ConsoleRun(IPSocket *socket, char *argv[])\r
+{\r
+   FILE *file;\r
+   int bytes, i;\r
+   uint8 code[128];\r
+   DllFunc funcPtr;\r
+   char *command, *ptr;\r
+\r
+   if(strcmp(argv[0], "run") == 0)\r
+      ++argv;\r
+   file = fopen(argv[0], "r");\r
+   if(file == NULL)\r
+   {\r
+      IPPrintf(socket, "Can't find %s", argv[0]);\r
+      return;\r
+   }\r
+\r
+   bytes = fread(code, 1, sizeof(code), file);  //load first 128 bytes\r
+   if(code[0] >= ' ')\r
+   {\r
+      socket->fileIn = file;       //script file\r
+      fseek(file, 0, 0);\r
+      return;\r
+   }\r
+\r
+   funcPtr = (DllFunc)code;\r
+   ptr = funcPtr(NULL);            //determine load address\r
+\r
+   memcpy(ptr, code, bytes);       //copy to correct address\r
+   bytes += fread(ptr + bytes, 1, 1024*1024*8, file);\r
+   fclose(file);\r
+   printf("address=0x%x bytes=%d\n", (int)ptr, bytes);\r
+   funcPtr = (DllFunc)ptr;\r
+   funcPtr = (DllFunc)funcPtr(DllFuncList);  //initialize DLL, find Start()\r
+\r
+   //Register new command\r
+   command = argv[0];\r
+   for(;;)\r
+   {\r
+      ptr = strstr(command, "/");\r
+      if(ptr == NULL)\r
+         break;\r
+      command = ptr + 1;\r
+   }\r
+   for(i = 0; TelnetFuncList[i].name; ++i)\r
+   {\r
+      if(TelnetFuncList[i].name[0] == 0 ||\r
+         strcmp(TelnetFuncList[i].name, command) == 0)\r
+      {\r
+         TelnetFuncList[i].name = (char*)malloc(40);\r
+         strcpy(TelnetFuncList[i].name, command);\r
+         TelnetFuncList[i].func = (ConsoleFunc)funcPtr;\r
+         break;\r
+      }\r
+   }\r
+\r
+   socket->userFunc = socket->funcPtr;\r
+   funcPtr(socket, argv);\r
+}\r
+\r
+\r
+typedef struct NameValue_t {\r
+   struct NameValue_t *next;\r
+   void *value;\r
+   char name[1];\r
+} NameValue_t;\r
+\r
+//Find the value associated with the name\r
+void *IPNameValue(const char *name, void *value)\r
+{\r
+   static NameValue_t *head;\r
+   NameValue_t *node;\r
+   for(node = head; node; node = node->next)\r
+   {\r
+      if(strcmp(node->name, name) == 0)\r
+         break;\r
+   }\r
+   if(node == NULL)\r
+   {\r
+      node = (NameValue_t*)malloc(sizeof(NameValue_t) + (int)strlen(name));\r
+      if(node == NULL)\r
+         return NULL;\r
+      strcpy(node->name, name);\r
+      node->value = value;\r
+      node->next = head;\r
+      head = node;\r
+   }\r
+   if(value)\r
+      node->value = value;\r
+   return node->value;\r
+}\r
+#endif\r
+\r
+\r
+#ifdef EDIT_FILE\r
+extern void EditFile(IPSocket *socket, char *argv[]);\r
+#endif\r
+\r
+static TelnetFunc_t MyFuncs[] = { \r
+   {"cat", ConsoleCat},\r
+   {"cp", ConsoleCp},\r
+   {"dump", ConsoleDump},\r
+   {"exit", ConsoleExit},\r
+#ifdef INCLUDE_FLASH\r
+   {"flashErase", ConsoleFlashErase},\r
+#endif\r
+   {"ftp", ConsoleFtp},\r
+   {"grep", ConsoleGrep},\r
+   {"help", ConsoleHelp},\r
+   {"ls", ConsoleLs},\r
+   {"math", ConsoleMath},\r
+   {"mkdir", ConsoleMkdir},\r
+   {"mkfile", ConsoleMkfile},\r
+   {"ping", ConsolePing},\r
+   {"rm", ConsoleRm},\r
+   {"tftp", ConsoleTftp},\r
+   {"uptime", ConsoleUptime},\r
+#ifdef DLL_SETUP\r
+   {"run", ConsoleRun},\r
+#endif\r
+#ifdef EDIT_FILE\r
+   {"edit", EditFile},\r
+#endif\r
+   {"", NULL},\r
+   {"", NULL},\r
+   {"", NULL},\r
+   {"", NULL},\r
+   {"", NULL},\r
+   {"", NULL},\r
+   {"", NULL},\r
+   {"", NULL},\r
+   {"", NULL},\r
+   {"", NULL},\r
+   {"", NULL},\r
+   {NULL, NULL}\r
+};\r
+\r
+\r
+void ConsoleInit(void)\r
+{\r
+   FtpdInit(1);\r
+   TftpdInit();\r
+   TelnetInit(MyFuncs);\r
+}\r
diff --git a/kernel/os_stubs.c b/kernel/os_stubs.c
new file mode 100644 (file)
index 0000000..606dab1
--- /dev/null
@@ -0,0 +1,71 @@
+/*--------------------------------------------------------------------
+ * TITLE: OS stubs
+ * AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
+ * DATE CREATED: 2/18/08
+ * FILENAME: os_stubs.c
+ * PROJECT: Plasma CPU core
+ * COPYRIGHT: Software placed into the public domain by the author.
+ *    Software 'as is' without warranty.  Author liable for nothing.
+ * DESCRIPTION:
+ *--------------------------------------------------------------------*/
+#include <stdlib.h>
+#include "plasma.h"
+#include "rtos.h"
+
+unsigned char *flash;
+int beenInit;
+
+
+void FlashRead(uint16 *dst, uint32 byteOffset, int bytes)
+{
+   if(beenInit == 0)
+   {
+      beenInit = 1;
+      flash = (unsigned char*)malloc(1024*1024*16);
+      memset(flash, 0xff, sizeof(flash));
+   }
+   memcpy(dst, flash+byteOffset, bytes);
+}
+
+
+void FlashWrite(uint16 *src, uint32 byteOffset, int bytes)
+{
+   memcpy(flash+byteOffset, src, bytes);
+}
+
+
+void FlashErase(uint32 byteOffset)
+{
+   memset(flash+byteOffset, 0xff, 1024*128);
+}
+
+
+//Stub out RTOS functions
+void UartPrintfCritical(const char *format, ...) {(void)format;}
+uint32 OS_AsmInterruptEnable(uint32 state)   {(void)state; return 0;}
+void OS_Assert(void)                         {}
+OS_Thread_t *OS_ThreadSelf(void)             {return NULL;}
+void OS_ThreadSleep(int ticks)               {(void)ticks;}
+uint32 OS_ThreadTime(void)                   {return 0;}
+OS_Mutex_t *OS_MutexCreate(const char *name) {(void)name; return NULL; }
+void OS_MutexDelete(OS_Mutex_t *semaphore)   {(void)semaphore;}
+void OS_MutexPend(OS_Mutex_t *semaphore)     {(void)semaphore;}
+void OS_MutexPost(OS_Mutex_t *semaphore)     {(void)semaphore;}
+
+OS_MQueue_t *OS_MQueueCreate(const char *name,
+                             int messageCount,
+                             int messageBytes)
+{(void)name;(void)messageCount;(void)messageBytes; return NULL;}
+
+void OS_MQueueDelete(OS_MQueue_t *mQueue)    {(void)mQueue;}
+
+int OS_MQueueSend(OS_MQueue_t *mQueue, void *message) 
+{(void)mQueue;(void)message; return 0;}
+
+int OS_MQueueGet(OS_MQueue_t *mQueue, void *message, int ticks)
+{(void)mQueue;(void)message;(void)ticks; return 0;}
+
+void OS_Job(void (*funcPtr)(), void *arg0, void *arg1, void *arg2)
+{funcPtr(arg0, arg1, arg2);}
+
+
diff --git a/kernel/rtos.c b/kernel/rtos.c
new file mode 100644 (file)
index 0000000..3c03538
--- /dev/null
@@ -0,0 +1,1508 @@
+/*--------------------------------------------------------------------
+ * TITLE: Plasma Real Time Operating System
+ * AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
+ * DATE CREATED: 12/17/05
+ * FILENAME: rtos.c
+ * PROJECT: Plasma CPU core
+ * COPYRIGHT: Software placed into the public domain by the author.
+ *    Software 'as is' without warranty.  Author liable for nothing.
+ * DESCRIPTION:
+ *    Plasma Real Time Operating System
+ *    Fully pre-emptive RTOS with support for:
+ *       Heaps, Threads, Semaphores, Mutexes, Message Queues, and Timers.
+ *    This file tries to be hardware independent except for calls to:
+ *       MemoryRead() and MemoryWrite() for interrupts.
+ *    Partial support for multiple CPUs using symmetric multiprocessing.
+ *--------------------------------------------------------------------*/
+#include "plasma.h"
+#include "rtos.h"
+
+#define HEAP_MAGIC 0x1234abcd
+#define THREAD_MAGIC 0x4321abcd
+#define SEM_RESERVED_COUNT 2
+#define INFO_COUNT 4
+#define HEAP_COUNT 8
+
+
+/*************** Structures ***************/
+#ifdef WIN32
+   #define setjmp _setjmp
+   //x86 registers
+   typedef struct jmp_buf2 {  
+      uint32 Ebp, Ebx, Edi, Esi, sp, pc, extra[10];
+   } jmp_buf2;
+#elif defined(ARM_CPU)
+   //ARM registers
+   typedef struct jmp_buf2 {  
+      uint32 r[13], sp, lr, pc, cpsr, extra[5];
+   } jmp_buf2;
+#else  
+   //Plasma registers
+   typedef struct jmp_buf2 {  
+      uint32 s[9], gp, sp, pc;
+   } jmp_buf2;
+#endif
+
+typedef struct HeapNode_s {
+   struct HeapNode_s *next;
+   int size;
+} HeapNode_t;
+
+struct OS_Heap_s {
+   uint32 magic;
+   const char *name;
+   OS_Semaphore_t *semaphore;
+   HeapNode_t *available;
+   HeapNode_t base;
+   struct OS_Heap_s *alternate;
+};
+//typedef struct OS_Heap_s OS_Heap_t;
+
+typedef enum {
+   THREAD_PEND    = 0,       //Thread in semaphore's linked list
+   THREAD_READY   = 1,       //Thread in ThreadHead linked list
+   THREAD_RUNNING = 2        //Thread == ThreadCurrent[cpu]
+} OS_ThreadState_e;
+
+struct OS_Thread_s {
+   const char *name;         //Name of thread
+   OS_ThreadState_e state;   //Pending, ready, or running
+   int cpuIndex;             //Which CPU is running the thread
+   int cpuLock;              //Lock the thread to a specific CPU
+   jmp_buf env;              //Registers saved during context swap
+   OS_FuncPtr_t funcPtr;     //First function called
+   void *arg;                //Argument to first function called
+   uint32 priority;          //Priority of thread (0=low, 255=high)
+   uint32 ticksTimeout;      //Tick value when semaphore pend times out
+   void *info[INFO_COUNT];   //User storage
+   OS_Semaphore_t *semaphorePending;  //Semaphore thread is blocked on
+   int returnCode;           //Return value from semaphore pend
+   uint32 processId;         //Process ID if using MMU
+   OS_Heap_t *heap;          //Heap used if no heap specified
+   struct OS_Thread_s *next; //Linked list of threads by priority
+   struct OS_Thread_s *prev;  
+   struct OS_Thread_s *nextTimeout; //Linked list of threads by timeout
+   struct OS_Thread_s *prevTimeout; 
+   uint32 magic[1];          //Bottom of stack to detect stack overflow
+};
+//typedef struct OS_Thread_s OS_Thread_t;
+
+struct OS_Semaphore_s {
+   const char *name;
+   struct OS_Thread_s *threadHead; //threads pending on semaphore
+   int count;
+};
+//typedef struct OS_Semaphore_s OS_Semaphore_t;
+
+struct OS_Mutex_s {
+   OS_Semaphore_t *semaphore;
+   OS_Thread_t *thread;
+   int count;
+}; 
+//typedef struct OS_Mutex_s OS_Mutex_t;
+
+struct OS_MQueue_s {
+   const char *name;
+   OS_Semaphore_t *semaphore;
+   int count, size, used, read, write;
+};
+//typedef struct OS_MQueue_s OS_MQueue_t;
+
+struct OS_Timer_s {
+   const char *name;
+   struct OS_Timer_s *next, *prev;
+   uint32 ticksTimeout;
+   uint32 ticksRestart;
+   int active;
+   OS_TimerFuncPtr_t callback;
+   OS_MQueue_t *mqueue;
+   uint32 info;
+}; 
+//typedef struct OS_Timer_s OS_Timer_t;
+
+
+/*************** Globals ******************/
+static OS_Heap_t *HeapArray[HEAP_COUNT];
+static int InterruptInside[OS_CPU_COUNT];
+static int ThreadNeedReschedule[OS_CPU_COUNT];
+static OS_Thread_t *ThreadCurrent[OS_CPU_COUNT];  //Currently running thread(s)
+static OS_Thread_t *ThreadHead;   //Linked list of threads sorted by priority
+static OS_Thread_t *TimeoutHead;  //Linked list of threads sorted by timeout
+static int ThreadSwapEnabled;
+static uint32 ThreadTime;         //Number of ~10ms ticks since reboot
+static void *NeedToFree;          //Closed but not yet freed thread
+static OS_Semaphore_t SemaphoreReserved[SEM_RESERVED_COUNT];
+static OS_Semaphore_t *SemaphoreSleep;
+static OS_Semaphore_t *SemaphoreRelease;
+static OS_Semaphore_t *SemaphoreLock;
+static OS_Semaphore_t *SemaphoreTimer;
+static OS_Timer_t *TimerHead;     //Linked list of timers sorted by timeout
+static OS_FuncPtr_t Isr[32];
+
+
+/***************** Heap *******************/
+/******************************************/
+OS_Heap_t *OS_HeapCreate(const char *name, void *memory, uint32 size)
+{
+   OS_Heap_t *heap;
+
+   assert(((uint32)memory & 3) == 0);
+   heap = (OS_Heap_t*)memory;
+   heap->magic = HEAP_MAGIC;
+   heap->name = name;
+   heap->semaphore = OS_SemaphoreCreate(name, 1);
+   heap->available = (HeapNode_t*)(heap + 1);
+   heap->available->next = &heap->base;
+   heap->available->size = (size - sizeof(OS_Heap_t)) / sizeof(HeapNode_t);
+   heap->base.next = heap->available;
+   heap->base.size = 0;
+   return heap;
+}
+
+
+/******************************************/
+void OS_HeapDestroy(OS_Heap_t *heap)
+{
+   OS_SemaphoreDelete(heap->semaphore);
+}
+
+
+/******************************************/
+//Modified from Kernighan & Ritchie "The C Programming Language"
+void *OS_HeapMalloc(OS_Heap_t *heap, int bytes)
+{
+   HeapNode_t *node, *prevp;
+   int nunits;
+
+   if(heap == NULL && OS_ThreadSelf())
+      heap = OS_ThreadSelf()->heap;
+   if((uint32)heap < HEAP_COUNT)
+      heap = HeapArray[(int)heap];
+   nunits = (bytes + sizeof(HeapNode_t) - 1) / sizeof(HeapNode_t) + 1;
+   OS_SemaphorePend(heap->semaphore, OS_WAIT_FOREVER);
+   prevp = heap->available;
+   for(node = prevp->next; ; prevp = node, node = node->next)
+   {
+      if(node->size >= nunits)       //Big enough?
+      {
+         if(node->size == nunits)    //Exactly
+            prevp->next = node->next;
+         else
+         {                           //Allocate tail end
+            node->size -= nunits;
+            node += node->size;
+            node->size = nunits;
+         }
+         heap->available = prevp;
+         node->next = (HeapNode_t*)heap;
+         OS_SemaphorePost(heap->semaphore);
+         return (void*)(node + 1);
+      }
+      if(node == heap->available)   //Wrapped around free list
+      {
+         OS_SemaphorePost(heap->semaphore);
+         if(heap->alternate)
+            return OS_HeapMalloc(heap->alternate, bytes);
+         return NULL;
+      }
+   }
+}
+
+
+/******************************************/
+//Modified from K&R
+void OS_HeapFree(void *block)
+{
+   OS_Heap_t *heap;
+   HeapNode_t *bp, *node;
+
+   assert(block);
+   bp = (HeapNode_t*)block - 1;   //point to block header
+   heap = (OS_Heap_t*)bp->next;
+   assert(heap->magic == HEAP_MAGIC);
+   if(heap->magic != HEAP_MAGIC)
+      return;
+   OS_SemaphorePend(heap->semaphore, OS_WAIT_FOREVER);
+   for(node = heap->available; !(node < bp && bp < node->next); node = node->next)
+   {
+      if(node >= node->next && (bp > node || bp < node->next))
+         break;               //freed block at start or end of area
+   }
+
+   if(bp + bp->size == node->next)   //join to upper
+   {
+      bp->size += node->next->size;
+      bp->next = node->next->next;
+   }
+   else
+   {
+      bp->next = node->next;
+   }
+
+   if(node + node->size == bp)       //join to lower
+   {
+      node->size += bp->size;
+      node->next = bp->next;
+   }
+   else
+      node->next = bp;
+   heap->available = node;
+   OS_SemaphorePost(heap->semaphore);
+}
+
+
+/******************************************/
+void OS_HeapAlternate(OS_Heap_t *heap, OS_Heap_t *alternate)
+{
+   heap->alternate = alternate;
+}
+
+
+/******************************************/
+void OS_HeapRegister(void *index, OS_Heap_t *heap)
+{
+   if((uint32)index < HEAP_COUNT)
+      HeapArray[(int)index] = heap;
+}
+
+
+
+/***************** Thread *****************/
+/******************************************/
+//Linked list of threads sorted by priority
+//The listed list is either ThreadHead (ready to run threads not including
+//the currently running thread) or a list of threads waiting on a semaphore.
+//Must be called with interrupts disabled
+static void OS_ThreadPriorityInsert(OS_Thread_t **head, OS_Thread_t *thread)
+{
+   OS_Thread_t *node, *prev;
+
+   prev = NULL;
+   for(node = *head; node; node = node->next)
+   {
+      if(node->priority < thread->priority)
+         break;
+      prev = node;
+   }
+
+   if(prev == NULL)
+   {
+      thread->next = *head;
+      thread->prev = NULL;
+      if(*head)
+         (*head)->prev = thread;
+      *head = thread;
+   }
+   else
+   {
+      if(prev->next)
+         prev->next->prev = thread;
+      thread->next = prev->next;
+      thread->prev = prev;
+      prev->next = thread;
+   }
+   assert(ThreadHead);
+   thread->state = THREAD_READY;
+}
+
+
+/******************************************/
+//Must be called with interrupts disabled
+static void OS_ThreadPriorityRemove(OS_Thread_t **head, OS_Thread_t *thread)
+{
+   assert(thread->magic[0] == THREAD_MAGIC);  //check stack overflow
+   if(thread->prev == NULL)
+      *head = thread->next;
+   else
+      thread->prev->next = thread->next;
+   if(thread->next)
+      thread->next->prev = thread->prev;
+   thread->next = NULL;
+   thread->prev = NULL;
+}
+
+
+/******************************************/
+//Linked list of threads sorted by timeout value
+//Must be called with interrupts disabled
+static void OS_ThreadTimeoutInsert(OS_Thread_t *thread)
+{
+   OS_Thread_t *node, *prev;
+   int diff;
+
+   prev = NULL;
+   for(node = TimeoutHead; node; node = node->nextTimeout)
+   {
+      diff = thread->ticksTimeout - node->ticksTimeout;
+      if(diff <= 0)
+         break;
+      prev = node;
+   }
+
+   if(prev == NULL)
+   {
+      thread->nextTimeout = TimeoutHead;
+      thread->prevTimeout = NULL;
+      if(TimeoutHead)
+         TimeoutHead->prevTimeout = thread;
+      TimeoutHead = thread;
+   }
+   else
+   {
+      if(prev->nextTimeout)
+         prev->nextTimeout->prevTimeout = thread;
+      thread->nextTimeout = prev->nextTimeout;
+      thread->prevTimeout = prev;
+      prev->nextTimeout = thread;
+   }
+}
+
+
+/******************************************/
+//Must be called with interrupts disabled
+static void OS_ThreadTimeoutRemove(OS_Thread_t *thread)
+{
+   if(thread->prevTimeout == NULL && TimeoutHead != thread)
+      return;         //not in list
+   if(thread->prevTimeout == NULL)
+      TimeoutHead = thread->nextTimeout;
+   else
+      thread->prevTimeout->nextTimeout = thread->nextTimeout;
+   if(thread->nextTimeout)
+      thread->nextTimeout->prevTimeout = thread->prevTimeout;
+   thread->nextTimeout = NULL;
+   thread->prevTimeout = NULL;
+}
+
+
+/******************************************/
+//Loads highest priority thread from the ThreadHead linked list
+//The currently running thread isn't in the ThreadHead list
+//Must be called with interrupts disabled
+static void OS_ThreadReschedule(int roundRobin)
+{
+   OS_Thread_t *threadNext, *threadCurrent;
+   int rc, cpuIndex = OS_CpuIndex();
+
+   if(ThreadSwapEnabled == 0 || InterruptInside[cpuIndex])
+   {
+      ThreadNeedReschedule[cpuIndex] |= 2 + roundRobin;  //Reschedule later
+      return;
+   }\r
+   ThreadNeedReschedule[cpuIndex] = 0;
+
+   //Determine which thread should run
+   threadNext = ThreadHead;
+   while(threadNext && threadNext->cpuLock != -1 && 
+         threadNext->cpuLock != cpuIndex)
+      threadNext = threadNext->next;         //Skip CPU locked threads
+   if(threadNext == NULL)
+      return;
+   threadCurrent = ThreadCurrent[cpuIndex];
+
+   if(threadCurrent == NULL || 
+      threadCurrent->state == THREAD_PEND ||
+      threadCurrent->priority < threadNext->priority ||
+      (roundRobin && threadCurrent->priority == threadNext->priority))
+   {
+      //Swap threads
+      ThreadCurrent[cpuIndex] = threadNext;
+      if(threadCurrent)
+      {
+         assert(threadCurrent->magic[0] == THREAD_MAGIC); //check stack overflow
+         if(threadCurrent->state == THREAD_RUNNING)
+            OS_ThreadPriorityInsert(&ThreadHead, threadCurrent);
+         rc = setjmp(threadCurrent->env);  //ANSI C call to save registers
+         if(rc)
+            return;  //Returned from longjmp()
+      }
+
+      //Remove the new running thread from the ThreadHead linked list
+      threadNext = ThreadCurrent[OS_CpuIndex()]; //removed warning
+      assert(threadNext->state == THREAD_READY);
+      OS_ThreadPriorityRemove(&ThreadHead, threadNext); 
+      threadNext->state = THREAD_RUNNING;               
+      threadNext->cpuIndex = OS_CpuIndex();
+      longjmp(threadNext->env, 1);         //ANSI C call to restore registers
+   }
+}
+
+
+/******************************************/
+void OS_ThreadCpuLock(OS_Thread_t *thread, int cpuIndex)
+{
+   thread->cpuLock = cpuIndex;
+   if(thread == OS_ThreadSelf() && cpuIndex != (int)OS_CpuIndex())
+      OS_ThreadSleep(1);
+}
+
+
+/******************************************/
+static void OS_ThreadInit(void *arg)
+{
+   uint32 cpuIndex = OS_CpuIndex();
+   (void)arg;
+
+   OS_CriticalEnd(1);
+   ThreadCurrent[cpuIndex]->funcPtr(ThreadCurrent[cpuIndex]->arg);
+   OS_ThreadExit();
+}
+
+
+/******************************************/
+//Stops warning "argument X might be clobbered by `longjmp'"
+static void OS_ThreadRegsInit(jmp_buf env)
+{
+   setjmp(env); //ANSI C call to save registers
+}
+
+
+/******************************************/
+OS_Thread_t *OS_ThreadCreate(const char *name,
+                             OS_FuncPtr_t funcPtr, 
+                             void *arg, 
+                             uint32 priority, 
+                             uint32 stackSize)
+{
+   OS_Thread_t *thread;
+   uint8 *stack;
+   jmp_buf2 *env;
+   uint32 state;
+
+   OS_SemaphorePend(SemaphoreRelease, OS_WAIT_FOREVER);
+   if(NeedToFree)
+      OS_HeapFree(NeedToFree);
+   NeedToFree = NULL;
+   OS_SemaphorePost(SemaphoreRelease);
+
+   if(stackSize == 0)
+      stackSize = STACK_SIZE_DEFAULT;
+   if(stackSize < STACK_SIZE_MINIMUM)
+      stackSize = STACK_SIZE_MINIMUM;
+   thread = (OS_Thread_t*)OS_HeapMalloc(NULL, sizeof(OS_Thread_t) + stackSize);
+   assert(thread);
+   if(thread == NULL)
+      return NULL;
+   memset(thread, 0, sizeof(OS_Thread_t));
+   stack = (uint8*)(thread + 1);
+   memset(stack, 0xcd, stackSize);
+
+   thread->name = name;
+   thread->state = THREAD_READY;
+   thread->cpuLock = -1;
+   thread->funcPtr = funcPtr;
+   thread->arg = arg;
+   thread->priority = priority;
+   thread->semaphorePending = NULL;
+   thread->returnCode = 0;
+   if(OS_ThreadSelf())
+   {
+      thread->processId = OS_ThreadSelf()->processId;
+      thread->heap = OS_ThreadSelf()->heap;
+   }
+   else
+   {
+      thread->processId = 0;
+      thread->heap = NULL;
+   }
+   thread->next = NULL;
+   thread->prev = NULL;
+   thread->nextTimeout = NULL;
+   thread->prevTimeout = NULL;
+   thread->magic[0] = THREAD_MAGIC;
+
+   OS_ThreadRegsInit(thread->env);
+   env = (jmp_buf2*)thread->env;
+   env->sp = (uint32)stack + stackSize - 24; //minimum stack frame size
+   env->pc = (uint32)OS_ThreadInit;
+
+   //Add thread to linked list of ready to run threads
+   state = OS_CriticalBegin();
+   OS_ThreadPriorityInsert(&ThreadHead, thread);
+   OS_ThreadReschedule(0);                   //run highest priority thread
+   OS_CriticalEnd(state);
+   return thread;
+}
+
+
+/******************************************/
+void OS_ThreadExit(void)
+{
+   uint32 state, cpuIndex = OS_CpuIndex();
+
+   for(;;)
+   {
+      //Free the memory for closed but not yet freed threads
+      OS_SemaphorePend(SemaphoreRelease, OS_WAIT_FOREVER);
+      if(NeedToFree)
+         OS_HeapFree(NeedToFree);
+      NeedToFree = NULL;
+      OS_SemaphorePost(SemaphoreRelease);
+
+      state = OS_CriticalBegin();
+      if(NeedToFree)
+      {
+         OS_CriticalEnd(state);
+         continue;
+      }
+      ThreadCurrent[cpuIndex]->state = THREAD_PEND;
+      NeedToFree = ThreadCurrent[cpuIndex];
+      OS_ThreadReschedule(0);
+      OS_CriticalEnd(state);
+   }
+}
+
+
+/******************************************/
+//Return currently running thread
+OS_Thread_t *OS_ThreadSelf(void)
+{
+   return ThreadCurrent[OS_CpuIndex()];
+}
+
+
+/******************************************/
+//Sleep for ~10 msecs ticks
+void OS_ThreadSleep(int ticks)
+{
+   OS_SemaphorePend(SemaphoreSleep, ticks);
+}
+
+
+/******************************************/
+//Return the number of ~10 msecs ticks since reboot
+uint32 OS_ThreadTime(void)
+{
+   return ThreadTime;
+}
+
+
+/******************************************/
+//Save thread unique values
+void OS_ThreadInfoSet(OS_Thread_t *thread, uint32 index, void *Info)
+{
+   if(index < INFO_COUNT)
+      thread->info[index] = Info;
+}
+
+
+/******************************************/
+void *OS_ThreadInfoGet(OS_Thread_t *thread, uint32 index)
+{
+   if(index < INFO_COUNT)
+      return thread->info[index];
+   return NULL;
+}
+
+
+/******************************************/
+uint32 OS_ThreadPriorityGet(OS_Thread_t *thread)
+{
+   return thread->priority;
+}
+
+
+/******************************************/
+void OS_ThreadPrioritySet(OS_Thread_t *thread, uint32 priority)
+{
+   uint32 state;
+   state = OS_CriticalBegin();
+   thread->priority = priority;
+   if(thread->state == THREAD_READY)
+   {
+      OS_ThreadPriorityRemove(&ThreadHead, thread);
+      OS_ThreadPriorityInsert(&ThreadHead, thread);
+      OS_ThreadReschedule(0);
+   }
+   OS_CriticalEnd(state);
+}
+
+
+/******************************************/
+void OS_ThreadProcessId(OS_Thread_t *thread, uint32 processId, OS_Heap_t *heap)
+{
+   thread->processId = processId;
+   thread->heap = heap;
+}
+
+
+/******************************************/
+//Must be called with interrupts disabled every ~10 msecs
+//Will wake up threads that have timed out waiting on a semaphore
+void OS_ThreadTick(void *Arg)
+{
+   OS_Thread_t *thread;
+   OS_Semaphore_t *semaphore;
+   int diff;
+   (void)Arg;
+
+   ++ThreadTime;         //Number of ~10 msec ticks since reboot
+   while(TimeoutHead)
+   {
+      thread = TimeoutHead;
+      diff = ThreadTime - thread->ticksTimeout;
+      if(diff < 0)
+         break;
+
+      //The thread has timed out waiting for a semaphore
+      OS_ThreadTimeoutRemove(thread);
+      semaphore = thread->semaphorePending;
+      ++semaphore->count;
+      thread->semaphorePending = NULL;
+      thread->returnCode = -1;
+      OS_ThreadPriorityRemove(&semaphore->threadHead, thread);
+      OS_ThreadPriorityInsert(&ThreadHead, thread);
+   }
+   OS_ThreadReschedule(1);    //Run highest priority thread
+}
+
+
+
+/***************** Semaphore **************/
+/******************************************/
+//Create a counting semaphore
+OS_Semaphore_t *OS_SemaphoreCreate(const char *name, uint32 count)
+{
+   OS_Semaphore_t *semaphore;
+   static int semCount = 0;
+
+   if(semCount < SEM_RESERVED_COUNT)
+      semaphore = &SemaphoreReserved[semCount++];  //Heap not ready yet
+   else
+      semaphore = (OS_Semaphore_t*)OS_HeapMalloc(HEAP_SYSTEM, sizeof(OS_Semaphore_t));
+   assert(semaphore);
+   if(semaphore == NULL)
+      return NULL;
+
+   semaphore->name = name;
+   semaphore->threadHead = NULL;
+   semaphore->count = count;
+   return semaphore;
+}
+
+
+/******************************************/
+void OS_SemaphoreDelete(OS_Semaphore_t *semaphore)
+{
+   while(semaphore->threadHead)
+      OS_SemaphorePost(semaphore);
+   OS_HeapFree(semaphore);
+}
+
+
+/******************************************/
+//Sleep the number of ticks (~10ms) until the semaphore is acquired
+int OS_SemaphorePend(OS_Semaphore_t *semaphore, int ticks)
+{
+   uint32 state, cpuIndex;
+   OS_Thread_t *thread;
+   int returnCode=0;
+
+   assert(semaphore);
+   assert(InterruptInside[OS_CpuIndex()] == 0);
+   state = OS_CriticalBegin();    //Disable interrupts
+   if(--semaphore->count < 0)
+   {
+      //Semaphore not available
+      if(ticks == 0)
+      {
+         ++semaphore->count;
+         OS_CriticalEnd(state);
+         return -1;
+      }
+
+      //Need to sleep until the semaphore is available
+      cpuIndex = OS_CpuIndex();
+      thread = ThreadCurrent[cpuIndex];
+      assert(thread);
+      thread->semaphorePending = semaphore;
+      thread->ticksTimeout = ticks + OS_ThreadTime();
+
+      //FYI: The current thread isn't in the ThreadHead linked list
+      //Place the thread into a sorted linked list of pending threads
+      OS_ThreadPriorityInsert(&semaphore->threadHead, thread);
+      thread->state = THREAD_PEND;
+      if(ticks != OS_WAIT_FOREVER)
+         OS_ThreadTimeoutInsert(thread); //Check every ~10ms for timeouts
+      assert(ThreadHead);
+      OS_ThreadReschedule(0);           //Run highest priority thread
+      returnCode = thread->returnCode;  //Will be -1 if timed out
+   }
+   OS_CriticalEnd(state);               //Re-enable interrupts
+   return returnCode;
+}
+
+
+/******************************************/
+//Release a semaphore and possibly wake up a blocked thread
+void OS_SemaphorePost(OS_Semaphore_t *semaphore)
+{
+   uint32 state;
+   OS_Thread_t *thread;
+
+   assert(semaphore);
+   state = OS_CriticalBegin();
+   if(++semaphore->count <= 0)
+   {
+      //Wake up a thread that was waiting for this semaphore
+      thread = semaphore->threadHead;
+      OS_ThreadTimeoutRemove(thread);
+      OS_ThreadPriorityRemove(&semaphore->threadHead, thread);
+      OS_ThreadPriorityInsert(&ThreadHead, thread);
+      thread->semaphorePending = NULL;
+      thread->returnCode = 0;
+      OS_ThreadReschedule(0);
+   }
+   OS_CriticalEnd(state);
+}
+
+
+
+/***************** Mutex ******************/
+/******************************************/
+//Create a mutex (a thread aware semaphore)
+OS_Mutex_t *OS_MutexCreate(const char *name)
+{
+   OS_Mutex_t *mutex;
+
+   mutex = (OS_Mutex_t*)OS_HeapMalloc(HEAP_SYSTEM, sizeof(OS_Mutex_t));
+   if(mutex == NULL)
+      return NULL;
+   mutex->semaphore = OS_SemaphoreCreate(name, 1);
+   if(mutex->semaphore == NULL)
+      return NULL;
+   mutex->thread = NULL;
+   mutex->count = 0;
+   return mutex;
+}
+
+
+/******************************************/
+void OS_MutexDelete(OS_Mutex_t *mutex)
+{
+   OS_SemaphoreDelete(mutex->semaphore);
+   OS_HeapFree(mutex);
+}
+
+
+/******************************************/
+void OS_MutexPend(OS_Mutex_t *mutex)
+{
+   OS_Thread_t *thread;
+
+   assert(mutex);
+   thread = OS_ThreadSelf();
+   if(thread == mutex->thread)
+   {
+      ++mutex->count;
+      return;
+   }
+   OS_SemaphorePend(mutex->semaphore, OS_WAIT_FOREVER);
+   mutex->thread = thread;
+   mutex->count = 1;
+}
+
+
+/******************************************/
+void OS_MutexPost(OS_Mutex_t *mutex)
+{
+   assert(mutex);
+   assert(mutex->thread == OS_ThreadSelf());
+   assert(mutex->count > 0);
+   if(--mutex->count <= 0)
+   {
+      mutex->thread = NULL;
+      OS_SemaphorePost(mutex->semaphore);
+   }
+}
+
+
+
+/***************** MQueue *****************/
+/******************************************/
+//Create a message queue
+OS_MQueue_t *OS_MQueueCreate(const char *name,
+                             int messageCount,
+                             int messageBytes)
+{
+   OS_MQueue_t *queue;
+   int size;
+
+   assert((messageBytes & 3) == 0);
+   size = messageBytes / sizeof(uint32);
+   queue = (OS_MQueue_t*)OS_HeapMalloc(HEAP_SYSTEM, sizeof(OS_MQueue_t) + 
+      messageCount * size * 4);
+   if(queue == NULL)
+      return queue;
+   queue->name = name;
+   queue->semaphore = OS_SemaphoreCreate(name, 0);
+   if(queue->semaphore == NULL)
+      return NULL;
+   queue->count = messageCount;
+   queue->size = size;
+   queue->used = 0;
+   queue->read = 0;
+   queue->write = 0;
+   return queue;
+}
+
+
+/******************************************/
+void OS_MQueueDelete(OS_MQueue_t *mQueue)
+{
+   OS_SemaphoreDelete(mQueue->semaphore);
+   OS_HeapFree(mQueue);
+}
+
+
+/******************************************/
+//Send a message that is messageBytes long (defined during create)
+int OS_MQueueSend(OS_MQueue_t *mQueue, void *message)
+{
+   uint32 state, *dst, *src;
+   int i;
+
+   assert(mQueue);
+   src = (uint32*)message;
+   state = OS_CriticalBegin();           //Disable interrupts
+   if(++mQueue->used > mQueue->count)
+   {
+      //The message queue is full so discard the message
+      --mQueue->used;
+      OS_CriticalEnd(state);
+      return -1;
+   }
+   dst = (uint32*)(mQueue + 1) + mQueue->write * mQueue->size;
+   for(i = 0; i < mQueue->size; ++i)     //Copy the message into the queue
+      dst[i] = src[i];
+   if(++mQueue->write >= mQueue->count)
+      mQueue->write = 0;
+   OS_CriticalEnd(state);                //Re-enable interrupts
+   OS_SemaphorePost(mQueue->semaphore);  //Wakeup the receiving thread
+   return 0;
+}
+
+
+/******************************************/
+//Receive a message that is messageBytes long (defined during create)
+//Wait at most ~10 msec ticks
+int OS_MQueueGet(OS_MQueue_t *mQueue, void *message, int ticks)
+{
+   uint32 state, *dst, *src;
+   int i, rc;
+
+   assert(mQueue);
+   rc = OS_SemaphorePend(mQueue->semaphore, ticks); //Wait for message
+   if(rc)
+      return rc;                         //Request timed out so rc = -1
+   state = OS_CriticalBegin();           //Disable interrupts
+   --mQueue->used;
+   dst = (uint32*)message;
+   src = (uint32*)(mQueue + 1) + mQueue->read * mQueue->size;
+   for(i = 0; i < mQueue->size; ++i)     //Copy message from the queue
+      dst[i] = src[i];
+   if(++mQueue->read >= mQueue->count)
+      mQueue->read = 0;
+   OS_CriticalEnd(state);                //Re-enable interrupts
+   return 0;
+}
+
+
+
+/***************** Jobs *******************/
+/******************************************/
+typedef void (*JobFunc_t)();
+static OS_MQueue_t *jobQueue;
+static OS_Thread_t *jobThread;
+
+//This thread waits for jobs that request a function to be called
+static void JobThread(void *arg)
+{
+   uint32 message[4];
+   JobFunc_t funcPtr;
+   (void)arg;
+   for(;;)
+   {
+      OS_MQueueGet(jobQueue, message, OS_WAIT_FOREVER);
+      funcPtr = (JobFunc_t)message[0];
+      funcPtr(message[1], message[2], message[3]);
+   }
+}
+
+
+/******************************************/
+//Call a function using the job thread so the caller won't be blocked
+void OS_Job(void (*funcPtr)(), void *arg0, void *arg1, void *arg2)
+{
+   uint32 message[4];
+   int rc;
+
+   OS_SemaphorePend(SemaphoreLock, OS_WAIT_FOREVER);
+   if(jobThread == NULL)
+   {
+      jobQueue = OS_MQueueCreate("job", 100, 16);
+      jobThread = OS_ThreadCreate("job", JobThread, NULL, 150, 4000);
+   }
+   OS_SemaphorePost(SemaphoreLock);
+
+   message[0] = (uint32)funcPtr;
+   message[1] = (uint32)arg0;
+   message[2] = (uint32)arg1;
+   message[3] = (uint32)arg2;
+   rc = OS_MQueueSend(jobQueue, message);
+}
+
+
+/***************** Timer ******************/
+/******************************************/
+//This thread polls the list of timers to see if any have timed out
+static void OS_TimerThread(void *arg)
+{
+   uint32 timeNow;
+   int diff, ticks;
+   uint32 message[8];
+   OS_Timer_t *timer;
+   (void)arg;
+
+   timeNow = OS_ThreadTime();  //Number of ~10 msec ticks since reboot
+   for(;;)
+   {
+      //Determine how long to sleep
+      OS_SemaphorePend(SemaphoreLock, OS_WAIT_FOREVER);
+      if(TimerHead)
+         ticks = TimerHead->ticksTimeout - timeNow;
+      else
+         ticks = OS_WAIT_FOREVER;
+      OS_SemaphorePost(SemaphoreLock);
+      OS_SemaphorePend(SemaphoreTimer, ticks);
+
+      //Send messages for all timed out timers
+      timeNow = OS_ThreadTime();
+      for(;;)
+      {
+         timer = NULL;
+         OS_SemaphorePend(SemaphoreLock, OS_WAIT_FOREVER);
+         if(TimerHead)
+         {
+            diff = timeNow - TimerHead->ticksTimeout;
+            if(diff >= 0)
+               timer = TimerHead;
+         }
+         OS_SemaphorePost(SemaphoreLock);
+         if(timer == NULL)
+            break;
+         if(timer->ticksRestart)
+            OS_TimerStart(timer, timer->ticksRestart, timer->ticksRestart);
+         else
+            OS_TimerStop(timer);
+
+         if(timer->callback)
+            timer->callback(timer, timer->info);
+         else
+         {
+            //Send message
+            message[0] = MESSAGE_TYPE_TIMER;
+            message[1] = (uint32)timer;
+            message[2] = timer->info;
+            OS_MQueueSend(timer->mqueue, message);
+         }
+      }
+   }
+}
+
+
+/******************************************/
+//Create a timer that will send a message upon timeout
+OS_Timer_t *OS_TimerCreate(const char *name, OS_MQueue_t *mQueue, uint32 info)
+{
+   OS_Timer_t *timer;
+
+   OS_SemaphorePend(SemaphoreLock, OS_WAIT_FOREVER);
+   if(SemaphoreTimer == NULL)
+   {
+      SemaphoreTimer = OS_SemaphoreCreate("Timer", 0);
+      OS_ThreadCreate("Timer", OS_TimerThread, NULL, 250, 2000);
+   }
+   OS_SemaphorePost(SemaphoreLock);
+
+   timer = (OS_Timer_t*)OS_HeapMalloc(HEAP_SYSTEM, sizeof(OS_Timer_t));
+   if(timer == NULL)
+      return NULL;
+   timer->name = name;
+   timer->callback = NULL;
+   timer->mqueue = mQueue;
+   timer->next = NULL;
+   timer->prev = NULL;
+   timer->info = info;
+   timer->active = 0;
+   return timer;
+}
+
+
+/******************************************/
+void OS_TimerDelete(OS_Timer_t *timer)
+{
+   OS_TimerStop(timer);
+   OS_HeapFree(timer);
+}
+
+
+/******************************************/
+void OS_TimerCallback(OS_Timer_t *timer, OS_TimerFuncPtr_t callback)
+{
+   timer->callback = callback;
+}
+
+
+/******************************************/
+//Must not be called from an ISR
+//In ~10 msec ticks send a message (or callback)
+void OS_TimerStart(OS_Timer_t *timer, uint32 ticks, uint32 ticksRestart)
+{
+   OS_Timer_t *node, *prev;
+   int diff, check=0;
+
+   assert(timer);
+   assert(InterruptInside[OS_CpuIndex()] == 0);
+   ticks += OS_ThreadTime();
+   if(timer->active)
+      OS_TimerStop(timer);
+   OS_SemaphorePend(SemaphoreLock, OS_WAIT_FOREVER);
+   if(timer->active)
+   {
+      //Prevent race condition
+      OS_SemaphorePost(SemaphoreLock);
+      return;
+   }
+   timer->ticksTimeout = ticks;
+   timer->ticksRestart = ticksRestart;
+   timer->active = 1;
+   prev = NULL;
+   for(node = TimerHead; node; node = node->next)
+   {
+      diff = ticks - node->ticksTimeout;
+      if(diff <= 0)
+         break;
+      prev = node;
+   }
+   timer->next = node;
+   timer->prev = prev;
+   if(node)
+      node->prev = timer;
+   if(prev == NULL)
+   {
+      TimerHead = timer;
+      check = 1;
+   }
+   else
+      prev->next = timer;
+   OS_SemaphorePost(SemaphoreLock);
+   if(check)
+      OS_SemaphorePost(SemaphoreTimer);  //Wakeup OS_TimerThread
+}
+
+
+/******************************************/
+//Must not be called from an ISR
+void OS_TimerStop(OS_Timer_t *timer)
+{
+   assert(timer);
+   assert(InterruptInside[OS_CpuIndex()] == 0);
+   OS_SemaphorePend(SemaphoreLock, OS_WAIT_FOREVER);
+   if(timer->active)
+   {
+      timer->active = 0;
+      if(timer->prev == NULL)
+         TimerHead = timer->next;
+      else
+         timer->prev->next = timer->next;
+      if(timer->next)
+         timer->next->prev = timer->prev;
+   }
+   OS_SemaphorePost(SemaphoreLock);
+}
+
+
+/***************** ISR ********************/
+/******************************************/
+void OS_InterruptServiceRoutine(uint32 status, uint32 *stack)
+{
+   int i;
+   uint32 state, cpuIndex = OS_CpuIndex();
+
+   if(status == 0 && Isr[31])
+      Isr[31](stack);                   //SYSCALL or BREAK
+
+   InterruptInside[cpuIndex] = 1;
+   i = 0;
+   do
+   {   
+      if(status & 1)
+      {
+         if(Isr[i])
+            Isr[i](stack);
+         else
+            OS_InterruptMaskClear(1 << i);
+      }
+      status >>= 1;
+      ++i;
+   } while(status);
+   InterruptInside[cpuIndex] = 0;
+
+   state = OS_SpinLock();
+   if(ThreadNeedReschedule[cpuIndex])
+      OS_ThreadReschedule(ThreadNeedReschedule[cpuIndex] & 1);
+   OS_SpinUnlock(state);
+}
+
+
+/******************************************/
+void OS_InterruptRegister(uint32 mask, OS_FuncPtr_t funcPtr)
+{
+   int i;
+
+   for(i = 0; i < 32; ++i)
+   {
+      if(mask & (1 << i))
+         Isr[i] = funcPtr;
+   }
+}
+
+
+/******************************************/
+//Plasma hardware dependent
+uint32 OS_InterruptStatus(void)
+{
+   return MemoryRead(IRQ_STATUS);
+}
+
+
+/******************************************/
+//Plasma hardware dependent
+uint32 OS_InterruptMaskSet(uint32 mask)
+{
+   uint32 state;
+   state = OS_CriticalBegin();
+   mask |= MemoryRead(IRQ_MASK);
+   MemoryWrite(IRQ_MASK, mask);
+   OS_CriticalEnd(state);
+   return mask;
+}
+
+
+/******************************************/
+//Plasma hardware dependent
+uint32 OS_InterruptMaskClear(uint32 mask)
+{
+   uint32 state;
+   state = OS_CriticalBegin();
+   mask = MemoryRead(IRQ_MASK) & ~mask;
+   MemoryWrite(IRQ_MASK, mask);
+   OS_CriticalEnd(state);
+   return mask;
+}
+
+
+/**************** Init ********************/
+/******************************************/
+//If there aren't any other ready to run threads then spin here
+static volatile uint32 IdleCount;
+static void OS_IdleThread(void *arg)
+{
+   (void)arg;
+
+   //Don't block in the idle thread!
+   for(;;)
+   {
+      ++IdleCount;
+   }
+}
+
+
+/******************************************/
+#ifndef DISABLE_IRQ_SIM
+//Simulate the hardware interrupts
+static void OS_IdleSimulateIsr(void *arg)
+{
+   uint32 count=0, value;
+   (void)arg;
+
+   for(;;)
+   {
+      MemoryRead(IRQ_MASK + 4);       //calls Sleep(10)
+#if WIN32
+      while(OS_InterruptMaskSet(0) & IRQ_UART_WRITE_AVAILABLE)
+         OS_InterruptServiceRoutine(IRQ_UART_WRITE_AVAILABLE, 0);
+#endif
+      value = OS_InterruptMaskSet(0) & 0xf;
+      if(value)
+         OS_InterruptServiceRoutine(value, 0);
+      ++count;
+   }
+}
+#endif //DISABLE_IRQ_SIM
+
+
+/******************************************/
+//Plasma hardware dependent
+//ISR called every ~10 msecs when bit 18 of the counter register toggles
+static void OS_ThreadTickToggle(void *arg)
+{
+   uint32 status, mask, state;
+
+   //Toggle looking for IRQ_COUNTER18 or IRQ_COUNTER18_NOT
+   state = OS_SpinLock();
+   status = MemoryRead(IRQ_STATUS) & (IRQ_COUNTER18 | IRQ_COUNTER18_NOT);
+   mask = MemoryRead(IRQ_MASK) | IRQ_COUNTER18 | IRQ_COUNTER18_NOT;
+   mask &= ~status;
+   MemoryWrite(IRQ_MASK, mask);
+   OS_ThreadTick(arg);
+   OS_SpinUnlock(state);
+}
+
+
+/******************************************/
+//Initialize the OS by setting up the system heap and the tick interrupt
+void OS_Init(uint32 *heapStorage, uint32 bytes)
+{
+   int i;\r
+   if((int)OS_Init > 0x10000000)        //Running from DDR?
+      OS_AsmInterruptInit();            //Patch interrupt vector
+   OS_InterruptMaskClear(0xffffffff);   //Disable interrupts
+   HeapArray[0] = OS_HeapCreate("Default", heapStorage, bytes);
+   HeapArray[1] = HeapArray[0];
+   SemaphoreSleep = OS_SemaphoreCreate("Sleep", 0);
+   SemaphoreRelease = OS_SemaphoreCreate("Release", 1);
+   SemaphoreLock = OS_SemaphoreCreate("Lock", 1);
+   for(i = 0; i < OS_CPU_COUNT; ++i)
+      OS_ThreadCreate("Idle", OS_IdleThread, NULL, 0, 256);
+#ifndef DISABLE_IRQ_SIM
+   if((OS_InterruptStatus() & (IRQ_COUNTER18 | IRQ_COUNTER18_NOT)) == 0)
+   {
+      //Detected that running in simulator so create SimIsr thread
+      UartPrintfCritical("SimIsr\n");
+      OS_ThreadCreate("SimIsr", OS_IdleSimulateIsr, NULL, 1, 0);
+   }
+#endif //DISABLE_IRQ_SIM
+   //Plasma hardware dependent (register for OS tick interrupt every ~10 msecs)
+   OS_InterruptRegister(IRQ_COUNTER18 | IRQ_COUNTER18_NOT, OS_ThreadTickToggle);
+   OS_InterruptMaskSet(IRQ_COUNTER18 | IRQ_COUNTER18_NOT);
+}
+
+
+/******************************************/
+//Start thread swapping
+void OS_Start(void)
+{
+   ThreadSwapEnabled = 1;
+   (void)OS_SpinLock();
+   OS_ThreadReschedule(1);
+}
+
+
+/******************************************/
+//Place breakpoint here
+void OS_Assert(void)
+{
+}
+
+
+#if OS_CPU_COUNT > 1
+static uint8 SpinLockArray[OS_CPU_COUNT];
+/******************************************/
+uint32 OS_CpuIndex(void)
+{
+   return 0; //0 to OS_CPU_COUNT-1
+}
+
+
+/******************************************/
+//Symmetric Multiprocessing Spin Lock Mutex
+uint32 OS_SpinLock(void)
+{
+   uint32 state, cpuIndex, i, j, ok, delay;
+
+   cpuIndex = OS_CpuIndex();
+   delay = cpuIndex + 8;
+   state = OS_AsmInterruptEnable(0);
+   //Spin until only this CPU has the spin lock
+   do
+   {
+      ok = 1;
+      if(++SpinLockArray[cpuIndex] == 1)
+      {
+         for(i = 0; i < OS_CPU_COUNT; ++i)
+         {
+            if(i != cpuIndex && SpinLockArray[i])
+               ok = 0;   //Another CPU has the spin lock
+         }
+         if(ok == 0)
+         {
+            SpinLockArray[cpuIndex] = 0;
+            for(j = 0; j < delay; ++j)  //wait a bit
+               ++i;
+            if(delay < 128)
+               delay <<= 1;
+         }
+      }
+   } while(ok == 0);
+   return state;
+}
+
+
+/******************************************/
+void OS_SpinUnlock(uint32 state)
+{
+   uint32 cpuIndex;
+   cpuIndex = OS_CpuIndex();
+   if(--SpinLockArray[cpuIndex] == 0)
+      OS_AsmInterruptEnable(state);
+
+   assert(SpinLockArray[cpuIndex] < 10);
+}
+#endif  //OS_CPU_COUNT > 1
+
+
+/************** WIN32/Linux Support *************/
+#ifdef WIN32
+#ifdef LINUX
+#define putch putchar
+#undef _LIBC
+#undef kbhit
+#undef getch
+#define UartPrintf UartPrintf2
+#define UartScanf UartScanf2
+#include <stdio.h>
+#include <stdlib.h>
+#include <termios.h>
+#include <unistd.h>
+//Support RTOS inside Linux
+void Sleep(unsigned int value)
+{ 
+   usleep(value * 1000);
+}
+
+int kbhit(void)
+{
+   struct termios oldt, newt;
+   struct timeval tv;
+   fd_set read_fd;
+
+   tcgetattr(STDIN_FILENO, &oldt);
+   newt = oldt;
+   newt.c_lflag &= ~(ICANON | ECHO);
+   tcsetattr(STDIN_FILENO, TCSANOW, &newt);
+   tv.tv_sec=0;
+   tv.tv_usec=0;
+   FD_ZERO(&read_fd);
+   FD_SET(0,&read_fd);
+   if(select(1, &read_fd, NULL, NULL, &tv) == -1)
+      return 0;
+   if(FD_ISSET(0,&read_fd))
+      return 1;
+   return 0;
+}
+
+int getch(void)
+{
+   struct termios oldt, newt;
+   int ch;
+
+   tcgetattr(STDIN_FILENO, &oldt);
+   newt = oldt;
+   newt.c_lflag &= ~(ICANON | ECHO);
+   tcsetattr(STDIN_FILENO, TCSANOW, &newt);
+   ch = getchar();
+   return ch;
+}
+#else
+//Support RTOS inside Windows
+#undef kbhit
+#undef getch
+#undef putch
+extern int kbhit();
+extern int getch(void);
+extern int putch(int);
+extern void __stdcall Sleep(unsigned long value);
+#endif
+
+static uint32 Memory[8];
+
+//Simulates device register memory reads
+uint32 MemoryRead(uint32 address)
+{
+   Memory[2] |= IRQ_UART_WRITE_AVAILABLE;    //IRQ_STATUS
+   switch(address)
+   {
+   case UART_READ: 
+      if(kbhit())
+         Memory[0] = getch();                //UART_READ
+      Memory[2] &= ~IRQ_UART_READ_AVAILABLE; //clear bit
+      return Memory[0];
+   case IRQ_MASK: 
+      return Memory[1];                      //IRQ_MASK
+   case IRQ_MASK + 4:
+      Sleep(10);
+      return 0;
+   case IRQ_STATUS: 
+      if(kbhit())
+         Memory[2] |= IRQ_UART_READ_AVAILABLE;
+      return Memory[2];
+   }
+   return 0;
+}
+
+//Simulates device register memory writes
+void MemoryWrite(uint32 address, uint32 value)
+{
+   switch(address)
+   {
+   case UART_WRITE: 
+      putch(value); 
+      break;
+   case IRQ_MASK:   
+      Memory[1] = value; 
+      break;
+   case IRQ_STATUS: 
+      Memory[2] = value; 
+      break;
+   }
+}
+
+uint32 OS_AsmInterruptEnable(uint32 enableInterrupt)
+{
+   return enableInterrupt;
+}
+
+void OS_AsmInterruptInit(void)
+{
+}
+#endif  //WIN32
+
+
+/**************** Example *****************/
+#ifndef NO_MAIN
+#ifdef WIN32
+static uint8 HeapSpace[1024*512];  //For simulation on a PC
+#endif
+
+int main(int programEnd, char *argv[])
+{
+   (void)programEnd;  //Pointer to end of used memory
+   (void)argv;
+
+   UartPrintfCritical("Starting RTOS\n");
+#ifdef WIN32
+   OS_Init((uint32*)HeapSpace, sizeof(HeapSpace));  //For PC simulation
+#else
+   //Create heap in remaining space after program in 1MB external RAM
+   OS_Init((uint32*)programEnd, 
+           RAM_EXTERNAL_BASE + RAM_EXTERNAL_SIZE - programEnd); 
+#endif
+   UartInit();
+   OS_ThreadCreate("Main", MainThread, NULL, 100, 4000);
+   OS_Start();
+   return 0;
+}
+#endif  //NO_MAIN
+
diff --git a/kernel/rtos.h b/kernel/rtos.h
new file mode 100644 (file)
index 0000000..5fbe66f
--- /dev/null
@@ -0,0 +1,377 @@
+/*--------------------------------------------------------------------
+ * TITLE: Plasma Real Time Operating System
+ * AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
+ * DATE CREATED: 12/17/05
+ * FILENAME: rtos.h
+ * PROJECT: Plasma CPU core
+ * COPYRIGHT: Software placed into the public domain by the author.
+ *    Software 'as is' without warranty.  Author liable for nothing.
+ * DESCRIPTION:
+ *    Plasma Real Time Operating System
+ *--------------------------------------------------------------------*/
+#ifndef __RTOS_H__
+#define __RTOS_H__
+
+// Symmetric Multi-Processing
+#define OS_CPU_COUNT 1
+
+// Typedefs
+typedef unsigned int   uint32;
+typedef unsigned short uint16;
+typedef unsigned char  uint8;
+
+// Memory Access
+#ifdef WIN32
+   uint32 MemoryRead(uint32 Address);
+   void MemoryWrite(uint32 Address, uint32 Value);
+#else
+   #define MemoryRead(A) (*(volatile uint32*)(A))
+   #define MemoryWrite(A,V) *(volatile uint32*)(A)=(V)
+#endif
+
+/***************** LibC ******************/
+#if !defined(_LIBC) && !defined(_CTYPE_DEFINED)
+#define printf     UartPrintf
+//#define printf     UartPrintfPoll
+#define scanf      UartScanf
+#ifndef WIN32
+   #define malloc(S)  OS_HeapMalloc(NULL, S)
+   #define free(S)    OS_HeapFree(S)
+#endif
+
+#ifndef NULL
+#define NULL (void*)0
+#endif
+
+#define assert(A) if((A)==0){OS_Assert();UartPrintfCritical("\r\nAssert %s:%d\r\n", __FILE__, __LINE__);}
+
+#define isprint(c) (' '<=(c)&&(c)<='~')
+#define isspace(c) ((c)==' '||(c)=='\t'||(c)=='\n'||(c)=='\r')
+#define isdigit(c) ('0'<=(c)&&(c)<='9')
+#define islower(c) ('a'<=(c)&&(c)<='z')
+#define isupper(c) ('A'<=(c)&&(c)<='Z')
+#define isalpha(c) (islower(c)||isupper(c))
+#define isalnum(c) (isalpha(c)||isdigit(c))
+#undef  min
+#define min(a,b)   ((a)<(b)?(a):(b))
+#define strcpy     strcpy2  //don't use intrinsic functions
+#define strcat     strcat2
+#define strncat    strncat2
+#define strcmp     strcmp2
+#define strlen     strlen2
+#define memcpy     memcpy2
+#define memcmp     memcmp2
+#define memset     memset2
+#define abs        abs2
+#define atoi       atoi2
+
+char *strcpy(char *dst, const char *src);
+char *strncpy(char *dst, const char *src, int count);
+char *strcat(char *dst, const char *src);
+char *strncat(char *dst, const char *src, int count);
+int   strcmp(const char *string1, const char *string2);
+int   strncmp(const char *string1, const char *string2, int count);
+char *strstr(const char *string, const char *find);
+int   strlen(const char *string);
+void *memcpy(void *dst, const void *src, unsigned long bytes);
+void *memmove(void *dst, const void *src, unsigned long bytes);
+int   memcmp(const void *cs, const void *ct, unsigned long bytes);
+void *memset(void *dst, int c, unsigned long bytes);
+int   abs(int n);
+int   rand(void);
+void  srand(unsigned int seed);
+long  strtol(const char *s, char **end, int base);
+int   atoi(const char *s);
+char *itoa(int num, char *dst, int base);
+#ifndef NO_ELLIPSIS
+   int sprintf(char *s, const char *format, ...);
+   int sscanf(const char *s, const char *format, ...);
+#endif
+#ifdef INCLUDE_DUMP
+   void dump(const unsigned char *data, int length);
+#endif
+#ifdef INCLUDE_QSORT
+   void qsort(void *base, 
+              long n, 
+              long size, 
+              int (*cmp)(const void *,const void *));
+   void *bsearch(const void *key,
+                 const void *base,
+                 long n,
+                 long size,
+                 int (*cmp)(const void *,const void *));
+#endif
+#ifdef INCLUDE_TIMELIB
+   #define difftime(time2,time1) (time2-time1)
+   typedef unsigned long time_t;  //start at 1/1/80
+   struct tm {
+      int tm_sec;      //(0,59)
+      int tm_min;      //(0,59)
+      int tm_hour;     //(0,23)
+      int tm_mday;     //(1,31)
+      int tm_mon;      //(0,11)
+      int tm_year;     //(0,n) from 1900
+      int tm_wday;     //(0,6)     calculated
+      int tm_yday;     //(0,365)   calculated
+      int tm_isdst;    //          calculated
+   };
+   time_t mktime(struct tm *tp);
+   void gmtime_r(const time_t *tp, struct tm *out);
+   void gmtimeDst(time_t dstTimeIn, time_t dstTimeOut);
+   void gmtimeDstSet(time_t *tp, time_t *dstTimeIn, time_t *dstTimeOut);
+#endif
+#define _LIBC
+#endif //_LIBC
+
+/***************** Assembly **************/
+typedef uint32 jmp_buf[20];
+extern uint32 OS_AsmInterruptEnable(uint32 state);
+extern void OS_AsmInterruptInit(void);
+extern int setjmp(jmp_buf env);
+extern void longjmp(jmp_buf env, int val);
+extern uint32 OS_AsmMult(uint32 a, uint32 b, unsigned long *hi);
+extern void *OS_Syscall();
+
+/***************** Heap ******************/
+#define HEAP_USER    (void*)0
+#define HEAP_SYSTEM  (void*)1
+#define HEAP_SMALL   (void*)2
+#define HEAP_UI      (void*)3
+typedef struct OS_Heap_s OS_Heap_t;
+OS_Heap_t *OS_HeapCreate(const char *name, void *memory, uint32 size);
+void OS_HeapDestroy(OS_Heap_t *heap);
+void *OS_HeapMalloc(OS_Heap_t *heap, int bytes);
+void OS_HeapFree(void *block);
+void OS_HeapAlternate(OS_Heap_t *heap, OS_Heap_t *alternate);
+void OS_HeapRegister(void *index, OS_Heap_t *heap);
+
+/***************** Critical Sections *****************/
+#if OS_CPU_COUNT <= 1
+   // Single CPU
+   #define OS_CpuIndex() 0
+   #define OS_CriticalBegin() OS_AsmInterruptEnable(0)
+   #define OS_CriticalEnd(S) OS_AsmInterruptEnable(S)
+   #define OS_SpinLock() 0
+   #define OS_SpinUnlock(S) 
+#else
+   // Symmetric multiprocessing
+   uint32 OS_CpuIndex(void);
+   #define OS_CriticalBegin() OS_SpinLock()
+   #define OS_CriticalEnd(S) OS_SpinUnlock(S)
+   uint32 OS_SpinLock(void);
+   void OS_SpinUnlock(uint32 state);
+#endif
+
+/***************** Thread *****************/
+#ifdef WIN32
+   #define STACK_SIZE_MINIMUM (1024*4)
+#else
+   #define STACK_SIZE_MINIMUM (1024*1)
+#endif
+#define STACK_SIZE_DEFAULT 1024*2
+#undef THREAD_PRIORITY_IDLE
+#define THREAD_PRIORITY_IDLE 0
+#define THREAD_PRIORITY_MAX 255
+
+typedef void (*OS_FuncPtr_t)(void *arg);
+typedef struct OS_Thread_s OS_Thread_t;
+OS_Thread_t *OS_ThreadCreate(const char *name,
+                             OS_FuncPtr_t funcPtr, 
+                             void *arg, 
+                             uint32 priority, 
+                             uint32 stackSize);
+void OS_ThreadExit(void);
+OS_Thread_t *OS_ThreadSelf(void);
+void OS_ThreadSleep(int ticks);
+uint32 OS_ThreadTime(void);
+void OS_ThreadInfoSet(OS_Thread_t *thread, uint32 index, void *info);
+void *OS_ThreadInfoGet(OS_Thread_t *thread, uint32 index);
+uint32 OS_ThreadPriorityGet(OS_Thread_t *thread);
+void OS_ThreadPrioritySet(OS_Thread_t *thread, uint32 priority);
+void OS_ThreadProcessId(OS_Thread_t *thread, uint32 processId, OS_Heap_t *heap);
+void OS_ThreadTick(void *arg);
+void OS_ThreadCpuLock(OS_Thread_t *thread, int cpuIndex);
+
+/***************** Semaphore **************/
+#define OS_SUCCESS 0
+#define OS_ERROR  -1
+#define OS_WAIT_FOREVER -1
+#define OS_NO_WAIT 0
+typedef struct OS_Semaphore_s OS_Semaphore_t;
+OS_Semaphore_t *OS_SemaphoreCreate(const char *name, uint32 count);
+void OS_SemaphoreDelete(OS_Semaphore_t *semaphore);
+int OS_SemaphorePend(OS_Semaphore_t *semaphore, int ticks); //tick ~= 10ms
+void OS_SemaphorePost(OS_Semaphore_t *semaphore);
+
+/***************** Mutex ******************/
+typedef struct OS_Mutex_s OS_Mutex_t;
+OS_Mutex_t *OS_MutexCreate(const char *name);
+void OS_MutexDelete(OS_Mutex_t *semaphore);
+void OS_MutexPend(OS_Mutex_t *semaphore);
+void OS_MutexPost(OS_Mutex_t *semaphore);
+
+/***************** MQueue *****************/
+enum {
+   MESSAGE_TYPE_USER = 0,
+   MESSAGE_TYPE_TIMER = 5
+};
+typedef struct OS_MQueue_s OS_MQueue_t;
+OS_MQueue_t *OS_MQueueCreate(const char *name,
+                             int messageCount,
+                             int messageBytes);
+void OS_MQueueDelete(OS_MQueue_t *mQueue);
+int OS_MQueueSend(OS_MQueue_t *mQueue, void *message);
+int OS_MQueueGet(OS_MQueue_t *mQueue, void *message, int ticks);
+
+/***************** Job ********************/
+void OS_Job(void (*funcPtr)(), void *arg0, void *arg1, void *arg2);
+
+/***************** Timer ******************/
+typedef struct OS_Timer_s OS_Timer_t;
+typedef void (*OS_TimerFuncPtr_t)(OS_Timer_t *timer, uint32 info);
+OS_Timer_t *OS_TimerCreate(const char *name, OS_MQueue_t *mQueue, uint32 info);
+void OS_TimerDelete(OS_Timer_t *timer);
+void OS_TimerCallback(OS_Timer_t *timer, OS_TimerFuncPtr_t callback);
+void OS_TimerStart(OS_Timer_t *timer, uint32 ticks, uint32 ticksRestart);
+void OS_TimerStop(OS_Timer_t *timer);
+
+/***************** ISR ********************/
+#define STACK_EPC 88/4
+void OS_InterruptServiceRoutine(uint32 status, uint32 *stack);
+void OS_InterruptRegister(uint32 mask, OS_FuncPtr_t funcPtr);
+uint32 OS_InterruptStatus(void);
+uint32 OS_InterruptMaskSet(uint32 mask);
+uint32 OS_InterruptMaskClear(uint32 mask);
+
+/***************** Init ******************/
+void OS_Init(uint32 *heapStorage, uint32 bytes);
+void OS_Start(void);
+void OS_Assert(void);
+void OS_DebuggerInit(void);
+void MainThread(void *Arg);
+
+/***************** MMU ******************/
+typedef struct {
+   const char *name;
+   OS_FuncPtr_t funcPtr;
+   void *arg;
+   uint32 priority;
+   uint32 stackSize;
+   uint32 heapSize;
+   uint32 processId;
+   OS_Semaphore_t *semaphoreDone;
+   uint8 *memory;       //private
+   OS_Heap_t *heap;     //private
+   OS_Thread_t *thread; //private
+} OS_Process_t;
+void OS_MMUInit(void);
+void OS_MMUMemoryRegister(uint32 processId,
+                          uint32 virtualAddress,
+                          uint32 physicalAddress,
+                          uint32 size,
+                          uint32 writable);
+OS_Process_t *OS_MMUProcessCreate(OS_Process_t *process);
+void OS_MMUProcessDelete(OS_Process_t *process);
+void OS_MMUUartPrintf();
+void OS_MMUUartScanf();
+void OS_MMUUartPrintfCritical();
+
+/***************** UART ******************/
+typedef uint8* (*PacketGetFunc_t)(void);
+void UartInit(void);
+void UartWrite(int ch);
+uint8 UartRead(void);
+void UartWriteData(uint8 *data, int length);
+void UartReadData(uint8 *data, int length);
+#ifndef NO_ELLIPSIS2
+void UartPrintf(const char *format, ...);
+void UartPrintfPoll(const char *format, ...);
+void UartPrintfCritical(const char *format, ...);
+void UartPrintfNull(const char *format, ...);
+void UartScanf(const char *format, ...);
+#endif
+void UartPacketConfig(PacketGetFunc_t packetGetFunc, 
+                      int packetSize, 
+                      OS_MQueue_t *mQueue);
+void UartPacketSend(uint8 *data, int bytes);
+#ifdef WIN32
+#define puts  puts2
+#define getch getch2
+#define kbhit kbhit2
+#endif
+int puts(const char *string);
+int getch(void);
+int kbhit(void);
+void LogWrite(int a);
+void LogDump(void);
+void Led(int mask, int value);
+
+/***************** Keyboard **************/
+#define KEYBOARD_RAW     0x100
+#define KEYBOARD_E0      0x200
+#define KEYBOARD_RELEASE 0x400
+void KeyboardInit(void);
+int KeyboardGetch(void);
+
+/***************** Math ******************/
+//IEEE single precision floating point math
+#ifndef WIN32
+#define FP_Neg     __negsf2
+#define FP_Add     __addsf3
+#define FP_Sub     __subsf3
+#define FP_Mult    __mulsf3
+#define FP_Div     __divsf3
+#define FP_ToLong  __fixsfsi
+#define FP_ToFloat __floatsisf
+#define sqrt FP_Sqrt
+#define cos  FP_Cos
+#define sin  FP_Sin
+#define atan FP_Atan
+#define log  FP_Log
+#define exp  FP_Exp
+#endif
+float FP_Neg(float a_fp);
+float FP_Add(float a_fp, float b_fp);
+float FP_Sub(float a_fp, float b_fp);
+float FP_Mult(float a_fp, float b_fp);
+float FP_Div(float a_fp, float b_fp);
+long  FP_ToLong(float a_fp);
+float FP_ToFloat(long af);
+int   FP_Cmp(float a_fp, float b_fp);
+float FP_Sqrt(float a);
+float FP_Cos(float rad);
+float FP_Sin(float rad);
+float FP_Atan(float x);
+float FP_Atan2(float y, float x);
+float FP_Exp(float x);
+float FP_Log(float x);
+float FP_Pow(float x, float y);
+
+/***************** Filesys ******************/
+#ifdef INCLUDE_FILESYS
+#define FILE   OS_FILE
+#define fopen  OS_fopen
+#define fclose OS_fclose
+#define fread  OS_fread
+#define fwrite OS_fwrite
+#define fseek  OS_fseek
+#endif
+#define _FILESYS_
+typedef struct OS_FILE_s OS_FILE;
+OS_FILE *OS_fopen(char *name, char *mode);
+void OS_fclose(OS_FILE *file);
+int OS_fread(void *buffer, int size, int count, OS_FILE *file);
+int OS_fwrite(void *buffer, int size, int count, OS_FILE *file);
+int OS_fseek(OS_FILE *file, int offset, int mode);
+int OS_fmkdir(char *name);
+int OS_fdir(OS_FILE *dir, char name[64]);
+void OS_fdelete(char *name);
+int OS_flength(char *entry);
+
+/***************** Flash ******************/
+void FlashRead(uint16 *dst, uint32 byteOffset, int bytes);
+void FlashWrite(uint16 *src, uint32 byteOffset, int bytes);
+void FlashErase(uint32 byteOffset);
+
+#endif //__RTOS_H__
+
diff --git a/kernel/rtos_test.c b/kernel/rtos_test.c
new file mode 100644 (file)
index 0000000..46f50d0
--- /dev/null
@@ -0,0 +1,522 @@
+/*--------------------------------------------------------------------
+ * TITLE: Test Plasma Real Time Operating System
+ * AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
+ * DATE CREATED: 1/1/06
+ * FILENAME: rtos_test.c
+ * PROJECT: Plasma CPU core
+ * COPYRIGHT: Software placed into the public domain by the author.
+ *    Software 'as is' without warranty.  Author liable for nothing.
+ * DESCRIPTION:
+ *    Test Plasma Real Time Operating System
+ *--------------------------------------------------------------------*/
+#include "plasma.h"
+#include "rtos.h"
+#include "tcpip.h"
+
+/* Including mmu.h will cause all OS calls to use SYSCALL */
+//#include "mmu.h"
+
+//#define DLL_SETUP
+//#define DLL_CALL
+//#include "dll.h"
+
+#define SEMAPHORE_COUNT 50
+#define TIMER_COUNT     10
+
+extern void TestMathFull(void);
+
+typedef struct {
+   OS_Thread_t *MyThread[TIMER_COUNT];
+   OS_Semaphore_t *MySemaphore[SEMAPHORE_COUNT];
+   OS_Mutex_t *MyMutex;
+   OS_Timer_t *MyTimer[TIMER_COUNT];
+   OS_MQueue_t *MyQueue[TIMER_COUNT];
+   int TimerDone;
+} TestInfo_t;
+
+int Global;
+
+//******************************************************************
+static void TestCLib(void)
+{
+   char s1[80], s2[80], *ptr;
+   int rc, v1, v2, v3;
+
+   printf("TestCLib\n");
+   strcpy(s1, "Hello ");
+   memset(s2, 0, sizeof(s2));
+   strncpy(s2, "World wide", 5);
+   strcat(s1, s2);
+   strncat(s1, "!\nthing", 14);
+   printf("%s", s1);
+   rc = strcmp(s1, "Hello World!\n");
+   assert(rc == 0);
+   rc = strcmp(s1, "Hello WOrld!\n");
+   assert(rc > 0);
+   rc = strcmp(s1, "Hello world!\n");
+   assert(rc < 0);
+   rc = strncmp(s1, "Hellx", 4);
+   assert(rc == 0);
+   ptr = strstr(s1, "orl");
+   assert(ptr[0] = 'o');
+   rc = strlen(s1);
+   assert(rc == 13);
+   memcpy(s2, s1, rc+1);
+   rc = memcmp(s1, s2, 8);
+   assert(rc == 0);
+   s2[5] = 'z';
+   rc = memcmp(s1, s2, 8);
+   assert(rc != 0);
+   memset(s2, 0, 5);
+   memset(s2, 'a', 3);
+   rc = abs(-5);
+   itoa(1234, s1, 10);
+   itoa(0, s1, 10);
+   itoa(-1234, s1, 10);
+   itoa(0xabcd, s1, 16);
+   itoa(0x12ab, s1, 16);
+   sprintf(s1, "test c%c d%d 0x%x s%s End\n", 'C', 1234, 0xabcd, "String");
+   printf("%s", s1);
+   sprintf(s1, "test c%c d%6d 0x%6x s%8s End\n", 'C', 1234, 0xabcd, "String");
+   printf("%s", s1);
+   sscanf("1234 -1234 0xabcd text h", "%d %d %x %s", &v1, &v2, &v3, s1);
+   assert(v1 == 1234 && v2 == -1234 && v3 == 0xabcd);
+   assert(strcmp(s1, "text") == 0);
+   //UartScanf("%d %d", &v1, &v2);
+   //printf("v1 = %d v2 = %d\n", v1, v2);
+   printf("Done.\n");
+}
+
+//******************************************************************
+static void TestHeap(void)
+{
+   uint8 *ptrs[256], size[256], *ptr;
+   int i, j, k, value;
+
+   printf("TestHeap\n");
+   memset(ptrs, 0, sizeof(ptrs));
+   for(i = 0; i < 1000; ++i)
+   {
+      j = rand() & 255;
+      if(ptrs[j])
+      {
+         ptr = ptrs[j];
+         value = size[j];
+         for(k = 0; k < value; ++k)
+         {
+            if(ptr[k] != value)
+               printf("Error\n");
+         }
+         OS_HeapFree(ptrs[j]);
+      }
+      size[j] = (uint8)(rand() & 255);
+      ptrs[j] = OS_HeapMalloc(NULL, size[j]);
+      if(ptrs[j] == NULL)
+         printf("malloc NULL\n");
+      else
+         memset(ptrs[j], size[j], size[j]);
+   }
+   for(i = 0; i < 256; ++i)
+   {
+      if(ptrs[i])
+         OS_HeapFree(ptrs[i]);
+   }
+   printf("Done.\n");
+}
+
+//******************************************************************
+static void MyThreadMain(void *arg)
+{
+   OS_Thread_t *thread;
+   int priority;
+
+   thread = OS_ThreadSelf();
+   priority = OS_ThreadPriorityGet(thread);
+   OS_ThreadSleep(10);
+   printf("Arg=%d thread=0x%x info=0x%x priority=%d\n", 
+      (uint32)arg, thread, OS_ThreadInfoGet(thread, 0), priority);
+   OS_ThreadExit();
+}
+
+static void TestThread(void)
+{
+   OS_Thread_t *thread;
+   int i, priority;
+
+   printf("TestThread\n");
+   for(i = 0; i < 32; ++i)
+   {
+      priority = 50 + i;
+      thread = OS_ThreadCreate("MyThread", MyThreadMain, (uint32*)i, priority, 0);
+      OS_ThreadInfoSet(thread, 0, (void*)(0xabcd + i));
+      //printf("Created thread 0x%x\n", thread);
+   }
+
+   thread = OS_ThreadSelf();
+   priority = OS_ThreadPriorityGet(thread);
+   printf("Priority = %d\n", priority);
+   OS_ThreadPrioritySet(thread, 200);
+   printf("Priority = %d\n", OS_ThreadPriorityGet(thread));
+   OS_ThreadPrioritySet(thread, priority);
+
+   printf("Thread time = %d\n", OS_ThreadTime());
+   OS_ThreadSleep(100);
+   printf("Thread time = %d\n", OS_ThreadTime());
+}
+
+//******************************************************************
+static void TestSemThread(void *arg)
+{
+   int i;
+   TestInfo_t *info = (TestInfo_t*)arg;
+
+   for(i = 0; i < SEMAPHORE_COUNT/2; ++i)
+   {
+      printf("s");
+      OS_SemaphorePend(info->MySemaphore[i], OS_WAIT_FOREVER);
+      OS_SemaphorePost(info->MySemaphore[i + SEMAPHORE_COUNT/2]);
+   }
+   OS_ThreadExit();
+}
+
+static void TestSemaphore(void)
+{
+   int i, rc;
+   TestInfo_t info;
+   printf("TestSemaphore\n");
+   for(i = 0; i < SEMAPHORE_COUNT; ++i)
+   {
+      info.MySemaphore[i] = OS_SemaphoreCreate("MySem", 0);
+      //printf("sem[%d]=0x%x\n", i, MySemaphore[i]);
+   }
+
+   OS_ThreadCreate("TestSem", TestSemThread, &info, 50, 0);
+
+   for(i = 0; i < SEMAPHORE_COUNT/2; ++i)
+   {
+      printf("S");
+      OS_SemaphorePost(info.MySemaphore[i]);
+      rc = OS_SemaphorePend(info.MySemaphore[i + SEMAPHORE_COUNT/2], 500);
+      assert(rc == 0);
+   }
+
+   printf(":");
+   rc = OS_SemaphorePend(info.MySemaphore[0], 10);
+   assert(rc != 0);
+   printf(":");
+   OS_SemaphorePend(info.MySemaphore[0], 100);
+   printf(":");
+
+   for(i = 0; i < SEMAPHORE_COUNT; ++i)
+      OS_SemaphoreDelete(info.MySemaphore[i]);
+
+   printf("\nDone.\n");
+}
+
+//******************************************************************
+static void TestMutexThread(void *arg)
+{
+   TestInfo_t *info = (TestInfo_t*)arg;
+
+   printf("Waiting for mutex\n");
+   OS_MutexPend(info->MyMutex);
+   printf("Have Mutex1\n");
+   OS_MutexPend(info->MyMutex);
+   printf("Have Mutex2\n");
+   OS_MutexPend(info->MyMutex);
+   printf("Have Mutex3\n");
+
+   OS_ThreadSleep(100);
+
+   OS_MutexPost(info->MyMutex);
+   OS_MutexPost(info->MyMutex);
+   OS_MutexPost(info->MyMutex);
+
+   OS_ThreadExit();
+}
+
+static void TestMutex(void)
+{
+   TestInfo_t info;
+   printf("TestMutex\n");
+   info.MyMutex = OS_MutexCreate("MyMutex");
+   OS_MutexPend(info.MyMutex);
+   OS_MutexPend(info.MyMutex);
+   OS_MutexPend(info.MyMutex);
+
+   OS_ThreadSleep(100);
+
+   OS_ThreadCreate("TestMutex", TestMutexThread, &info, 50, 0);
+
+   OS_ThreadSleep(50);
+   OS_MutexPost(info.MyMutex);
+   OS_MutexPost(info.MyMutex);
+   OS_MutexPost(info.MyMutex);
+
+   printf("Try get mutex\n");
+   OS_MutexPend(info.MyMutex);
+   printf("Gotit\n");
+
+   OS_MutexDelete(info.MyMutex);
+   printf("Done.\n");
+}
+
+//******************************************************************
+static void TestMQueue(void)
+{
+   OS_MQueue_t *mqueue;
+   char data[16];
+   int i, rc;
+
+   printf("TestMQueue\n");
+   mqueue = OS_MQueueCreate("MyMQueue", 10, 16);
+   strcpy(data, "Test0");
+   for(i = 0; i < 16; ++i)
+   {
+      data[4] = (char)('0' + i);
+      OS_MQueueSend(mqueue, data);
+   }
+   for(i = 0; i < 16; ++i)
+   {
+      memset(data, 0, sizeof(data));
+      rc = OS_MQueueGet(mqueue, data, 20);
+      if(rc == 0)
+         printf("message=(%s)\n", data);
+      else
+         printf("timeout\n");
+   }
+
+   OS_MQueueDelete(mqueue);
+   printf("Done.\n");
+}
+
+//******************************************************************
+static void TestTimerThread(void *arg)
+{
+   int index;
+   uint32 data[4];
+   OS_Timer_t *timer;
+   TestInfo_t *info = (TestInfo_t*)arg;
+
+   //printf("TestTimerThread\n");
+
+   OS_ThreadSleep(1);
+   index = (int)OS_ThreadInfoGet(OS_ThreadSelf(), 0);
+   //printf("index=%d\n", index);
+   OS_MQueueGet(info->MyQueue[index], data, 1000);
+   timer = (OS_Timer_t*)data[1];
+   printf("%d ", data[2]);
+   OS_MQueueGet(info->MyQueue[index], data, 1000);
+   printf("%d ", data[2]);
+   ++info->TimerDone;
+   OS_ThreadExit();
+}
+
+static void TestTimer(void)
+{
+   int i;
+   TestInfo_t info;
+
+   printf("TestTimer\n");
+   info.TimerDone = 0;
+   for(i = 0; i < TIMER_COUNT; ++i)
+   {
+      info.MyQueue[i] = OS_MQueueCreate("MyQueue", 10, 16);
+      info.MyTimer[i] = OS_TimerCreate("MyTimer", info.MyQueue[i], i);
+      info.MyThread[i] = OS_ThreadCreate("TimerTest", TestTimerThread, &info, 50, 0);
+      OS_ThreadInfoSet(info.MyThread[i], 0, (void*)i);
+      OS_TimerStart(info.MyTimer[i], 10+i*2, 220+i);
+   }
+
+   while(info.TimerDone < TIMER_COUNT)
+      OS_ThreadSleep(10);
+
+   for(i = 0; i < TIMER_COUNT; ++i)
+   {
+      OS_MQueueDelete(info.MyQueue[i]);
+      OS_TimerDelete(info.MyTimer[i]);
+   }
+
+   printf("Done.\n");
+}
+
+//******************************************************************
+#if 1
+void TestMath(void)
+{
+   int i;
+   float a, b, sum, diff, mult, div;
+   uint32 compare;
+
+   //Check add subtract multiply and divide
+   for(i = -4; i < 4; ++i)
+   {
+      a = (float)(i * 10 + (float)63.2);
+      b = (float)(-i * 5 + (float)3.5);
+      sum = a + b;
+      diff = a - b;
+      mult = a * b;
+      div = a / b;
+      printf("a=%dE-3 b=%dE-3 sum=%dE-3 diff=%dE-3 mult=%dE-3 div=%dE-3\n",
+         (int)(a*(float)1000), (int)(b*(float)1000), 
+         (int)(sum*(float)1000), (int)(diff*(float)1000),
+         (int)(mult*(float)1000), (int)(div*(float)1000));
+   }
+
+   //Comparisons
+   b = (float)2.0;
+   compare = 0;
+   for(i = 1; i < 4; ++i)
+   {
+      a = (float)i;
+      compare = (compare << 1) | (a == b);
+      compare = (compare << 1) | (a != b);
+      compare = (compare << 1) | (a <  b);
+      compare = (compare << 1) | (a <= b);
+      compare = (compare << 1) | (a >  b);
+      compare = (compare << 1) | (a >= b);
+   }
+   printf("Compare = %8x %s\n", compare, 
+      compare==0x1c953 ? "OK" : "ERROR");
+
+   //Cosine
+   for(a = (float)0.0; a <= (float)(3.1415); a += (float)(3.1415/16.0))
+   {
+      b = FP_Cos(a);
+      printf("cos(%4dE-3) = %4dE-3\n", 
+         (int)(a*(float)1000.0), (int)(b*(float)1000.0));
+   }
+}
+#endif
+
+//******************************************************************
+#ifndef WIN32
+static void MySyscall(void *arg)
+{
+   uint32 *stack = arg;
+   stack[STACK_EPC] += 4;  //skip over SYSCALL
+   printf("Inside MySyscall %d\n", stack[28/4]);
+}
+
+void TestSyscall(void)
+{
+   OS_InterruptRegister((uint32)(1<<31), MySyscall);
+   OS_Syscall(57);
+   OS_ThreadSleep(1);
+   printf("Done\n");
+}
+#endif
+
+#ifdef __MMU_ENUM_H__
+void TestProcess(void)
+{
+   OS_Process_t *process;
+   process = (OS_Process_t*)OS_HeapMalloc(NULL, sizeof(OS_Process_t));
+   process->name = "test";
+   process->funcPtr = MainThread;
+   process->arg = NULL;
+   process->priority = 200;
+   process->stackSize = 1024*32;
+   process->heapSize = 1024*128;
+   process->processId = 1;
+   process->semaphoreDone = OS_SemaphoreCreate("processDone", 0);
+   printf("Creating process\n");
+   OS_MMUProcessCreate(process);
+   OS_SemaphorePend(process->semaphoreDone, OS_WAIT_FOREVER);
+   printf("Process done\n");
+   OS_MMUProcessDelete(process);
+}
+#endif
+
+
+//******************************************************************
+void MMUTest(void);
+void HtmlThread(void *arg);
+void ConsoleInit(void);
+void exit(int);
+uint8 macAddress[] =  {0x00, 0x10, 0xdd, 0xce, 0x15, 0xd4};
+
+
+void MainThread(void *Arg)
+{
+   int ch, i, display=1;
+   (void)Arg;
+#ifdef __MMU_ENUM_H__
+   OS_MMUInit();
+#endif
+
+#ifdef INCLUDE_ETH
+   EthernetInit(macAddress);
+   IPInit(EthernetTransmit, macAddress, "plasma");
+   HtmlInit(1);
+#endif
+
+#ifdef INCLUDE_HTML
+   IPInit(NULL, macAddress, "plasma");
+   HtmlInit(1);
+#endif
+
+#ifdef INCLUDE_CONSOLE
+   ConsoleInit();
+#endif
+
+   for(;;)
+   {
+      if(display)
+      {
+         printf("\n");
+         printf("1 CLib\n");
+         printf("2 Heap\n");
+         printf("3 Thread\n");
+         printf("4 Semaphore\n");
+         printf("5 Mutex\n");
+         printf("6 MQueue\n");
+         printf("7 Timer\n");
+         printf("8 Math\n");
+         printf("9 Syscall\n");
+#ifdef __MMU_ENUM_H__
+         printf("p MMU Process\n");
+#endif
+      }
+      printf("> ");
+      display = 1;
+      ch = UartRead();
+      printf("%c\n", ch);
+      switch(ch)
+      {
+#ifdef WIN32
+      case '0': exit(0);
+#endif
+      case '1': TestCLib(); break;
+      case '2': TestHeap(); break;
+      case '3': TestThread(); break;
+      case '4': TestSemaphore(); break;
+      case '5': TestMutex(); break;
+      case '6': TestMQueue(); break;
+      case '7': TestTimer(); break;
+      case '8': TestMath(); break;
+#ifndef WIN32
+      case '9': TestSyscall(); break;
+#endif
+#ifdef __MMU_ENUM_H__
+      case 'p': TestProcess(); break;
+#endif
+#ifdef WIN32
+      case 'm': TestMathFull(); break;
+#endif
+      case 'g': printf("Global=%d\n", ++Global); break;
+      default: 
+         printf("E");
+         display = 0;
+         for(i = 0; i < 30; ++i)
+         {
+            while(kbhit())
+               ch = UartRead();
+            OS_ThreadSleep(1);
+         }
+         break;
+      }
+   }
+}
+
+
diff --git a/kernel/tcpip.c b/kernel/tcpip.c
new file mode 100644 (file)
index 0000000..b5e4c63
--- /dev/null
@@ -0,0 +1,1737 @@
+/*--------------------------------------------------------------------\r
+ * TITLE: Plasma TCP/IP Protocol Stack\r
+ * AUTHOR: Steve Rhoads (rhoadss@yahoo.com)\r
+ * DATE CREATED: 4/22/06\r
+ * FILENAME: tcpip.c\r
+ * PROJECT: Plasma CPU core\r
+ * COPYRIGHT: Software placed into the public domain by the author.\r
+ *    Software 'as is' without warranty.  Author liable for nothing.\r
+ * DESCRIPTION:\r
+ *    Plasma TCP/IP Protocol Stack\r
+ *\r
+ *    Possible call stack when receiving a packet:\r
+ *       IPMainThread()\r
+ *          IPProcessEthernetPacket()\r
+ *             IPProcessTCPPacket()\r
+ *                TCPSendPacket()\r
+ *                   IPSendPacket()\r
+ *                      IPChecksum()\r
+ *                      IPSendFrame()\r
+ *                         FrameInsert()\r
+ *--------------------------------------------------------------------*/\r
+#ifdef WIN32\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include <assert.h>\r
+#define _LIBC\r
+#endif\r
+#include "rtos.h"\r
+#define IPPRINTF\r
+#include "tcpip.h"\r
+\r
+\r
+//ETHER FIELD                 OFFSET   LENGTH   VALUE\r
+#define ETHERNET_DEST         0        //6\r
+#define ETHERNET_SOURCE       6        //6\r
+#define ETHERNET_FRAME_TYPE   12       //2      IP=0x0800; ARP=0x0806\r
+\r
+//ARP   FIELD                 OFFSET   LENGTH   VALUE\r
+#define ARP_HARD_TYPE         14       //2      0x0001\r
+#define ARP_PROT_TYPE         16       //2      0x0800\r
+#define ARP_HARD_SIZE         18       //1      0x06\r
+#define ARP_PROT_SIZE         19       //1      0x04\r
+#define ARP_OP                20       //2      ARP=1;ARPreply=2\r
+#define ARP_ETHERNET_SENDER   22       //6\r
+#define ARP_IP_SENDER         28       //4\r
+#define ARP_ETHERNET_TARGET   32       //6\r
+#define ARP_IP_TARGET         38       //4\r
+#define ARP_PAD               42       //18     0\r
+\r
+//IP    FIELD                 OFFSET   LENGTH   VALUE\r
+#define IP_VERSION_LENGTH     14       //1      0x45\r
+#define IP_TYPE_OF_SERVICE    15       //1      0x00\r
+#define IP_LENGTH             16       //2\r
+#define IP_ID16               18       //2\r
+#define IP_FRAG_OFFSET        20       //2\r
+#define IP_TIME_TO_LIVE       22       //1      0x80\r
+#define IP_PROTOCOL           23       //1      TCP=0x06;PING=0x01;UDP=0x11\r
+#define IP_CHECKSUM           24       //2\r
+#define IP_SOURCE             26       //4\r
+#define IP_DEST               30       //4\r
+\r
+//PSEUDO FIELD                OFFSET   LENGTH   VALUE\r
+#define PSEUDO_IP_SOURCE      0        //4\r
+#define PSEUDO_IP_DEST        4        //4\r
+#define PSEUDO_ZERO           8        //1      0\r
+#define PSEUDO_IP_PROTOCOL    9        //1\r
+#define PSEUDO_LENGTH         10       //2\r
+\r
+//UDP   FIELD                 OFFSET   LENGTH   VALUE\r
+#define UDP_SOURCE_PORT       34       //2\r
+#define UDP_DEST_PORT         36       //2\r
+#define UDP_LENGTH            38       //2\r
+#define UDP_CHECKSUM          40       //2\r
+#define UDP_DATA              42\r
+\r
+//DHCP  FIELD                 OFFSET   LENGTH   VALUE\r
+#define DHCP_OPCODE           42       //1      REQUEST=1;REPLY=2\r
+#define DHCP_HW_TYPE          43       //1      1\r
+#define DHCP_HW_LEN           44       //1      6\r
+#define DHCP_HOP_COUNT        45       //1      0\r
+#define DHCP_TRANS_ID         46       //4\r
+#define DHCP_NUM_SEC          50       //2      0\r
+#define DHCP_UNUSED           52       //2\r
+#define DHCP_CLIENT_IP        54       //4\r
+#define DHCP_YOUR_IP          58       //4\r
+#define DHCP_SERVER_IP        62       //4\r
+#define DHCP_GATEWAY_IP       66       //4\r
+#define DHCP_CLIENT_ETHERNET  70       //16\r
+#define DHCP_SERVER_NAME      86       //64\r
+#define DHCP_BOOT_FILENAME    150      //128\r
+#define DHCP_MAGIC_COOKIE     278      //4      0x63825363\r
+#define DHCP_OPTIONS          282      //N\r
+\r
+#define DHCP_MESSAGE_TYPE     53       //1 type\r
+#define DHCP_DISCOVER         1\r
+#define DHCP_OFFER            2\r
+#define DHCP_REQUEST          3\r
+#define DHCP_ACK              5\r
+#define DHCP_REQUEST_IP       50       //4 ip\r
+#define DHCP_REQUEST_SERV_IP  54       //4 ip\r
+#define DHCP_CLIENT_ID        61       //7 1 ethernet\r
+#define DHCP_HOST_NAME        12       //6 plasma\r
+#define DHCP_PARAMS           55       //4 1=subnet; 15=domain_name; 3=router; 6=dns\r
+#define DHCP_PARAM_SUBNET     1\r
+#define DHCP_PARAM_ROUTER     3\r
+#define DHCP_PARAM_DNS        6\r
+#define DHCP_END_OPTION       0xff\r
+\r
+//DHCP  FIELD                 OFFSET   LENGTH   VALUE\r
+#define DNS_ID                0        //2    \r
+#define DNS_FLAGS             2        //2      \r
+#define DNS_NUM_QUESTIONS     4        //2      1 \r
+#define DNS_NUM_ANSWERS_RR    6        //2      0/1\r
+#define DNS_NUM_AUTHORITY_RR  8        //2      0 \r
+#define DNS_NUM_ADDITIONAL_RR 10       //2      0\r
+#define DNS_QUESTIONS         12       //2   \r
+\r
+#define DNS_FLAGS_RESPONSE    0x8000\r
+#define DNS_FLAGS_RECURSIVE   0x0100\r
+#define DNS_FLAGS_ERROR       0x0003\r
+#define DNS_FLAGS_OK          0x0000\r
+#define DNS_QUERY_TYPE_IP     1\r
+#define DNS_QUERY_CLASS       1\r
+#define DNS_PORT              53\r
+\r
+//TCP   FIELD                 OFFSET   LENGTH   VALUE\r
+#define TCP_SOURCE_PORT       34       //2\r
+#define TCP_DEST_PORT         36       //2\r
+#define TCP_SEQ               38       //4\r
+#define TCP_ACK               42       //4\r
+#define TCP_HEADER_LENGTH     46       //1      0x50\r
+#define TCP_FLAGS             47       //1      SYNC=0x2;ACK=0x10;FIN=0x1\r
+#define TCP_WINDOW_SIZE       48       //2\r
+#define TCP_CHECKSUM          50       //2\r
+#define TCP_URGENT_POINTER    52       //2\r
+#define TCP_DATA              54       //length-N\r
+\r
+#define TCP_FLAGS_FIN         1\r
+#define TCP_FLAGS_SYN         2\r
+#define TCP_FLAGS_RST         4\r
+#define TCP_FLAGS_PSH         8\r
+#define TCP_FLAGS_ACK         16\r
+\r
+//PING  FIELD                 OFFSET   LENGTH   VALUE\r
+#define PING_TYPE             34       //1      SEND=8;REPLY=0\r
+#define PING_CODE             35       //1      0\r
+#define PING_CHECKSUM         36       //2\r
+#define PING_ID               38       //2\r
+#define PING_SEQUENCE         40       //2\r
+#define PING_DATA             44\r
+\r
+static void IPClose2(IPSocket *Socket);\r
+static void IPArp(unsigned char ipAddress[4]);\r
+\r
+typedef struct ArpCache_s {\r
+   unsigned char ip[4];\r
+   unsigned char mac[6];\r
+} ArpCache_t;\r
+static ArpCache_t ArpCache[10];\r
+static int ArpCacheIndex;\r
+\r
+static uint8 ethernetAddressGateway[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};\r
+#ifndef WIN32\r
+static uint8 ethernetAddressPlasma[] =  {0x00, 0x10, 0xdd, 0xce, 0x15, 0xd4};\r
+#else\r
+static uint8 ethernetAddressPlasma[] =  {0x00, 0x10, 0xdd, 0xce, 0x15, 0xd5};\r
+#endif\r
+\r
+static uint8 ipAddressPlasma[] =  {192, 168, 100, 10};      //changed by DHCP\r
+static uint8 ipAddressGateway[] = {0x00, 0x00, 0x00, 0x00}; //changed by DHCP\r
+static uint32 ipAddressDns;                                 //changed by DHCP\r
+\r
+static OS_Mutex_t *IPMutex;\r
+static int FrameFreeCount;\r
+static IPFrame *FrameFreeHead;\r
+static IPFrame *FrameSendHead;\r
+static IPFrame *FrameSendTail;\r
+static IPFrame *FrameResendHead;\r
+static IPFrame *FrameResendTail;\r
+static IPSocket *SocketHead;\r
+static uint32 Seconds;\r
+static int DhcpRetrySeconds;\r
+static IPFuncPtr FrameSendFunc;\r
+static OS_MQueue_t *IPMQueue;\r
+static OS_Thread_t *IPThread;\r
+int IPVerbose=1;\r
+\r
+static const unsigned char dhcpDiscover[] = {\r
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff,             //dest\r
+   0x00, 0x10, 0xdd, 0xce, 0x15, 0xd4,             //src\r
+   0x08, 0x00, \r
+   0x45, 0x00, 0x01, 0x48, 0x2e, 0xf5, 0x00, 0x00, //ip\r
+   0x80, 0x11, 0x0a, 0xb1, 0x00, 0x00, 0x00, 0x00, \r
+   0xff, 0xff, 0xff, 0xff,\r
+   0x00, 0x44, 0x00, 0x43, 0x01, 0x34, 0x45, 0x66, //udp\r
+   0x01, 0x01, 0x06, 0x00, 0x69, 0x26, 0xb5, 0x52  //dhcp\r
+};\r
+\r
+static unsigned char dhcpOptions[] = {\r
+   0x63, 0x82, 0x53, 0x63,      //cookie\r
+   0x35, 0x01, 0x01,            //DHCP Discover\r
+   0x3d, 0x07, 0x01, 0x00, 0x10, 0xdd, 0xce, 0x15, 0xd4, //Client identifier\r
+#ifndef WIN32\r
+   0x0c, 0x06, 'p', 'l', 'a', 's', 'm', 'a',             //Host name\r
+#else\r
+   0x0c, 0x06, 'p', 'l', 'a', 's', 'm', 'b',             //Host name\r
+#endif\r
+   0x37, 0x03, DHCP_PARAM_SUBNET, DHCP_PARAM_ROUTER, DHCP_PARAM_DNS, //Parameters\r
+   DHCP_END_OPTION\r
+};\r
+\r
+\r
+//Get a free frame; can be called from an ISR\r
+IPFrame *IPFrameGet(int freeCount)\r
+{\r
+   IPFrame *frame=NULL;\r
+   uint32 state;\r
+\r
+   state = OS_CriticalBegin();\r
+   if(FrameFreeCount > freeCount)\r
+   {\r
+      frame = FrameFreeHead;\r
+      if(FrameFreeHead)\r
+      {\r
+         FrameFreeHead = FrameFreeHead->next;\r
+         --FrameFreeCount;\r
+      }\r
+   }\r
+   OS_CriticalEnd(state);\r
+   if(frame)\r
+   {\r
+      assert(frame->state == 0);\r
+      frame->state = 1;\r
+   }\r
+   return frame;\r
+}\r
+\r
+\r
+static void FrameFree(IPFrame *frame)\r
+{\r
+   uint32 state;\r
+\r
+   assert(frame->state == 1);\r
+   frame->state = 0;\r
+   state = OS_CriticalBegin();\r
+   frame->next = FrameFreeHead;\r
+   FrameFreeHead = frame;\r
+   ++FrameFreeCount;\r
+   OS_CriticalEnd(state);\r
+}\r
+\r
+\r
+static void FrameInsert(IPFrame **head, IPFrame **tail, IPFrame *frame)\r
+{\r
+   assert(frame->state == 1);\r
+   frame->state = 2;\r
+   OS_MutexPend(IPMutex);\r
+   frame->prev = NULL;\r
+   frame->next = *head;\r
+   if(*head)\r
+      (*head)->prev = frame;\r
+   *head = frame;\r
+   if(*tail == NULL)\r
+      *tail = frame;\r
+   OS_MutexPost(IPMutex);\r
+}\r
+\r
+\r
+static void FrameRemove(IPFrame **head, IPFrame **tail, IPFrame *frame)\r
+{\r
+   assert(frame->state == 2);\r
+   if(frame->state != 2)\r
+   {\r
+      printf("frame->state=%d\n", frame->state);\r
+      return;\r
+   }\r
+   frame->state = 1;\r
+   if(frame->prev)\r
+      frame->prev->next = frame->next;\r
+   else\r
+      *head = frame->next;\r
+   if(frame->next)\r
+      frame->next->prev = frame->prev;\r
+   else\r
+      *tail = frame->prev;\r
+   frame->prev = NULL;\r
+   frame->next = NULL;\r
+}\r
+\r
+\r
+static int IPChecksum(int checksum, const unsigned char *data, int length)\r
+{\r
+   int i;\r
+   checksum = ~checksum & 0xffff;\r
+   for(i = 0; i < length-1; i += 2)\r
+   {\r
+      checksum += (data[i] << 8) | data[i+1];\r
+   }\r
+   if(i < length)\r
+      checksum += data[i] << 8;\r
+   while(checksum >> 16)\r
+      checksum = (checksum & 0xffff) + (checksum >> 16);\r
+   checksum = ~checksum & 0xffff;\r
+   return checksum;\r
+}\r
+\r
+\r
+static int EthernetVerifyChecksums(const unsigned char *packet, int length)\r
+{\r
+   int checksum, length2;\r
+   unsigned char pseudo[12];\r
+\r
+   //Calculate checksums\r
+   if(packet[ETHERNET_FRAME_TYPE+1] == 0x00)  //IP\r
+   {\r
+      checksum = IPChecksum(0xffff, packet+IP_VERSION_LENGTH, 20);\r
+      if(checksum)\r
+         return -1;\r
+      if(packet[IP_PROTOCOL] == 0x01)         //PING\r
+      {\r
+         checksum = IPChecksum(0xffff, packet+PING_TYPE, length-PING_TYPE);\r
+      }\r
+      else if(packet[IP_PROTOCOL] == 0x11)    //UDP\r
+      {\r
+         if(packet[UDP_CHECKSUM] == 0 && packet[UDP_CHECKSUM+1] == 0)\r
+            return 0;\r
+         memcpy(pseudo+PSEUDO_IP_SOURCE, packet+IP_SOURCE, 4);\r
+         memcpy(pseudo+PSEUDO_IP_DEST, packet+IP_DEST, 4);\r
+         pseudo[PSEUDO_ZERO] = 0;\r
+         pseudo[PSEUDO_IP_PROTOCOL] = packet[IP_PROTOCOL];\r
+         memcpy(pseudo+PSEUDO_LENGTH, packet+UDP_LENGTH, 2);\r
+         checksum = IPChecksum(0xffff, pseudo, 12);\r
+         length2 = (packet[UDP_LENGTH] << 8) + packet[UDP_LENGTH+1];\r
+         checksum = IPChecksum(checksum, packet+UDP_SOURCE_PORT, length);\r
+      }\r
+      else if(packet[IP_PROTOCOL] == 0x06)    //TCP\r
+      {\r
+         memcpy(pseudo+PSEUDO_IP_SOURCE, packet+IP_SOURCE, 4);\r
+         memcpy(pseudo+PSEUDO_IP_DEST, packet+IP_DEST, 4);\r
+         pseudo[PSEUDO_ZERO] = 0;\r
+         pseudo[PSEUDO_IP_PROTOCOL] = packet[IP_PROTOCOL];\r
+         length = (packet[IP_LENGTH] << 8) + packet[IP_LENGTH+1];\r
+         length2 = length - 20;\r
+         pseudo[PSEUDO_LENGTH] = (unsigned char)(length2 >> 8);\r
+         pseudo[PSEUDO_LENGTH+1] = (unsigned char)length2;\r
+         checksum = IPChecksum(0xffff, pseudo, 12);\r
+         checksum = IPChecksum(checksum, packet+TCP_SOURCE_PORT, length2);\r
+      }\r
+      if(checksum)\r
+         return -1;\r
+   }\r
+   return 0;\r
+}\r
+\r
+\r
+static void IPFrameReschedule(IPFrame *frame)\r
+{\r
+   int length;\r
+   length = frame->length - TCP_DATA;\r
+   if(frame->packet[TCP_FLAGS] & (TCP_FLAGS_FIN | TCP_FLAGS_SYN))\r
+      ++length;\r
+   if(frame->socket == NULL || frame->socket->state == IP_UDP || length == 0 ||\r
+      frame->socket->state == IP_PING || ++frame->retryCnt > 4)\r
+   {\r
+      FrameFree(frame);     //can't be ACK'ed\r
+   }\r
+#ifdef WIN32\r
+   else if(FrameFreeCount < FRAME_COUNT_SYNC)\r
+   {\r
+      FrameFree(frame);     //can't be ACK'ed\r
+   }\r
+#endif\r
+   else\r
+   {\r
+      //Put on resend list until TCP ACK'ed\r
+      frame->timeout = (short)(RETRANSMIT_TIME * frame->retryCnt);\r
+      FrameInsert(&FrameResendHead, &FrameResendTail, frame);\r
+   }\r
+}\r
+\r
+\r
+static void IPSendFrame(IPFrame *frame)\r
+{\r
+   uint32 message[4];\r
+   int i;\r
+   unsigned char *packet=frame->packet;\r
+\r
+   //Check if MAC address unknown\r
+   if(packet[ETHERNET_FRAME_TYPE+1] == 0x00 && //IP\r
+      packet[ETHERNET_DEST] == 0xff && packet[IP_DEST] != 0xff)\r
+   {\r
+      for(i = 0; i < sizeof(ArpCache) / sizeof(ArpCache_t); ++i)\r
+      {\r
+         if(memcmp(packet+IP_DEST, ArpCache[i].ip, 4) == 0)\r
+         {\r
+            memcpy(packet+ETHERNET_DEST, ArpCache[i].mac, 6);\r
+            if(frame->socket)\r
+               memcpy(frame->socket->headerSend+ETHERNET_DEST, ArpCache[i].mac, 6);\r
+            break;\r
+         }\r
+      }\r
+      if(packet[ETHERNET_DEST] == 0xff)\r
+         IPArp(packet+IP_DEST);\r
+   }\r
+\r
+   if(FrameSendFunc)\r
+   {\r
+      //Single threaded\r
+      FrameSendFunc(frame->packet, frame->length);\r
+      IPFrameReschedule(frame);\r
+   }\r
+   else\r
+   {\r
+      //Add Packet to send queue\r
+      FrameInsert(&FrameSendHead, &FrameSendTail, frame);\r
+\r
+      //Wakeup sender thread\r
+      message[0] = 2;\r
+      OS_MQueueSend(IPMQueue, message);\r
+   }\r
+}\r
+\r
+\r
+static void IPSendPacket(IPSocket *socket, IPFrame *frame, int length)\r
+{\r
+   int checksum, length2=length;\r
+   unsigned char pseudo[12], *packet=frame->packet;\r
+\r
+   frame->length = (uint16)length;\r
+\r
+   //Calculate checksums\r
+   if(packet[ETHERNET_FRAME_TYPE+1] == 0x00)  //IP\r
+   {\r
+      length2 = length - IP_VERSION_LENGTH;\r
+      packet[IP_LENGTH] = (uint8)(length2 >> 8);\r
+      packet[IP_LENGTH+1] = (uint8)length2;\r
+      memset(packet+IP_CHECKSUM, 0, 2);\r
+      checksum = IPChecksum(0xffff, packet+IP_VERSION_LENGTH, 20);\r
+      packet[IP_CHECKSUM] = (unsigned char)(checksum >> 8);\r
+      packet[IP_CHECKSUM+1] = (unsigned char)checksum;\r
+      if(packet[IP_PROTOCOL] == 0x01)         //ICMP & PING\r
+      {\r
+         memset(packet+PING_CHECKSUM, 0, 2);\r
+         checksum = IPChecksum(0xffff, packet+PING_TYPE, length-PING_TYPE);\r
+         packet[PING_CHECKSUM] = (unsigned char)(checksum >> 8);\r
+         packet[PING_CHECKSUM+1] = (unsigned char)checksum;\r
+      }\r
+      else if(packet[IP_PROTOCOL] == 0x11)    //UDP\r
+      {\r
+         length2 = length - UDP_SOURCE_PORT;\r
+         packet[UDP_LENGTH] = (uint8)(length2 >> 8);\r
+         packet[UDP_LENGTH+1] = (uint8)length2;\r
+         memcpy(pseudo+PSEUDO_IP_SOURCE, packet+IP_SOURCE, 4);\r
+         memcpy(pseudo+PSEUDO_IP_DEST, packet+IP_DEST, 4);\r
+         pseudo[PSEUDO_ZERO] = 0;\r
+         pseudo[PSEUDO_IP_PROTOCOL] = packet[IP_PROTOCOL];\r
+         memcpy(pseudo+PSEUDO_LENGTH, packet+UDP_LENGTH, 2);\r
+         checksum = IPChecksum(0xffff, pseudo, 12);\r
+         memset(packet+UDP_CHECKSUM, 0, 2);\r
+         length2 = (packet[UDP_LENGTH] << 8) + packet[UDP_LENGTH+1];\r
+         checksum = IPChecksum(checksum, packet+UDP_SOURCE_PORT, length2);\r
+         packet[UDP_CHECKSUM] = (unsigned char)(checksum >> 8);\r
+         packet[UDP_CHECKSUM+1] = (unsigned char)checksum;\r
+      }\r
+      else if(packet[IP_PROTOCOL] == 0x06)    //TCP\r
+      {\r
+         memcpy(pseudo+PSEUDO_IP_SOURCE, packet+IP_SOURCE, 4);\r
+         memcpy(pseudo+PSEUDO_IP_DEST, packet+IP_DEST, 4);\r
+         pseudo[PSEUDO_ZERO] = 0;\r
+         pseudo[PSEUDO_IP_PROTOCOL] = packet[IP_PROTOCOL];\r
+         length2 = (packet[IP_LENGTH] << 8) + packet[IP_LENGTH+1];\r
+         length2 = length2 - 20;\r
+         pseudo[PSEUDO_LENGTH] = (unsigned char)(length2 >> 8);\r
+         pseudo[PSEUDO_LENGTH+1] = (unsigned char)length2;\r
+         checksum = IPChecksum(0xffff, pseudo, 12);\r
+         memset(packet+TCP_CHECKSUM, 0, 2);\r
+         checksum = IPChecksum(checksum, packet+TCP_SOURCE_PORT, length2);\r
+         packet[TCP_CHECKSUM] = (unsigned char)(checksum >> 8);\r
+         packet[TCP_CHECKSUM+1] = (unsigned char)checksum;\r
+      }\r
+   }\r
+\r
+   length2 = length - TCP_DATA;\r
+   if(socket && (packet[TCP_FLAGS] & (TCP_FLAGS_FIN | TCP_FLAGS_SYN)))\r
+      length2 = 1;\r
+   frame->socket = socket;\r
+   frame->timeout = 0;\r
+   frame->retryCnt = 0;\r
+   if(socket)\r
+      frame->seqEnd = socket->seq + length2;\r
+   IPSendFrame(frame);\r
+}\r
+\r
+\r
+static void TCPSendPacket(IPSocket *socket, IPFrame *frame, int length)\r
+{\r
+   uint8 *packet = frame->packet;\r
+   int flags, count;\r
+\r
+   flags = packet[TCP_FLAGS];\r
+   memcpy(packet, socket->headerSend, TCP_SEQ);\r
+   packet[TCP_FLAGS] = (uint8)flags;\r
+   if(flags & TCP_FLAGS_SYN)\r
+      packet[TCP_HEADER_LENGTH] = 0x60;  //set maximum segment size\r
+   else\r
+      packet[TCP_HEADER_LENGTH] = 0x50;\r
+   packet[TCP_SEQ]   = (uint8)(socket->seq >> 24);\r
+   packet[TCP_SEQ+1] = (uint8)(socket->seq >> 16);\r
+   packet[TCP_SEQ+2] = (uint8)(socket->seq >> 8);\r
+   packet[TCP_SEQ+3] = (uint8)socket->seq;\r
+   packet[TCP_ACK]   = (uint8)(socket->ack >> 24);\r
+   packet[TCP_ACK+1] = (uint8)(socket->ack >> 16);\r
+   packet[TCP_ACK+2] = (uint8)(socket->ack >> 8);\r
+   packet[TCP_ACK+3] = (uint8)socket->ack;\r
+   count = RECEIVE_WINDOW - (socket->ack - socket->ackProcessed);\r
+   if(count < 0)\r
+      count = 0;\r
+   packet[TCP_WINDOW_SIZE] = (uint8)(count >> 8);\r
+   packet[TCP_WINDOW_SIZE+1] = (uint8)count;\r
+   packet[TCP_URGENT_POINTER] = 0;\r
+   packet[TCP_URGENT_POINTER+1] = 0;\r
+   IPSendPacket(socket, frame, length);\r
+}\r
+\r
+\r
+static void EthernetCreateResponse(unsigned char *packetOut,\r
+                                   const unsigned char *packet,\r
+                                   int length)\r
+{\r
+   //Swap destination and source fields\r
+   memcpy(packetOut, packet, length);\r
+   memcpy(packetOut+ETHERNET_DEST, packet+ETHERNET_SOURCE, 6);\r
+   memcpy(packetOut+ETHERNET_SOURCE, packet+ETHERNET_DEST, 6);\r
+   if(packet[ETHERNET_FRAME_TYPE+1] == 0x00)  //IP\r
+   {\r
+      memcpy(packetOut+IP_SOURCE, packet+IP_DEST, 4);\r
+      memcpy(packetOut+IP_DEST, packet+IP_SOURCE, 4);\r
+      if(packet[IP_PROTOCOL] == 0x06 || packet[IP_PROTOCOL] == 0x11)   //TCP/UDP\r
+      {\r
+         memcpy(packetOut+TCP_SOURCE_PORT, packet+TCP_DEST_PORT, 2);\r
+         memcpy(packetOut+TCP_DEST_PORT, packet+TCP_SOURCE_PORT, 2);\r
+      }\r
+   }\r
+}\r
+\r
+\r
+static void IPArp(unsigned char ipAddress[4])\r
+{\r
+   IPFrame *frame;\r
+   uint8 *packetOut;\r
+\r
+   frame = IPFrameGet(0);\r
+   if(frame == NULL)\r
+      return;\r
+   packetOut = frame->packet;\r
+   memset(packetOut, 0, 512);\r
+   memset(packetOut+ETHERNET_DEST, 0xff, 6);\r
+   memcpy(packetOut+ETHERNET_SOURCE, ethernetAddressPlasma, 6);\r
+   packetOut[ETHERNET_FRAME_TYPE] = 0x08;\r
+   packetOut[ETHERNET_FRAME_TYPE+1] = 0x06;\r
+   packetOut[ARP_HARD_TYPE+1] = 0x01;\r
+   packetOut[ARP_PROT_TYPE] = 0x08;\r
+   packetOut[ARP_HARD_SIZE] = 0x06;\r
+   packetOut[ARP_PROT_SIZE] = 0x04;\r
+   packetOut[ARP_OP+1] = 1;\r
+   memcpy(packetOut+ARP_ETHERNET_SENDER, ethernetAddressPlasma, 6);\r
+   memcpy(packetOut+ARP_IP_SENDER, ipAddressPlasma, 4);\r
+   memcpy(packetOut+ARP_IP_TARGET, ipAddress, 4);\r
+   IPSendPacket(NULL, frame, 60);\r
+}\r
+\r
+\r
+static void IPDhcp(const unsigned char *packet, int length, int state)\r
+{\r
+   uint8 *packetOut, *ptr;\r
+   const uint8 *ptr2;\r
+   IPFrame *frame;\r
+   static int request=0;\r
+\r
+   if(state == 1)\r
+   {\r
+      //Create DHCP Discover\r
+      frame = IPFrameGet(0);\r
+      if(frame == NULL)\r
+         return;\r
+      packetOut = frame->packet;\r
+      memset(packetOut, 0, 512);\r
+      memcpy(packetOut, dhcpDiscover, sizeof(dhcpDiscover));\r
+      memcpy(packetOut+ETHERNET_SOURCE, ethernetAddressPlasma, 6);\r
+      memcpy(packetOut+DHCP_CLIENT_ETHERNET, ethernetAddressPlasma, 6);\r
+      memcpy(packetOut+DHCP_MAGIC_COOKIE, dhcpOptions, sizeof(dhcpOptions));\r
+      memcpy(packetOut+DHCP_MAGIC_COOKIE+10, ethernetAddressPlasma, 6);\r
+      IPSendPacket(NULL, frame, 400);\r
+      request = DHCP_DISCOVER;\r
+      DhcpRetrySeconds = 2;\r
+   }\r
+   else if(state == 2 && memcmp(packet+DHCP_CLIENT_ETHERNET, ethernetAddressPlasma, 6) == 0)\r
+   {\r
+      if(packet[DHCP_MAGIC_COOKIE+6] == DHCP_OFFER && request == DHCP_DISCOVER)\r
+      {\r
+         //Process DHCP Offer and send DHCP Request\r
+         frame = IPFrameGet(0);\r
+         if(frame == NULL)\r
+            return;\r
+         packetOut = frame->packet;\r
+         memset(packetOut, 0, 512);\r
+         memcpy(packetOut, dhcpDiscover, sizeof(dhcpDiscover));\r
+         memcpy(packetOut+ETHERNET_SOURCE, ethernetAddressPlasma, 6);\r
+         memcpy(packetOut+DHCP_CLIENT_ETHERNET, ethernetAddressPlasma, 6);\r
+         memcpy(packetOut+DHCP_MAGIC_COOKIE, dhcpOptions, sizeof(dhcpOptions));\r
+         memcpy(packetOut+DHCP_MAGIC_COOKIE+10, ethernetAddressPlasma, 6);\r
+         request = DHCP_REQUEST;\r
+         packetOut[DHCP_MAGIC_COOKIE+6] = DHCP_REQUEST;\r
+         ptr = packetOut+DHCP_MAGIC_COOKIE+sizeof(dhcpOptions)-1;\r
+         ptr[0] = DHCP_REQUEST_IP;\r
+         ptr[1] = 4;\r
+         memcpy(ptr+2, packet+DHCP_YOUR_IP, 4);\r
+         ptr[6] = DHCP_REQUEST_SERV_IP;\r
+         ptr[7] = 4;\r
+         memcpy(ptr+8, packet+DHCP_SERVER_IP, 4);\r
+         ptr[12] = DHCP_END_OPTION;\r
+         IPSendPacket(NULL, frame, 400);\r
+      }\r
+      else if(packet[DHCP_MAGIC_COOKIE+6] == DHCP_ACK && request == DHCP_REQUEST)\r
+      {\r
+         //Process DHCP Ack\r
+         request = 0;\r
+         DhcpRetrySeconds = 3600*4;\r
+         memcpy(ipAddressPlasma, packet+DHCP_YOUR_IP, 4);\r
+         printf("IP=%d.%d.%d.%d ", ipAddressPlasma[0], ipAddressPlasma[1],\r
+            ipAddressPlasma[2], ipAddressPlasma[3]);\r
+         memcpy(ipAddressGateway, packet+DHCP_GATEWAY_IP, 4);\r
+         if(ipAddressGateway[0] == 0 && ipAddressGateway[1] == 0 &&\r
+            ipAddressGateway[2] == 0 && ipAddressGateway[3] == 0)\r
+            memcpy(ipAddressGateway, packet+DHCP_SERVER_IP, 4);\r
+         printf("GW=%d.%d.%d.%d ", ipAddressGateway[0], ipAddressGateway[1],\r
+            ipAddressGateway[2], ipAddressGateway[3]);\r
+         memcpy(ethernetAddressGateway, packet+ETHERNET_SOURCE, 6);\r
+         ptr2 = packet+DHCP_MAGIC_COOKIE+4;\r
+         while(ptr2[0] != DHCP_END_OPTION && (int)(ptr2 - packet) < length)\r
+         {\r
+            if(ptr2[0] == DHCP_PARAM_DNS)\r
+            {\r
+               ipAddressDns = (ptr2[2] << 24) | (ptr2[3] << 16) | (ptr2[4] << 8) | ptr2[5];\r
+               printf("DNS=%d.%d.%d.%d ", ptr2[2], ptr2[3], ptr2[4], ptr2[5]);\r
+            }\r
+            ptr2 += ptr2[1] + 2;\r
+         }\r
+\r
+         //Check if DHCP reply came from gateway\r
+         if(memcmp(packet+IP_SOURCE, ipAddressGateway, 4))\r
+         {\r
+            memset(ethernetAddressGateway, 0xff, 6);\r
+            IPArp(ipAddressGateway);     //Send ARP to gateway\r
+         }\r
+      }\r
+   }\r
+}\r
+\r
+\r
+uint32 IPAddressSelf(void)\r
+{\r
+   return (ipAddressPlasma[0] << 24) | (ipAddressPlasma[1] << 16) |\r
+          (ipAddressPlasma[2] << 8) | ipAddressPlasma[3];\r
+}\r
+\r
+\r
+static int IPProcessTCPPacket(IPFrame *frameIn)\r
+{\r
+   uint32 seq, ack;\r
+   int length, ip_length, bytes, rc=0, notify=0;\r
+   IPSocket *socket, *socketNew;\r
+   IPFrame *frameOut, *frame2, *framePrev;\r
+   uint8 *packet, *packetOut;\r
+\r
+   packet = frameIn->packet;\r
+   length = frameIn->length;\r
+\r
+   ip_length = (packet[IP_LENGTH] << 8) | packet[IP_LENGTH+1];\r
+   seq = (packet[TCP_SEQ] << 24) | (packet[TCP_SEQ+1] << 16) | \r
+         (packet[TCP_SEQ+2] << 8) | packet[TCP_SEQ+3];\r
+   ack = (packet[TCP_ACK] << 24) | (packet[TCP_ACK+1] << 16) | \r
+         (packet[TCP_ACK+2] << 8) | packet[TCP_ACK+3];\r
+\r
+   //Check if start of connection\r
+   if((packet[TCP_FLAGS] & (TCP_FLAGS_SYN | TCP_FLAGS_ACK)) == TCP_FLAGS_SYN)\r
+   {\r
+      if(IPVerbose)\r
+         printf("S");\r
+      //Check if duplicate SYN\r
+      for(socket = SocketHead; socket; socket = socket->next)\r
+      {\r
+         if(socket->state != IP_LISTEN &&\r
+            packet[IP_PROTOCOL] == socket->headerRcv[IP_PROTOCOL] &&\r
+            memcmp(packet+IP_SOURCE, socket->headerRcv+IP_SOURCE, 8) == 0 &&\r
+            memcmp(packet+TCP_SOURCE_PORT, socket->headerRcv+TCP_SOURCE_PORT, 4) == 0)\r
+         {\r
+            if(IPVerbose)\r
+               printf("s");\r
+            return 0;\r
+         }\r
+      }\r
+\r
+      //Find an open port\r
+      for(socket = SocketHead; socket; socket = socket->next)\r
+      {\r
+         if(socket->state == IP_LISTEN &&\r
+            packet[IP_PROTOCOL] == socket->headerRcv[IP_PROTOCOL] &&\r
+            memcmp(packet+TCP_DEST_PORT, socket->headerRcv+TCP_DEST_PORT, 2) == 0)\r
+         {\r
+            //Create a new socket\r
+            frameOut = IPFrameGet(FRAME_COUNT_SYNC);\r
+            if(frameOut == NULL)\r
+               return 0;\r
+            socketNew = (IPSocket*)malloc(sizeof(IPSocket));\r
+            if(socketNew == NULL)\r
+               return 0;\r
+            memcpy(socketNew, socket, sizeof(IPSocket));\r
+            socketNew->state = IP_TCP;\r
+            socketNew->timeout = SOCKET_TIMEOUT;\r
+            socketNew->ack = seq;\r
+            socketNew->ackProcessed = seq + 1;\r
+            socketNew->seq = socketNew->ack + 0x12345678;\r
+            socketNew->seqReceived = socketNew->seq;\r
+            socketNew->seqWindow = (packet[TCP_WINDOW_SIZE] << 8) | packet[TCP_WINDOW_SIZE+1];\r
+\r
+            //Send ACK\r
+            packetOut = frameOut->packet;\r
+            EthernetCreateResponse(packetOut, packet, length);\r
+            memcpy(socketNew->headerRcv, packet, TCP_SEQ);\r
+            memcpy(socketNew->headerSend, packetOut, TCP_SEQ);\r
+            packetOut[TCP_FLAGS] = TCP_FLAGS_SYN | TCP_FLAGS_ACK;\r
+            ++socketNew->ack;\r
+            packetOut[TCP_DATA] = 2;    //maximum segment size = 536\r
+            packetOut[TCP_DATA+1] = 4;\r
+            packetOut[TCP_DATA+2] = 2;\r
+            packetOut[TCP_DATA+3] = 24;\r
+            TCPSendPacket(socketNew, frameOut, TCP_DATA+4);\r
+            ++socketNew->seq;\r
+\r
+            //Add socket to linked list\r
+            OS_MutexPend(IPMutex);\r
+            socketNew->next = SocketHead;\r
+            socketNew->prev = NULL;\r
+            if(SocketHead)\r
+               SocketHead->prev = socketNew;\r
+            SocketHead = socketNew;\r
+            OS_MutexPost(IPMutex);\r
+            if(socketNew->funcPtr)\r
+               OS_Job(socketNew->funcPtr, socketNew, 0, 0);\r
+            return 0;\r
+         }\r
+      }\r
+\r
+      //Send reset\r
+      frameOut = IPFrameGet(0);\r
+      if(frameOut == NULL)\r
+         return 0;\r
+      packetOut = frameOut->packet;\r
+      EthernetCreateResponse(packetOut, packet, TCP_DATA);\r
+      memset(packetOut+TCP_SEQ, 0, 4);\r
+      ++seq;\r
+      packetOut[TCP_ACK]   = (uint8)(seq >> 24);\r
+      packetOut[TCP_ACK+1] = (uint8)(seq >> 16);\r
+      packetOut[TCP_ACK+2] = (uint8)(seq >> 8);\r
+      packetOut[TCP_ACK+3] = (uint8)seq;\r
+      packetOut[TCP_HEADER_LENGTH] = 0x50;\r
+      packetOut[TCP_FLAGS] = TCP_FLAGS_RST;\r
+      IPSendPacket(NULL, frameOut, TCP_DATA);\r
+      return 0;\r
+   }\r
+\r
+   //Find an open socket\r
+   for(socket = SocketHead; socket; socket = socket->next)\r
+   {\r
+      if(packet[IP_PROTOCOL] == socket->headerRcv[IP_PROTOCOL] &&\r
+         memcmp(packet+IP_SOURCE, socket->headerRcv+IP_SOURCE, 8) == 0 &&\r
+         memcmp(packet+TCP_SOURCE_PORT, socket->headerRcv+TCP_SOURCE_PORT, 4) == 0)\r
+      {\r
+         break;\r
+      }\r
+   }\r
+   if(socket == NULL)\r
+   {\r
+      return 0;\r
+   }\r
+\r
+   //Determine window\r
+   socket->seqWindow = (packet[TCP_WINDOW_SIZE] << 8) | packet[TCP_WINDOW_SIZE+1];\r
+   bytes = ip_length - (TCP_DATA - IP_VERSION_LENGTH);\r
+\r
+   //Check if packets can be removed from retransmition list\r
+   if(packet[TCP_FLAGS] & TCP_FLAGS_ACK)\r
+   {\r
+      if(ack != socket->seqReceived)\r
+      {\r
+         OS_MutexPend(IPMutex);\r
+         for(frame2 = FrameResendHead; frame2; )\r
+         {\r
+            framePrev = frame2;\r
+            frame2 = frame2->next;\r
+            if(framePrev->socket == socket && (int)(ack - framePrev->seqEnd) >= 0)\r
+            {\r
+               //Remove packet from retransmition queue\r
+               if(socket->timeout)\r
+                  socket->timeout = socket->timeoutReset;\r
+               FrameRemove(&FrameResendHead, &FrameResendTail, framePrev);\r
+               FrameFree(framePrev);\r
+            }\r
+         }\r
+         OS_MutexPost(IPMutex);\r
+         socket->seqReceived = ack;\r
+         socket->resentDone = 0;\r
+      }\r
+      else if(ack == socket->seqReceived && bytes == 0 &&\r
+         (packet[TCP_FLAGS] & (TCP_FLAGS_RST | TCP_FLAGS_FIN)) == 0 &&\r
+         socket->resentDone == 0)\r
+      {\r
+         //Detected that packet was lost, resend all\r
+         if(IPVerbose)\r
+            printf("A");\r
+         OS_MutexPend(IPMutex);\r
+         for(frame2 = FrameResendHead; frame2; )\r
+         {\r
+            framePrev = frame2;\r
+            frame2 = frame2->next;\r
+            if(framePrev->socket == socket)\r
+            {\r
+               //Remove packet from retransmition queue\r
+               FrameRemove(&FrameResendHead, &FrameResendTail, framePrev);\r
+               IPSendFrame(framePrev);\r
+            }\r
+         }\r
+         OS_MutexPost(IPMutex);\r
+         socket->resentDone = 1;\r
+      }\r
+   }\r
+\r
+   //Check if SYN/ACK\r
+   if((packet[TCP_FLAGS] & (TCP_FLAGS_SYN | TCP_FLAGS_ACK)) == \r
+      (TCP_FLAGS_SYN | TCP_FLAGS_ACK))\r
+   {\r
+      //Ack SYN/ACK\r
+      socket->ack = seq + 1;\r
+      socket->ackProcessed = seq + 1;\r
+      frameOut = IPFrameGet(FRAME_COUNT_SEND);\r
+      if(frameOut)\r
+      {\r
+         frameOut->packet[TCP_FLAGS] = TCP_FLAGS_ACK;\r
+         TCPSendPacket(socket, frameOut, TCP_DATA);\r
+      }\r
+      if(socket->funcPtr)\r
+         OS_Job(socket->funcPtr, socket, 0, 0);\r
+      return 0;\r
+   }\r
+   if(packet[TCP_HEADER_LENGTH] != 0x50)\r
+   {\r
+      if(IPVerbose)\r
+         printf("length error\n");\r
+      return 0;\r
+   }\r
+\r
+   //Check if RST flag set\r
+   if(packet[TCP_FLAGS] & TCP_FLAGS_RST)\r
+   {\r
+      notify = 1;\r
+      IPClose2(socket);\r
+   }\r
+   //Copy packet into socket\r
+   else if(socket->ack == seq && bytes > 0)\r
+   {\r
+      //Insert packet into socket linked list\r
+      notify = 1;\r
+      if(socket->timeout)\r
+         socket->timeout = socket->timeoutReset;\r
+      if(IPVerbose)\r
+         printf("D");\r
+      if(frameIn->length > ip_length + IP_VERSION_LENGTH)\r
+         frameIn->length = (uint16)(ip_length + IP_VERSION_LENGTH);\r
+      FrameInsert(&socket->frameReadHead, &socket->frameReadTail, frameIn);\r
+      socket->ack += bytes;\r
+\r
+      //Ack data\r
+      frameOut = IPFrameGet(FRAME_COUNT_SEND);\r
+      if(frameOut)\r
+      {\r
+         frameOut->packet[TCP_FLAGS] = TCP_FLAGS_ACK;\r
+         TCPSendPacket(socket, frameOut, TCP_DATA);\r
+      }\r
+\r
+      //Using frame\r
+      rc = 1;\r
+   }\r
+   else if(bytes)\r
+   {\r
+      //Ack with current offset since data missing\r
+      frameOut = IPFrameGet(FRAME_COUNT_SEND);\r
+      if(frameOut)\r
+      {\r
+         frameOut->packet[TCP_FLAGS] = TCP_FLAGS_ACK;\r
+         TCPSendPacket(socket, frameOut, TCP_DATA);\r
+      }\r
+   }\r
+\r
+   //Check if FIN flag set\r
+   if(packet[TCP_FLAGS] & TCP_FLAGS_FIN && socket->ack >= seq)\r
+   {\r
+      notify = 1;\r
+      socket->timeout = SOCKET_TIMEOUT;\r
+      if(IPVerbose)\r
+         printf("F");\r
+      frameOut = IPFrameGet(0);\r
+      if(frameOut == NULL)\r
+         return 0;\r
+      packetOut = frameOut->packet;\r
+      packetOut[TCP_FLAGS] = TCP_FLAGS_ACK;\r
+      ++socket->ack;\r
+      TCPSendPacket(socket, frameOut, TCP_DATA);\r
+      if(socket->state == IP_FIN_SERVER)\r
+         socket->timeout = SOCKET_TIMEOUT;\r
+      else if(socket->state == IP_TCP)\r
+         socket->state = IP_FIN_CLIENT;\r
+   }\r
+\r
+   //Notify application\r
+   if(socket->funcPtr && notify)\r
+      OS_Job(socket->funcPtr, socket, 0, 0);\r
+   return rc;\r
+}\r
+\r
+\r
+int IPProcessEthernetPacket(IPFrame *frameIn, int length)\r
+{\r
+   int ip_length, rc;\r
+   IPSocket *socket;\r
+   IPFrame *frameOut;\r
+   uint8 *packet, *packetOut;\r
+\r
+   packet = frameIn->packet;\r
+   frameIn->length = (uint16)length;\r
+\r
+   if(packet[ETHERNET_FRAME_TYPE] != 0x08 || frameIn->length > PACKET_SIZE)\r
+      return 0;  //wrong ethernet type, packet not used\r
+\r
+   //ARP?\r
+   if(packet[ETHERNET_FRAME_TYPE+1] == 0x06)\r
+   {\r
+      //Check if ARP reply\r
+      if(memcmp(packet+ETHERNET_DEST, ethernetAddressPlasma, 6) == 0 &&\r
+         packet[ARP_OP+1] == 2)\r
+      {\r
+         memcpy(ArpCache[ArpCacheIndex].ip, packet+ARP_IP_SENDER, 4);\r
+         memcpy(ArpCache[ArpCacheIndex].mac, packet+ARP_ETHERNET_SENDER, 6);\r
+         if(++ArpCacheIndex >= sizeof(ArpCache) / sizeof(ArpCache_t))\r
+            ArpCacheIndex = 0;\r
+         if(memcmp(packet+ARP_IP_SENDER, ipAddressGateway, 4) == 0)\r
+         {\r
+            //Found MAC address for gateway\r
+            memcpy(ethernetAddressGateway, packet+ARP_ETHERNET_SENDER, 6);\r
+         }\r
+         return 0;\r
+      }\r
+\r
+      //Check if ARP request\r
+      if(packet[ARP_OP] != 0 || packet[ARP_OP+1] != 1 ||  \r
+         memcmp(packet+ARP_IP_TARGET, ipAddressPlasma, 4))\r
+         return 0;\r
+      //Create ARP response\r
+      frameOut = IPFrameGet(0);\r
+      if(frameOut == NULL)\r
+         return 0;\r
+      packetOut = frameOut->packet;\r
+      memcpy(packetOut, packet, frameIn->length);\r
+      memcpy(packetOut+ETHERNET_DEST, packet+ETHERNET_SOURCE, 6);\r
+      memcpy(packetOut+ETHERNET_SOURCE, ethernetAddressPlasma, 6);\r
+      packetOut[ARP_OP+1] = 2; //ARP reply\r
+      memcpy(packetOut+ARP_ETHERNET_SENDER, ethernetAddressPlasma, 6);\r
+      memcpy(packetOut+ARP_IP_SENDER, packet+ARP_IP_TARGET, 4);\r
+      memcpy(packetOut+ARP_ETHERNET_TARGET, packet+ARP_ETHERNET_SENDER, 6);\r
+      memcpy(packetOut+ARP_IP_TARGET, packet+ARP_IP_SENDER, 4);\r
+      IPSendPacket(NULL, frameOut, frameIn->length);\r
+      return 0;\r
+   }\r
+\r
+   //Check if proper type of packet\r
+   ip_length = (packet[IP_LENGTH] << 8) | packet[IP_LENGTH+1];\r
+   if(frameIn->length < UDP_DATA || ip_length > frameIn->length - IP_VERSION_LENGTH)\r
+      return 0;\r
+   if(packet[ETHERNET_FRAME_TYPE+1] != 0x00 ||\r
+      packet[IP_VERSION_LENGTH] != 0x45)\r
+      return 0;\r
+\r
+   //Check if DHCP reply\r
+   if(packet[IP_PROTOCOL] == 0x11 &&\r
+      packet[UDP_SOURCE_PORT] == 0 && packet[UDP_SOURCE_PORT+1] == 67 &&\r
+      packet[UDP_DEST_PORT] == 0 && packet[UDP_DEST_PORT+1] == 68)\r
+   {\r
+      IPDhcp(packet, frameIn->length, 2);            //DHCP reply\r
+      return 0;\r
+   }\r
+\r
+   //Check if correct destination address\r
+   if(memcmp(packet+ETHERNET_DEST, ethernetAddressPlasma, 6) ||\r
+      memcmp(packet+IP_DEST, ipAddressPlasma, 4))\r
+      return 0;\r
+   rc = EthernetVerifyChecksums(packet, frameIn->length);\r
+#ifndef WIN32\r
+   if(rc && FrameSendFunc)\r
+   {\r
+      printf("C ");\r
+      return 0;\r
+   }\r
+#endif\r
+\r
+   //PING request?\r
+   if(packet[IP_PROTOCOL] == 1)\r
+   {\r
+      if(packet[PING_TYPE] == 0)  //PING reply\r
+      {\r
+         for(socket = SocketHead; socket; socket = socket->next)\r
+         {\r
+            if(socket->state == IP_PING && \r
+               memcmp(packet+IP_SOURCE, socket->headerSend+IP_DEST, 4) == 0)\r
+            {\r
+               OS_Job(socket->funcPtr, socket, 0, 0);\r
+               return 0;\r
+            }\r
+         }\r
+      }\r
+      if(packet[PING_TYPE] != 8)\r
+         return 0;\r
+      frameOut = IPFrameGet(FRAME_COUNT_SEND);\r
+      if(frameOut == NULL)\r
+         return 0;\r
+      packetOut = frameOut->packet;\r
+      EthernetCreateResponse(packetOut, packet, frameIn->length);\r
+      frameOut->packet[PING_TYPE] = 0;       //PING reply\r
+      IPSendPacket(NULL, frameOut, frameIn->length);\r
+      return 0;\r
+   }\r
+\r
+   //TCP packet?\r
+   if(packet[IP_PROTOCOL] == 0x06)\r
+   {\r
+      return IPProcessTCPPacket(frameIn);\r
+   }\r
+\r
+   //UDP packet?\r
+   if(packet[IP_PROTOCOL] == 0x11)\r
+   {\r
+      //Find open socket\r
+      for(socket = SocketHead; socket; socket = socket->next)\r
+      {\r
+         if(packet[IP_PROTOCOL] == socket->headerRcv[IP_PROTOCOL] &&\r
+            memcmp(packet+IP_SOURCE, socket->headerRcv+IP_SOURCE, 8) == 0 &&\r
+            memcmp(packet+UDP_SOURCE_PORT, socket->headerRcv+UDP_SOURCE_PORT, 2) == 0)\r
+         {\r
+            break;\r
+         }\r
+      }\r
+\r
+      if(socket == NULL)\r
+      {\r
+         //Find listening socket\r
+         for(socket = SocketHead; socket; socket = socket->next)\r
+         {\r
+            if(packet[IP_PROTOCOL] == socket->headerRcv[IP_PROTOCOL] &&\r
+               memcmp(packet+UDP_DEST_PORT, socket->headerRcv+UDP_DEST_PORT, 2) == 0)\r
+            {\r
+               EthernetCreateResponse(socket->headerSend, packet, UDP_DATA);\r
+               break;\r
+            }\r
+         }\r
+      }\r
+\r
+      if(socket)\r
+      {\r
+         if(IPVerbose)\r
+            printf("U");\r
+         FrameInsert(&socket->frameReadHead, &socket->frameReadTail, frameIn);\r
+         OS_Job(socket->funcPtr, socket, 0, 0);\r
+         return 1;\r
+      }\r
+   }\r
+   return 0;\r
+}\r
+\r
+\r
+#ifndef WIN32\r
+static void IPMainThread(void *arg)\r
+{\r
+   uint32 message[4];\r
+   int rc;\r
+   IPFrame *frame, *frameOut=NULL;\r
+   uint32 ticks, ticksLast;\r
+   (void)arg;\r
+\r
+   ticksLast = OS_ThreadTime();\r
+   memset(message, 0, sizeof(message));\r
+\r
+   for(;;)\r
+   {\r
+      Led(7, 0);\r
+      rc = OS_MQueueGet(IPMQueue, message, 10);\r
+      if(rc == 0)\r
+      {\r
+         frame = (IPFrame*)message[1];\r
+         if(message[0] == 0)       //frame received\r
+         {\r
+            Led(7, 1);\r
+            frame->length = (uint16)message[2];\r
+            rc = IPProcessEthernetPacket(frame, frame->length);\r
+            if(rc == 0)\r
+               FrameFree(frame);\r
+         }\r
+         else if(message[0] == 1)  //frame sent\r
+         {\r
+            Led(7, 2);\r
+            assert(frame == frameOut);\r
+            IPFrameReschedule(frame);\r
+            frameOut = NULL;\r
+         }\r
+         else if(message[0] == 2)  //frame ready to send\r
+         {\r
+         }\r
+      }\r
+\r
+      if(frameOut == NULL)\r
+      {\r
+         OS_MutexPend(IPMutex);\r
+         frameOut = FrameSendTail;\r
+         if(frameOut)\r
+            FrameRemove(&FrameSendHead, &FrameSendTail, frameOut);\r
+         OS_MutexPost(IPMutex);\r
+         if(frameOut)\r
+         {\r
+            Led(7, 4);\r
+            UartPacketSend(frameOut->packet, frameOut->length);\r
+         }\r
+      }\r
+\r
+      ticks = OS_ThreadTime();\r
+      if(ticks - ticksLast > 100)\r
+      {\r
+         IPTick();\r
+         ticksLast = ticks;\r
+      }\r
+   }\r
+}\r
+#endif\r
+\r
+\r
+uint8 *MyPacketGet(void)\r
+{\r
+   return (uint8*)IPFrameGet(FRAME_COUNT_RCV);\r
+}\r
+\r
+\r
+//Set FrameSendFunction only if single threaded\r
+void IPInit(IPFuncPtr frameSendFunction, uint8 macAddress[6], char name[6])\r
+{\r
+   int i;\r
+   IPFrame *frame;\r
+\r
+   if(macAddress)\r
+      memcpy(ethernetAddressPlasma, macAddress, 6);\r
+   if(name)\r
+      memcpy(dhcpOptions+18, name, 6);\r
+   FrameSendFunc = frameSendFunction;\r
+   IPMutex = OS_MutexCreate("IPSem");\r
+   IPMQueue = OS_MQueueCreate("IPMQ", FRAME_COUNT*2, 32);\r
+   for(i = 0; i < FRAME_COUNT; ++i)\r
+   {\r
+      frame = (IPFrame*)malloc(sizeof(IPFrame));\r
+      memset(frame, 0, sizeof(IPFrame));\r
+      frame->next = FrameFreeHead;\r
+      frame->prev = NULL;\r
+      FrameFreeHead = frame;\r
+   }\r
+   FrameFreeCount = FRAME_COUNT;\r
+#ifndef WIN32\r
+   UartPacketConfig(MyPacketGet, PACKET_SIZE, IPMQueue);\r
+   if(frameSendFunction == NULL)\r
+      IPThread = OS_ThreadCreate("TCP/IP", IPMainThread, NULL, 240, 6000);\r
+#endif\r
+   IPDhcp(NULL, 360, 1);        //Send DHCP request\r
+}\r
+\r
+\r
+//To open a socket for listen set ipAddress to 0\r
+IPSocket *IPOpen(IPMode_e mode, uint32 ipAddress, uint32 port, IPFuncPtr funcPtr)\r
+{\r
+   IPSocket *socket;\r
+   uint8 *ptrSend, *ptrRcv;\r
+   IPFrame *frame;\r
+   static int portSource=0x1007;\r
+\r
+   socket = (IPSocket*)malloc(sizeof(IPSocket));\r
+   if(socket == NULL)\r
+      return socket;\r
+   memset(socket, 0, sizeof(IPSocket));\r
+   socket->prev = NULL;\r
+   socket->state = IP_LISTEN;\r
+   socket->timeout = 0;\r
+   socket->timeoutReset = SOCKET_TIMEOUT;\r
+   socket->frameReadHead = NULL;\r
+   socket->frameReadTail = NULL;\r
+   socket->readOffset = 0;\r
+   socket->funcPtr = funcPtr;\r
+   socket->userData = 0;\r
+   socket->userFunc = NULL;\r
+   socket->userPtr = NULL;\r
+   socket->seqWindow = 2048;\r
+   ptrSend = socket->headerSend;\r
+   ptrRcv = socket->headerRcv;\r
+\r
+   if(ipAddress == 0)\r
+   {\r
+      //Setup listing port\r
+      socket->headerRcv[TCP_DEST_PORT] = (uint8)(port >> 8);\r
+      socket->headerRcv[TCP_DEST_PORT+1] = (uint8)port;\r
+   }\r
+   else\r
+   {\r
+      //Setup sending packet\r
+      memset(ptrSend, 0, UDP_LENGTH);\r
+      memset(ptrRcv, 0, UDP_LENGTH);\r
+\r
+      //Setup Ethernet\r
+      if(ipAddress != IPAddressSelf())\r
+         memcpy(ptrSend+ETHERNET_DEST, ethernetAddressGateway, 6);\r
+      else\r
+         memcpy(ptrSend+ETHERNET_DEST, ethernetAddressPlasma, 6);\r
+      memcpy(ptrSend+ETHERNET_SOURCE, ethernetAddressPlasma, 6);\r
+      ptrSend[ETHERNET_FRAME_TYPE] = 0x08;\r
+\r
+      //Setup IP\r
+      ptrSend[IP_VERSION_LENGTH] = 0x45;\r
+      ptrSend[IP_TIME_TO_LIVE] = 0x80;\r
+\r
+      //Setup IP addresses\r
+      memcpy(ptrSend+IP_SOURCE, ipAddressPlasma, 4);\r
+      ptrSend[IP_DEST] = (uint8)(ipAddress >> 24);\r
+      ptrSend[IP_DEST+1] = (uint8)(ipAddress >> 16);\r
+      ptrSend[IP_DEST+2] = (uint8)(ipAddress >> 8);\r
+      ptrSend[IP_DEST+3] = (uint8)ipAddress;\r
+      ptrRcv[IP_SOURCE] = (uint8)(ipAddress >> 24);\r
+      ptrRcv[IP_SOURCE+1] = (uint8)(ipAddress >> 16);\r
+      ptrRcv[IP_SOURCE+2] = (uint8)(ipAddress >> 8);\r
+      ptrRcv[IP_SOURCE+3] = (uint8)ipAddress;\r
+      memcpy(ptrRcv+IP_DEST, ipAddressPlasma, 4);\r
+\r
+      //Setup ports\r
+      ptrSend[TCP_SOURCE_PORT] = (uint8)(portSource >> 8);\r
+      ptrSend[TCP_SOURCE_PORT+1] = (uint8)portSource;\r
+      ptrSend[TCP_DEST_PORT] = (uint8)(port >> 8);\r
+      ptrSend[TCP_DEST_PORT+1] = (uint8)port;\r
+      ptrRcv[TCP_SOURCE_PORT] = (uint8)(port >> 8);\r
+      ptrRcv[TCP_SOURCE_PORT+1] = (uint8)port;\r
+      ptrRcv[TCP_DEST_PORT] = (uint8)(portSource >> 8);\r
+      ptrRcv[TCP_DEST_PORT+1] = (uint8)portSource;\r
+      ++portSource;\r
+   }\r
+\r
+   if(mode == IP_MODE_TCP)\r
+   {\r
+      if(ipAddress)\r
+         socket->state = IP_TCP;\r
+      else\r
+         socket->state = IP_LISTEN;\r
+      ptrSend[IP_PROTOCOL] = 0x06;  //TCP\r
+      ptrRcv[IP_PROTOCOL] = 0x06;\r
+   }\r
+   else if(mode == IP_MODE_UDP)\r
+   {\r
+      socket->state = IP_UDP;\r
+      ptrSend[IP_PROTOCOL] = 0x11;  //UDP\r
+      ptrRcv[IP_PROTOCOL] = 0x11; \r
+   }\r
+   else if(mode == IP_MODE_PING)\r
+   {\r
+      socket->state = IP_PING;\r
+      ptrSend[IP_PROTOCOL] = 0x01;  //PING\r
+      memset(ptrSend+PING_TYPE, 0, 8);\r
+      ptrSend[PING_TYPE] = 8;       //SEND\r
+   }\r
+\r
+   //Add socket to linked list\r
+   OS_MutexPend(IPMutex);\r
+   socket->next = SocketHead;\r
+   socket->prev = NULL;\r
+   if(SocketHead)\r
+      SocketHead->prev = socket;\r
+   SocketHead = socket;\r
+   OS_MutexPost(IPMutex);\r
+\r
+   if(mode == IP_MODE_TCP && ipAddress)\r
+   {\r
+      //Send TCP SYN\r
+      socket->seq = 0x01234567;\r
+      frame = IPFrameGet(0);\r
+      if(frame)\r
+      {\r
+         frame->packet[TCP_FLAGS] = TCP_FLAGS_SYN;\r
+         frame->packet[TCP_DATA] = 2;    //maximum segment size = 536\r
+         frame->packet[TCP_DATA+1] = 4;\r
+         frame->packet[TCP_DATA+2] = 2;\r
+         frame->packet[TCP_DATA+3] = 24;\r
+         TCPSendPacket(socket, frame, TCP_DATA+4);\r
+         ++socket->seq;\r
+      }\r
+   }\r
+   return socket;\r
+}\r
+\r
+\r
+void IPWriteFlush(IPSocket *socket)\r
+{\r
+   uint8 *packetOut;\r
+   if(socket->frameSend && socket->state != IP_UDP &&\r
+      socket->state != IP_PING)\r
+   {\r
+      packetOut = socket->frameSend->packet;\r
+      packetOut[TCP_FLAGS] = TCP_FLAGS_ACK | TCP_FLAGS_PSH;\r
+      TCPSendPacket(socket, socket->frameSend, TCP_DATA + socket->sendOffset);\r
+      socket->seq += socket->sendOffset;\r
+      socket->frameSend = NULL;\r
+      socket->sendOffset = 0;\r
+   }\r
+}\r
+\r
+\r
+uint32 IPWrite(IPSocket *socket, const uint8 *buf, uint32 length)\r
+{\r
+   IPFrame *frameOut;\r
+   uint8 *packetOut;\r
+   uint32 bytes, count=0, tries=0;\r
+   int offset;\r
+   OS_Thread_t *self;\r
+\r
+   if(socket->state > IP_TCP)\r
+      return 0;\r
+\r
+   if(socket->timeout)\r
+      socket->timeout = socket->timeoutReset;\r
+\r
+#ifdef INCLUDE_FILESYS\r
+   if(socket->fileOut)   //override stdout\r
+      return fwrite((char*)buf, 1, length, socket->fileOut);\r
+#endif\r
\r
+   //printf("IPWrite(0x%x, %d)", Socket, Length);\r
+   self = OS_ThreadSelf();\r
+   while(length)\r
+   {\r
+      //Rate limit output\r
+      if(socket->seq - socket->seqReceived >= SEND_WINDOW)\r
+      {\r
+         //printf("l(%d,%d,%d) ", socket->seq - socket->seqReceived, socket->seq, socket->seqReceived);\r
+         if(self != IPThread && ++tries < 200)\r
+         {\r
+            OS_ThreadSleep(1);\r
+            continue;\r
+         }\r
+      }\r
+      tries = 0;\r
+      while(socket->frameSend == NULL)\r
+      {\r
+         socket->frameSend = IPFrameGet(FRAME_COUNT_SEND);\r
+         socket->sendOffset = 0;\r
+         if(socket->frameSend == NULL)\r
+         {\r
+            //printf("L");\r
+            if(self == IPThread || ++tries > 200)\r
+               break;\r
+            else\r
+               OS_ThreadSleep(1);\r
+         }\r
+      }\r
+      frameOut = socket->frameSend;\r
+      offset = socket->sendOffset;\r
+      if(frameOut == NULL)\r
+         break;\r
+      packetOut = frameOut->packet;\r
+\r
+      if(socket->state == IP_PING)\r
+      {\r
+         bytes = length;\r
+         memcpy(packetOut, socket->headerSend, PING_DATA);\r
+         memcpy(packetOut+PING_DATA, buf, bytes);\r
+         IPSendPacket(socket, socket->frameSend, PING_DATA + bytes);\r
+         socket->frameSend = NULL;\r
+      }\r
+      else if(socket->state != IP_UDP)\r
+      {\r
+         bytes = 512 - offset;\r
+         if(bytes > length)\r
+            bytes = length;\r
+         socket->sendOffset += bytes;\r
+         memcpy(packetOut+TCP_DATA+offset, buf, bytes);\r
+         if(socket->sendOffset >= 512)\r
+            IPWriteFlush(socket);\r
+         //if(Socket->seq - Socket->seqReceived > Socket->seqWindow)\r
+         //{\r
+         //   printf("W");\r
+         //   OS_ThreadSleep(10);\r
+         //}\r
+      }\r
+      else  //UDP\r
+      {\r
+         bytes = length;\r
+         memcpy(packetOut+UDP_DATA+offset, buf, bytes);\r
+         memcpy(packetOut, socket->headerSend, UDP_LENGTH);\r
+         IPSendPacket(socket, socket->frameSend, UDP_DATA + bytes);\r
+         socket->frameSend = NULL;\r
+      }\r
+      count += bytes;\r
+      buf += bytes;\r
+      length -= bytes;\r
+   }\r
+   return count;\r
+}\r
+\r
+\r
+uint32 IPRead(IPSocket *socket, uint8 *buf, uint32 length)\r
+{\r
+   IPFrame *frame, *frame2;\r
+   int count=0, bytes, offset;\r
+\r
+#ifdef INCLUDE_FILESYS\r
+   if(socket->fileIn)   //override stdin\r
+   {\r
+      bytes = fread(buf, 1, 1, socket->fileIn);\r
+      if(bytes == 0)\r
+      {\r
+         buf[0] = 0;\r
+         fclose(socket->fileIn);\r
+         socket->fileIn = NULL;\r
+         bytes = 1;\r
+      }\r
+      return bytes;\r
+   }\r
+#endif\r
+\r
+   if(socket->state == IP_UDP)\r
+      offset = UDP_DATA;\r
+   else\r
+      offset = TCP_DATA;\r
+\r
+   OS_MutexPend(IPMutex);\r
+   for(frame = socket->frameReadTail; length && frame; )\r
+   {\r
+      bytes = frame->length - offset - socket->readOffset;\r
+      if(bytes > (int)length)\r
+         bytes = length;\r
+      memcpy(buf, frame->packet + offset + socket->readOffset, bytes);\r
+      buf += bytes;\r
+      socket->readOffset += bytes;\r
+      length -= bytes;\r
+      count += bytes;\r
+\r
+      //Check if done with packet\r
+      frame2 = frame;\r
+      frame = frame->prev;\r
+      if(socket->readOffset == frame2->length - offset)\r
+      {\r
+         //Remove packet from socket linked list\r
+         socket->readOffset = 0;\r
+         FrameRemove(&socket->frameReadHead, &socket->frameReadTail, frame2);\r
+         socket->ackProcessed += frame2->length - offset;\r
+         if(socket->state == IP_TCP &&\r
+            socket->ack - socket->ackProcessed > RECEIVE_WINDOW - 2048)\r
+         {\r
+            //Update receive window for flow control\r
+            frame2->packet[TCP_FLAGS] = TCP_FLAGS_ACK;\r
+            TCPSendPacket(socket, frame2, TCP_DATA);\r
+         }\r
+         else\r
+            FrameFree(frame2);\r
+      }\r
+   }\r
+   OS_MutexPost(IPMutex);\r
+   return count;\r
+}\r
+\r
+\r
+static void IPClose2(IPSocket *socket)\r
+{\r
+   IPFrame *frame, *framePrev;\r
+\r
+   //printf("IPClose2(%x) ", (int)socket);\r
+\r
+   OS_MutexPend(IPMutex);\r
+\r
+   //Remove pending packets\r
+   for(frame = FrameSendHead; frame; )\r
+   {\r
+      framePrev = frame;\r
+      frame = frame->next;\r
+      if(framePrev->socket == socket)\r
+      {\r
+         FrameRemove(&FrameResendHead, &FrameResendTail, framePrev);\r
+         FrameFree(framePrev);\r
+      }\r
+   }\r
+\r
+   //Remove packets from retransmision list\r
+   for(frame = FrameResendHead; frame; )\r
+   {\r
+      framePrev = frame;\r
+      frame = frame->next;\r
+      if(framePrev->socket == socket)\r
+      {\r
+         FrameRemove(&FrameResendHead, &FrameResendTail, framePrev);\r
+         FrameFree(framePrev);\r
+      }\r
+   }\r
+\r
+   //Remove packets from socket read linked list\r
+   for(frame = socket->frameReadHead; frame; )\r
+   {\r
+      framePrev = frame;\r
+      frame = frame->next;\r
+      FrameRemove(&socket->frameReadHead, &socket->frameReadTail, framePrev);\r
+      FrameFree(framePrev);\r
+   }\r
+\r
+   //Give application time to stop using socket\r
+   socket->timeout = SOCKET_TIMEOUT;\r
+   socket->state = IP_CLOSED;\r
+\r
+   OS_MutexPost(IPMutex);\r
+}\r
+\r
+\r
+void IPClose(IPSocket *socket)\r
+{\r
+   IPFrame *frameOut;\r
+\r
+   //printf("IPClose(%x) ", (int)socket);\r
+\r
+   IPWriteFlush(socket);\r
+   if(socket->state <= IP_UDP)\r
+   {\r
+      IPClose2(socket);\r
+      return;\r
+   }\r
+   frameOut = IPFrameGet(0);\r
+   if(frameOut == NULL)\r
+      return;\r
+   frameOut->packet[TCP_FLAGS] = TCP_FLAGS_FIN | TCP_FLAGS_ACK;\r
+   TCPSendPacket(socket, frameOut, TCP_DATA);\r
+   ++socket->seq;\r
+   socket->timeout = SOCKET_TIMEOUT;\r
+   socket->timeoutReset = SOCKET_TIMEOUT;\r
+   socket->state = IP_FIN_SERVER;\r
+}\r
+\r
+\r
+void IPPrintf(IPSocket *socket, char *message, \r
+              int arg0, int arg1, int arg2, int arg3)\r
+{\r
+   char buf[500];\r
+   if(socket == NULL)\r
+   {\r
+      printf(message, arg0, arg1, arg2, arg3);\r
+      return;\r
+   }\r
+   if(strcmp(message, "%s") == 0)\r
+      IPWrite(socket, (uint8*)arg0, (int)strlen((char*)arg0));\r
+   else\r
+   {\r
+      sprintf(buf, message, arg0, arg1, arg2, arg3, 0, 0, 0, 0);\r
+      IPWrite(socket, (uint8*)buf, (int)strlen(buf));\r
+   }\r
+   if(socket->dontFlush == 0 || strstr(message, "\n"))\r
+      IPWriteFlush(socket);\r
+}\r
+\r
+\r
+void IPTick(void)\r
+{\r
+   IPFrame *frame, *frame2;\r
+   IPSocket *socket, *socket2;\r
+   unsigned long ticks;\r
+   static unsigned long ticksPrev=0, ticksPrev2=0;\r
+\r
+   ticks = OS_ThreadTime();\r
+#ifdef WIN32\r
+   ticks = ticksPrev + 100;\r
+#endif\r
+   if(ticks - ticksPrev >= 95)\r
+   {\r
+      if(IPVerbose && (Seconds % 60) == 0)\r
+      {\r
+         if(FrameFreeCount >= FRAME_COUNT-1)\r
+            printf("T");\r
+         else\r
+            printf("T(%d)", FrameFreeCount);\r
+      }\r
+      ++Seconds;\r
+      if(--DhcpRetrySeconds <= 0)\r
+         IPDhcp(NULL, 400, 1);   //DHCP request\r
+   }\r
+\r
+   OS_MutexPend(IPMutex);\r
+\r
+   //Retransmit timeout packets\r
+   for(frame = FrameResendHead; frame; )\r
+   {\r
+      frame2 = frame;\r
+      frame = frame->next;\r
+      frame2->timeout = (short)(frame2->timeout - (ticks - ticksPrev2));\r
+      if(--frame2->timeout <= 0)\r
+      {\r
+         if(IPVerbose)\r
+            printf("r" /*"(%x,%x,%d,%d,%d)"*/, (int)frame2, (int)frame2->socket, \r
+               frame2->retryCnt, frame2->length - TCP_DATA,\r
+               frame2->socket->state);\r
+         FrameRemove(&FrameResendHead, &FrameResendTail, frame2);\r
+         if(frame2->retryCnt < 4 && frame2->socket->state < IP_CLOSED)\r
+            IPSendFrame(frame2);\r
+         else \r
+         {\r
+            if(frame2->socket->state == IP_TCP)\r
+               IPClose(frame2->socket);\r
+            FrameFree(frame2);\r
+         }\r
+      }\r
+   }\r
+\r
+   if(ticks - ticksPrev >= 95)\r
+   {\r
+      //Close timed out sockets\r
+      for(socket = SocketHead; socket; )\r
+      {\r
+         socket2 = socket;\r
+         socket = socket->next;\r
+         if(socket2->timeout && --socket2->timeout == 0)\r
+         {\r
+            socket2->timeout = SOCKET_TIMEOUT;\r
+            if(socket2->state <= IP_TCP || socket2->state == IP_FIN_CLIENT)\r
+               IPClose(socket2);\r
+            else if(socket2->state != IP_CLOSED)\r
+               IPClose2(socket2);\r
+            else\r
+            {\r
+               if(socket2->prev == NULL)\r
+                  SocketHead = socket2->next;\r
+               else\r
+                  socket2->prev->next = socket2->next;\r
+               if(socket2->next)\r
+                  socket2->next->prev = socket2->prev;\r
+               //printf("freeSocket(%x) ", (int)socket2);\r
+               free(socket2);\r
+            }\r
+         }\r
+      }\r
+      ticksPrev = ticks;\r
+   }\r
+   OS_MutexPost(IPMutex);\r
+   ticksPrev2 = ticks;\r
+}\r
+\r
+\r
+static void DnsCallback(IPSocket *socket)\r
+{\r
+   uint8 buf[200], *ptr;\r
+   uint32 ipAddress;\r
+   int bytes;\r
+\r
+   memset(buf, 0, sizeof(buf));\r
+   bytes = IPRead(socket, buf, sizeof(buf));\r
+   if(buf[DNS_NUM_ANSWERS_RR+1])\r
+   {\r
+      for(ptr = buf + DNS_QUESTIONS; ptr + 14 <= buf + bytes; ++ptr)\r
+      {\r
+         if(ptr[0] == 0 && ptr[1] == 1 && ptr[2] == 0 && ptr[3] == 1 && \r
+            ptr[8] == 0 && ptr[9] == 4)\r
+         {\r
+            ipAddress = (ptr[10] << 24) | (ptr[11] << 16) | (ptr[12] << 8) | ptr[13];\r
+            printf("ipAddress = %d.%d.%d.%d\n", ptr[10], ptr[11], ptr[12], ptr[13]);\r
+            socket->userData = ipAddress;\r
+            if(socket->userFunc)\r
+            {\r
+               socket->userFunc(socket, ipAddress, socket->userPtr);\r
+            }\r
+            break;\r
+         }\r
+      }\r
+   }\r
+   IPClose(socket);\r
+}\r
+\r
+\r
+void IPResolve(char *name, IPFuncPtr resolvedFunc, void *arg)\r
+{\r
+   uint8 buf[200], *ptr;\r
+   int length, i;\r
+   IPSocket *socket;\r
+\r
+   socket = IPOpen(IP_MODE_UDP, ipAddressDns, DNS_PORT, DnsCallback);\r
+   memset(buf, 0, sizeof(buf));\r
+   buf[DNS_ID+1] = 1;\r
+   buf[DNS_FLAGS] = 1;\r
+   buf[DNS_NUM_QUESTIONS+1] = 1;\r
+\r
+   //Setup name\r
+   ptr = buf + DNS_QUESTIONS;\r
+   strncpy((char*)ptr+1, name, 100);\r
+   ptr[0] = 1;\r
+   while(ptr[0])\r
+   {\r
+      for(i = 0; i < 100; ++i)\r
+      {\r
+         if(ptr[i+1] == '.' || ptr[i+1] == 0)\r
+         {\r
+            ptr[0] = (uint8)i;\r
+            ptr += i+1;\r
+            break;\r
+         }\r
+      }\r
+   }\r
+   ++ptr;\r
+   ptr[1] = DNS_QUERY_TYPE_IP;\r
+   ptr[3] = DNS_QUERY_CLASS;\r
+   length = (int)(ptr - buf) + 4;\r
+   if(length < 60)\r
+      length = 60;\r
+\r
+   socket->userFunc = (IPFuncPtr)resolvedFunc;\r
+   socket->userPtr = arg;\r
+   socket->userData = 0;\r
+   IPWrite(socket, buf, length);\r
+}\r
+\r
diff --git a/kernel/tcpip.h b/kernel/tcpip.h
new file mode 100644 (file)
index 0000000..9d5d626
--- /dev/null
@@ -0,0 +1,131 @@
+/*--------------------------------------------------------------------
+ * TITLE: Plasma TCP/IP Protocol Stack
+ * AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
+ * DATE CREATED: 4/22/06
+ * FILENAME: tcpip.h
+ * PROJECT: Plasma CPU core
+ * COPYRIGHT: Software placed into the public domain by the author.
+ *    Software 'as is' without warranty.  Author liable for nothing.
+ * DESCRIPTION:
+ *    Plasma TCP/IP Protocol Stack
+ *--------------------------------------------------------------------*/
+#ifndef __TCPIP_H__
+#define __TCPIP_H__
+#define PACKET_SIZE           600
+#define FRAME_COUNT           100
+#define FRAME_COUNT_SYNC      50
+#define FRAME_COUNT_SEND      10
+#define FRAME_COUNT_RCV       5
+#define RETRANSMIT_TIME       110
+#define SOCKET_TIMEOUT        15
+#define SEND_WINDOW           7000
+#define RECEIVE_WINDOW        5120
+
+typedef enum IPMode_e {
+   IP_MODE_UDP,
+   IP_MODE_TCP,
+   IP_MODE_PING
+} IPMode_e;
+
+typedef enum IPState_e {
+   IP_LISTEN,
+   IP_PING,
+   IP_UDP,
+   IP_SYN,
+   IP_TCP,
+   IP_FIN_CLIENT,
+   IP_FIN_SERVER,
+   IP_CLOSED
+} IPState_e;
+
+typedef void (*IPFuncPtr)();
+
+typedef struct IPFrame {
+   uint8 packet[PACKET_SIZE];
+   struct IPFrame *next, *prev;
+   struct IPSocket *socket;
+   uint32 seqEnd;
+   uint16 length;
+   short  timeout;
+   uint8 state, retryCnt;
+} IPFrame;
+
+typedef struct IPSocket {
+   struct IPSocket *next, *prev;
+   IPState_e state;
+   uint32 seq;
+   uint32 seqReceived;
+   uint32 seqWindow;
+   uint32 ack;
+   uint32 ackProcessed;
+   uint32 timeout;
+   uint32 timeoutReset;
+   int resentDone;
+   int dontFlush;
+   uint8 headerSend[38];
+   uint8 headerRcv[38];
+   struct IPFrame *frameReadHead;
+   struct IPFrame *frameReadTail;
+   int readOffset;
+   struct IPFrame *frameSend;
+   int sendOffset;
+   void *fileOut;\r
+   void *fileIn;\r
+   IPFuncPtr funcPtr;
+   IPFuncPtr userFunc;
+   void *userPtr;
+   void *userPtr2;
+   uint32 userData;
+   uint32 userData2;
+} IPSocket;
+
+//ethernet.c
+void EthernetSendPacket(const unsigned char *packet, int length); //Windows
+void EthernetInit(unsigned char MacAddress[6]);
+int EthernetReceive(unsigned char *buffer, int length);
+void EthernetTransmit(unsigned char *buffer, int length);
+
+//tcpip.c
+void IPInit(IPFuncPtr frameSendFunction, uint8 macAddress[6], char name[6]);
+IPFrame *IPFrameGet(int freeCount);
+int IPProcessEthernetPacket(IPFrame *frameIn, int length);
+void IPTick(void);
+
+IPSocket *IPOpen(IPMode_e mode, uint32 ipAddress, uint32 port, IPFuncPtr funcPtr);
+void IPWriteFlush(IPSocket *socket);
+uint32 IPWrite(IPSocket *socket, const uint8 *buf, uint32 length);
+uint32 IPRead(IPSocket *socket, uint8 *buf, uint32 length);
+void IPClose(IPSocket *socket);
+#ifdef IPPRINTF
+void IPPrintf(IPSocket *socket, char *message, int arg0, int arg1, int arg2, int arg3);
+#else
+void IPPrintf(IPSocket *socket, char *message, ...);
+#endif
+void IPResolve(char *name, IPFuncPtr resolvedFunc, void *arg);
+uint32 IPAddressSelf(void);
+
+//http.c
+#define HTML_LENGTH_CALLBACK  -2
+#define HTML_LENGTH_LIST_END  -1
+typedef struct PageEntry_s {
+   const char *name;
+   int length;
+   const char *page;
+} PageEntry_t;
+void HttpInit(const PageEntry_t *Pages, int UseFiles);
+
+//html.c
+void HtmlInit(int UseFiles);
+
+//netutil.c
+void FtpdInit(int UseFiles);
+IPSocket *FtpTransfer(uint32 ip, char *user, char *passwd, 
+                      char *filename, uint8 *buf, int size, 
+                      int send, void (*callback)(uint8 *data, int size));
+void TftpdInit(void);
+IPSocket *TftpTransfer(uint32 ip, char *filename, uint8 *buffer, int size,
+                       void (*callback)(uint8 *data, int bytes));
+void ConsoleInit(void);
+void *IPNameValue(const char *name, void *value);
+
+#endif //__TCPIP_H__
diff --git a/kernel/uart.c b/kernel/uart.c
new file mode 100644 (file)
index 0000000..f813d7a
--- /dev/null
@@ -0,0 +1,549 @@
+/*--------------------------------------------------------------------
+ * TITLE: Plasma Uart Driver
+ * AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
+ * DATE CREATED: 12/31/05
+ * FILENAME: uart.c
+ * PROJECT: Plasma CPU core
+ * COPYRIGHT: Software placed into the public domain by the author.
+ *    Software 'as is' without warranty.  Author liable for nothing.
+ * DESCRIPTION:
+ *    Plasma Uart Driver
+ *--------------------------------------------------------------------*/
+#define NO_ELLIPSIS2
+#include "plasma.h"
+#include "rtos.h"
+
+#ifndef NO_PACKETS
+#define SUPPORT_DATA_PACKETS
+#endif
+
+#define BUFFER_WRITE_SIZE 128
+#define BUFFER_READ_SIZE 128
+#define BUFFER_PRINTF_SIZE 1024
+#undef UartPrintf
+
+void UartPrintfCritical(const char *format,
+                        int arg0, int arg1, int arg2, int arg3,
+                        int arg4, int arg5, int arg6, int arg7);
+
+typedef struct Buffer_s {
+   uint8 *data;
+   int size;
+   volatile int read, write;
+   volatile int pendingRead, pendingWrite;
+   OS_Semaphore_t *semaphoreRead, *semaphoreWrite;
+} Buffer_t;
+
+static Buffer_t *WriteBuffer, *ReadBuffer;
+static OS_Semaphore_t *SemaphoreUart;
+static char PrintfString[BUFFER_PRINTF_SIZE];  //Used in UartPrintf
+
+#ifdef SUPPORT_DATA_PACKETS
+//For packet processing [0xff lengthMSB lengthLSB checksum data]
+static PacketGetFunc_t UartPacketGet;
+static uint8 *PacketCurrent;
+static uint32 UartPacketSize;
+static uint32 UartPacketChecksum, Checksum;
+static OS_MQueue_t *UartPacketMQueue;
+static uint32 PacketBytes, PacketLength;
+static uint32 UartPacketOutLength, UartPacketOutByte;
+int CountOk, CountError;
+#endif
+static uint8 *UartPacketOut;
+
+
+/******************************************/
+Buffer_t *BufferCreate(int size)
+{
+   Buffer_t *buffer;
+   buffer = (Buffer_t*)OS_HeapMalloc(NULL, sizeof(Buffer_t) + size);
+   if(buffer == NULL)
+      return NULL;
+   buffer->data = (uint8*)(buffer + 1);
+   buffer->read = 0;
+   buffer->write = 0;
+   buffer->size = size;
+   buffer->pendingRead = 0;
+   buffer->pendingWrite = 0;
+   buffer->semaphoreRead = OS_SemaphoreCreate("BufferRead", 0);
+   buffer->semaphoreWrite = OS_SemaphoreCreate("BufferWrite", 0);
+   return buffer;
+}
+
+
+void BufferWrite(Buffer_t *buffer, int value, int pend)
+{
+   int writeNext;
+
+   writeNext = buffer->write + 1;
+   if(writeNext >= buffer->size)
+      writeNext = 0;
+
+   //Check if room for value
+   if(writeNext == buffer->read)
+   {
+      if(pend == 0)
+         return;
+      ++buffer->pendingWrite;
+      OS_SemaphorePend(buffer->semaphoreWrite, OS_WAIT_FOREVER);
+   }
+
+   buffer->data[buffer->write] = (uint8)value;
+   buffer->write = writeNext;
+   if(buffer->pendingRead)
+   {
+      --buffer->pendingRead;
+      OS_SemaphorePost(buffer->semaphoreRead);
+   }
+}
+
+
+int BufferRead(Buffer_t *buffer, int pend)
+{
+   int value;
+
+   //Check if empty buffer
+   if(buffer->read == buffer->write)
+   {
+      if(pend == 0)
+         return 0;
+      ++buffer->pendingRead;
+      OS_SemaphorePend(buffer->semaphoreRead, OS_WAIT_FOREVER);
+   }
+
+   value = buffer->data[buffer->read];
+   if(++buffer->read >= buffer->size)
+      buffer->read = 0;
+   if(buffer->pendingWrite)
+   {
+      --buffer->pendingWrite;
+      OS_SemaphorePost(buffer->semaphoreWrite);
+   }
+   return value;
+}
+
+
+/******************************************/
+#ifdef SUPPORT_DATA_PACKETS
+static void UartPacketRead(uint32 value)
+{
+   uint32 message[4];
+   if(PacketBytes == 0 && value == 0xff)
+   {
+      ++PacketBytes;
+   }
+   else if(PacketBytes == 1)
+   {
+      ++PacketBytes;
+      PacketLength = value << 8;
+   }
+   else if(PacketBytes == 2)
+   {
+      ++PacketBytes;
+      PacketLength |= value;
+      if(PacketLength <= UartPacketSize)
+      {
+         if(PacketCurrent == NULL)
+            PacketCurrent = UartPacketGet();
+      }
+      else
+      {
+         PacketBytes = 0;
+      }
+   }
+   else if(PacketBytes == 3)
+   {
+      ++PacketBytes;
+      UartPacketChecksum = value;
+      Checksum = 0;
+   }
+   else if(PacketBytes >= 4)
+   {
+      if(PacketCurrent)
+         PacketCurrent[PacketBytes - 4] = (uint8)value;
+      Checksum += value;
+      ++PacketBytes;
+      if(PacketBytes - 4 >= PacketLength)
+      {
+         if((uint8)Checksum == UartPacketChecksum)
+         {
+            //Notify thread that a packet has been received
+            ++CountOk;
+            message[0] = 0;
+            message[1] = (uint32)PacketCurrent;
+            message[2] = PacketLength;
+            if(PacketCurrent)
+               OS_MQueueSend(UartPacketMQueue, message);
+            PacketCurrent = NULL;
+         }
+         else
+         {
+            ++CountError;
+            //printf("E");
+         }
+         PacketBytes = 0;
+      }
+   }
+}
+
+
+static int UartPacketWrite(void)
+{
+   int value=0, i;
+   uint32 message[4];
+   if(UartPacketOut)
+   {
+      if(UartPacketOutByte == 0)
+      {
+         value = 0xff;
+         ++UartPacketOutByte;
+      }
+      else if(UartPacketOutByte == 1)
+      {
+         value = UartPacketOutLength >> 8;
+         ++UartPacketOutByte;
+      }
+      else if(UartPacketOutByte == 2)
+      {
+         value = (uint8)UartPacketOutLength;
+         ++UartPacketOutByte;
+      }
+      else if(UartPacketOutByte == 3)
+      {
+         value = 0;
+         for(i = 0; i < (int)UartPacketOutLength; ++i)
+            value += UartPacketOut[i];
+         value = (uint8)value;
+         ++UartPacketOutByte;
+      }
+      else 
+      {
+         value = UartPacketOut[UartPacketOutByte - 4];
+         ++UartPacketOutByte;
+         if(UartPacketOutByte - 4 >= UartPacketOutLength)
+         {
+            //Notify thread that a packet has been sent
+            message[0] = 1;
+            message[1] = (uint32)UartPacketOut;
+            UartPacketOut = 0;
+            OS_MQueueSend(UartPacketMQueue, message);
+         }
+      }
+   }
+   return value;
+}
+#endif
+
+
+static void UartInterrupt(void *arg)
+{
+   uint32 status, value, count=0;
+   (void)arg;
+
+   status = OS_InterruptStatus();
+   while(status & IRQ_UART_READ_AVAILABLE)
+   {
+      value = MemoryRead(UART_READ);
+#ifdef SUPPORT_DATA_PACKETS
+      if(UartPacketGet && (value == 0xff || PacketBytes))
+         UartPacketRead(value);
+      else
+#endif
+      BufferWrite(ReadBuffer, value, 0);
+      status = OS_InterruptStatus();
+      if(++count >= 16)
+         break;
+   }
+   while(status & IRQ_UART_WRITE_AVAILABLE)
+   {
+#ifdef SUPPORT_DATA_PACKETS
+      if(UartPacketOut)
+      {
+         value = UartPacketWrite();
+         MemoryWrite(UART_WRITE, value);
+      } else 
+#endif
+      if(WriteBuffer->read != WriteBuffer->write)
+      {
+         value = BufferRead(WriteBuffer, 0);
+         MemoryWrite(UART_WRITE, value);
+      }
+      else
+      {
+         OS_InterruptMaskClear(IRQ_UART_WRITE_AVAILABLE);
+         break;
+      }
+      status = OS_InterruptStatus();
+   }
+}
+
+
+void UartInit(void)
+{
+   uint32 mask;
+
+   SemaphoreUart = OS_SemaphoreCreate("Uart", 1);
+   WriteBuffer = BufferCreate(BUFFER_WRITE_SIZE);
+   ReadBuffer = BufferCreate(BUFFER_READ_SIZE);
+
+   mask = IRQ_UART_READ_AVAILABLE | IRQ_UART_WRITE_AVAILABLE;
+   OS_InterruptRegister(mask, UartInterrupt);
+   OS_InterruptMaskSet(IRQ_UART_READ_AVAILABLE);
+}
+
+
+void UartWrite(int ch)
+{
+   BufferWrite(WriteBuffer, ch, 1);
+   OS_InterruptMaskSet(IRQ_UART_WRITE_AVAILABLE);
+}
+
+
+uint8 UartRead(void)
+{
+   return (uint8)BufferRead(ReadBuffer, 1);
+}
+
+
+void UartWriteData(uint8 *data, int length)
+{
+   OS_SemaphorePend(SemaphoreUart, OS_WAIT_FOREVER);
+   while(length--)
+      UartWrite(*data++);
+   OS_SemaphorePost(SemaphoreUart);
+}
+
+
+void UartReadData(uint8 *data, int length)
+{
+   OS_SemaphorePend(SemaphoreUart, OS_WAIT_FOREVER);
+   while(length--)
+      *data++ = UartRead();
+   OS_SemaphorePost(SemaphoreUart);
+}
+
+
+void UartPrintf(const char *format,
+                int arg0, int arg1, int arg2, int arg3,
+                int arg4, int arg5, int arg6, int arg7)
+{
+   uint8 *ptr;
+#if 0
+   //Check for string "!m#~" to mask print statement
+   static char moduleLevel[26];
+   if(format[0] == '!' && format[3] == '~')
+   {
+      int level = format[2] - '5';
+      if('a' <= format[1] && format[1] <= 'z')
+      {
+         if(level < moduleLevel[format[1] - 'a'])
+            return;
+      }
+      else if('A' <= format[1] && format[1] <= 'Z')
+         moduleLevel[format[1] - 'A'] = (char)level;
+      format += 4;
+   }
+#endif
+   OS_SemaphorePend(SemaphoreUart, OS_WAIT_FOREVER);
+   sprintf(PrintfString, format, arg0, arg1, arg2, arg3,
+           arg4, arg5, arg6, arg7);
+   ptr = (uint8*)PrintfString;
+   while(*ptr)
+   {
+      if(*ptr == '\n')
+         UartWrite('\r');
+#ifdef SUPPORT_DATA_PACKETS
+      if(*ptr == 0xff)
+         *ptr = '@';
+#endif
+      UartWrite(*ptr++);
+   }
+   OS_SemaphorePost(SemaphoreUart);
+}
+
+
+void UartPrintfPoll(const char *format,
+                    int arg0, int arg1, int arg2, int arg3,
+                    int arg4, int arg5, int arg6, int arg7)
+{
+   uint8 *ptr;
+   uint32 state;
+
+   if(SemaphoreUart)
+      OS_SemaphorePend(SemaphoreUart, OS_WAIT_FOREVER);
+   sprintf(PrintfString, format, arg0, arg1, arg2, arg3,
+           arg4, arg5, arg6, arg7);
+   ptr = (uint8*)PrintfString;
+   while(*ptr)
+   {
+      while((MemoryRead(IRQ_STATUS) & IRQ_UART_WRITE_AVAILABLE) == 0)
+         ;
+      state = OS_CriticalBegin();
+      if((MemoryRead(IRQ_STATUS) & IRQ_UART_WRITE_AVAILABLE) &&
+         UartPacketOut == NULL)
+      {
+         MemoryWrite(UART_WRITE, *ptr++);
+      }
+      OS_CriticalEnd(state);
+   }
+   if(SemaphoreUart)
+      OS_SemaphorePost(SemaphoreUart);
+}
+
+
+void UartPrintfCritical(const char *format,
+                        int arg0, int arg1, int arg2, int arg3,
+                        int arg4, int arg5, int arg6, int arg7)
+{
+   uint8 *ptr;
+   uint32 state;
+
+   state = OS_CriticalBegin();
+   sprintf(PrintfString, format, arg0, arg1, arg2, arg3,
+           arg4, arg5, arg6, arg7);
+   ptr = (uint8*)PrintfString;
+   while(*ptr)
+   {
+      while((MemoryRead(IRQ_STATUS) & IRQ_UART_WRITE_AVAILABLE) == 0)
+         ;
+      MemoryWrite(UART_WRITE, *ptr++);
+#ifdef SUPPORT_DATA_PACKETS
+      if(UartPacketOut && UartPacketOutByte - 4 < UartPacketOutLength)
+      {
+         ++UartPacketOutByte;
+         --ptr;
+      }
+#endif
+   }
+   memset(PrintfString, 0, sizeof(PrintfString));
+   OS_CriticalEnd(state);
+}
+
+
+void UartPrintfNull(void)
+{
+}
+
+
+void UartScanf(const char *format,
+               int arg0, int arg1, int arg2, int arg3,
+               int arg4, int arg5, int arg6, int arg7)
+{
+   int index = 0, ch;
+   OS_SemaphorePend(SemaphoreUart, OS_WAIT_FOREVER);
+   for(;;)
+   {
+      ch = UartRead();
+      if(ch != '\b' || index)
+         UartWrite(ch);
+      if(ch == '\n' || ch == '\r')
+         break;
+      else if(ch == '\b')
+      {
+         if(index)
+         {
+            UartWrite(' ');
+            UartWrite(ch);
+            --index;
+         }
+      }
+      else if(index < sizeof(PrintfString))
+         PrintfString[index++] = (uint8)ch;
+   }
+   UartWrite('\n');
+   PrintfString[index] = 0;
+   sscanf(PrintfString, format, arg0, arg1, arg2, arg3,
+          arg4, arg5, arg6, arg7);
+   OS_SemaphorePost(SemaphoreUart);
+}
+
+
+#ifdef SUPPORT_DATA_PACKETS
+void UartPacketConfig(PacketGetFunc_t PacketGetFunc, 
+                      int PacketSize, 
+                      OS_MQueue_t *mQueue)
+{
+   UartPacketGet = PacketGetFunc;
+   UartPacketSize = PacketSize;
+   UartPacketMQueue = mQueue;
+}
+
+
+void UartPacketSend(uint8 *data, int bytes)
+{
+   UartPacketOutByte = 0;
+   UartPacketOutLength = bytes;
+   UartPacketOut = data;
+   OS_InterruptMaskSet(IRQ_UART_WRITE_AVAILABLE);
+}
+#else
+void UartPacketConfig(PacketGetFunc_t PacketGetFunc, 
+                      int PacketSize, 
+                      OS_MQueue_t *mQueue)
+{ (void)PacketGetFunc; (void)PacketSize; (void)mQueue; }
+
+
+void UartPacketSend(uint8 *data, int bytes)
+{ (void)data; (void)bytes; }
+#endif
+
+
+void Led(int mask, int value)
+{\r
+   mask &= 0xff;
+   MemoryWrite(GPIO0_CLEAR, mask);       //clear
+   MemoryWrite(GPIO0_OUT, value & mask); //set LEDs
+}
+
+
+/******************************************/
+int puts(const char *string)
+{
+   uint8 *ptr;
+   OS_SemaphorePend(SemaphoreUart, OS_WAIT_FOREVER);
+   ptr = (uint8*)string;
+   while(*ptr)
+   {
+      if(*ptr == '\n')
+         UartWrite('\r');
+      UartWrite(*ptr++);
+   }
+   OS_SemaphorePost(SemaphoreUart);
+   return 0;
+}
+
+
+int getch(void)
+{
+   return BufferRead(ReadBuffer, 1);
+}
+
+
+int kbhit(void)
+{
+   return ReadBuffer->read != ReadBuffer->write;
+}
+
+
+/******************************************/
+#if 0
+int LogArray[100], LogIndex;
+void LogWrite(int a)
+{
+   if(LogIndex < sizeof(LogArray)/4)
+      LogArray[LogIndex++] = a;
+}
+
+void LogDump(void)
+{
+   int i;
+   for(i = 0; i < LogIndex; ++i)
+   {
+      if(LogArray[i] > 0xfff)
+         UartPrintfCritical("\n", 0,0,0,0,0,0,0,0);
+      UartPrintfCritical("0x%x ", LogArray[i], 0,0,0,0,0,0,0);
+   }
+   LogIndex = 0;
+}
+#endif
+
diff --git a/tools/bintohex.c b/tools/bintohex.c
new file mode 100644 (file)
index 0000000..67bf1df
--- /dev/null
@@ -0,0 +1,64 @@
+/*bintohex by Steve Rhoads 5/29/02*/
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define BUF_SIZE (1024*1024)
+
+int main(int argc, char *argv[])
+{
+   FILE *file;
+   unsigned char *buf;
+   unsigned long size, mem_size = 1024 * 4, i, j, k, sum;
+   char filename[80];
+
+   if(argc < 2)
+   {
+      printf ("usage: bintohex infile\n");
+      return -1;
+   }
+   file = fopen(argv[1], "rb");
+   if(file == NULL)
+   {
+      printf("Can't open %s\n", argv[1]);
+      return -1;
+   }
+
+   buf = (unsigned char *)malloc(BUF_SIZE);
+   memset(buf, 0, BUF_SIZE);
+   size = fread(buf, 1, BUF_SIZE, file);
+   mem_size = size;
+   if(size > mem_size)
+   {
+      printf("FILE TOO LARGE!!!!!!!!!!!\n");
+      return -1;
+   }
+   fclose(file);
+   strcpy(filename, "codeX.hex");
+
+   for(i = 0; i < 4; ++i)
+   {
+      filename[4] = '0' + i;
+      file = fopen(filename, "wb");
+      for(j = 0; i + j * 4 * 16 < mem_size; ++j)
+      {
+         k = j * 16;
+         fprintf(file, ":10%4.4x00", (int)k);
+         sum = 0x10 + (k >> 8) + (k & 0xff);
+         for(k = 0; k < 16; ++k)
+         {
+            fprintf(file, "%2.2x", buf[i + j * 4 * 16 + k * 4]);
+            sum += buf[i + j * 4 * 16 + k * 4];
+         }
+         sum &= 0xff;
+         sum = 0x100 - sum;
+         sum &= 0xff;
+         fprintf(file, "%2.2x\n", (int)sum);
+      }
+      fprintf(file, ":00000001ff\n");
+      fclose(file);
+   }
+   free(buf);
+   return 0;
+}
+
diff --git a/tools/boot.asm b/tools/boot.asm
new file mode 100644 (file)
index 0000000..9b412a9
--- /dev/null
@@ -0,0 +1,239 @@
+##################################################################
+# TITLE: Boot Up Code
+# AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
+# DATE CREATED: 1/12/02
+# FILENAME: boot.asm
+# PROJECT: Plasma CPU core
+# COPYRIGHT: Software placed into the public domain by the author.
+#    Software 'as is' without warranty.  Author liable for nothing.
+# DESCRIPTION:
+#    Initializes the stack pointer and jumps to main().
+##################################################################
+   #Reserve 512 bytes for stack
+   .comm InitStack, 512
+
+   .text
+   .align 2
+   .global entry
+   .ent        entry
+entry:
+   .set noreorder
+
+   #These four instructions should be the first instructions.
+   #convert.exe previously initialized $gp, .sbss_start, .bss_end, $sp
+   la    $gp, _gp             #initialize global pointer
+   la    $5, __bss_start      #$5 = .sbss_start
+   la    $4, _end             #$2 = .bss_end
+   la    $sp, InitStack+488   #initialize stack pointer
+
+$BSS_CLEAR:
+   sw    $0, 0($5)
+   slt   $3, $5, $4
+   bnez  $3, $BSS_CLEAR
+   addiu $5, $5, 4
+
+   jal   main
+   nop
+$L1:
+   j $L1
+
+   .end entry
+
+
+###################################################
+   #address 0x3c
+   .global interrupt_service_routine
+   .ent interrupt_service_routine
+interrupt_service_routine:
+   .set noreorder
+   .set noat
+
+   #Registers $26 and $27 are reserved for the OS
+   #Save all temporary registers
+   #Slots 0($29) through 12($29) reserved for saving a0-a3
+   addi  $29, $29, -104  #adjust sp
+   sw    $1,  16($29)    #at
+   sw    $2,  20($29)    #v0
+   sw    $3,  24($29)    #v1
+   sw    $4,  28($29)    #a0
+   sw    $5,  32($29)    #a1
+   sw    $6,  36($29)    #a2
+   sw    $7,  40($29)    #a3
+   sw    $8,  44($29)    #t0
+   sw    $9,  48($29)    #t1
+   sw    $10, 52($29)    #t2
+   sw    $11, 56($29)    #t3
+   sw    $12, 60($29)    #t4
+   sw    $13, 64($29)    #t5
+   sw    $14, 68($29)    #t6
+   sw    $15, 72($29)    #t7
+   sw    $24, 76($29)    #t8
+   sw    $25, 80($29)    #t9
+   sw    $31, 84($29)    #lr
+   mfc0  $26, $14        #C0_EPC=14 (Exception PC)
+   addi  $26, $26, -4    #Backup one opcode
+   sw    $26, 88($29)    #pc
+   mfhi  $27
+   sw    $27, 92($29)    #hi
+   mflo  $27
+   sw    $27, 96($29)    #lo
+
+   lui   $6,  0x2000    
+   lw    $4,  0x20($6)   #IRQ_STATUS
+   lw    $6,  0x10($6)   #IRQ_MASK
+   and   $4,  $4, $6
+   jal   OS_InterruptServiceRoutine
+   addi  $5,  $29, 0
+
+   #Restore all temporary registers
+   lw    $1,  16($29)    #at
+   lw    $2,  20($29)    #v0
+   lw    $3,  24($29)    #v1
+   lw    $4,  28($29)    #a0
+   lw    $5,  32($29)    #a1
+   lw    $6,  36($29)    #a2
+   lw    $7,  40($29)    #a3
+   lw    $8,  44($29)    #t0
+   lw    $9,  48($29)    #t1
+   lw    $10, 52($29)    #t2
+   lw    $11, 56($29)    #t3
+   lw    $12, 60($29)    #t4
+   lw    $13, 64($29)    #t5
+   lw    $14, 68($29)    #t6
+   lw    $15, 72($29)    #t7
+   lw    $24, 76($29)    #t8
+   lw    $25, 80($29)    #t9
+   lw    $31, 84($29)    #lr
+   lw    $26, 88($29)    #pc
+   lw    $27, 92($29)    #hi
+   mthi  $27
+   lw    $27, 96($29)    #lo
+   mtlo  $27
+   addi  $29, $29, 104   #adjust sp
+
+isr_return:
+   ori   $27, $0, 0x1    #re-enable interrupts
+   jr    $26
+   mtc0  $27, $12        #STATUS=1; enable interrupts
+
+   .end interrupt_service_routine
+   .set at
+
+
+###################################################
+   .global OS_AsmInterruptEnable
+   .ent OS_AsmInterruptEnable
+OS_AsmInterruptEnable:
+   .set noreorder
+   mfc0  $2, $12
+   jr    $31
+   mtc0  $4, $12            #STATUS=1; enable interrupts
+   #nop
+   .set reorder
+   .end OS_AsmInterruptEnable
+
+
+###################################################
+   .global  OS_AsmInterruptInit
+   .ent    OS_AsmInterruptInit
+OS_AsmInterruptInit:
+   .set noreorder
+   #Patch interrupt vector to 0x1000003c
+   la    $5, OS_AsmPatchValue
+   lw    $6, 0($5)
+   sw    $6, 0x3c($0)
+   lw    $6, 4($5)
+   sw    $6, 0x40($0)
+   lw    $6, 8($5)
+   sw    $6, 0x44($0)
+   lw    $6, 12($5)
+   jr    $31
+   sw    $6, 0x48($0)
+
+OS_AsmPatchValue:
+   #Registers $26 and $27 are reserved for the OS
+   #Code to place at address 0x3c
+   lui   $26, 0x1000
+   ori   $26, $26, 0x3c
+   jr    $26
+   nop
+
+   .set reorder
+   .end OS_AsmInterruptInit
+
+
+###################################################
+   .global   setjmp
+   .ent     setjmp
+setjmp:
+   .set noreorder
+   sw    $16, 0($4)   #s0
+   sw    $17, 4($4)   #s1
+   sw    $18, 8($4)   #s2
+   sw    $19, 12($4)  #s3
+   sw    $20, 16($4)  #s4
+   sw    $21, 20($4)  #s5
+   sw    $22, 24($4)  #s6
+   sw    $23, 28($4)  #s7
+   sw    $30, 32($4)  #s8
+   sw    $28, 36($4)  #gp
+   sw    $29, 40($4)  #sp
+   sw    $31, 44($4)  #lr
+   jr    $31
+   ori   $2,  $0, 0
+
+   .set reorder
+   .end setjmp
+
+
+###################################################
+   .global   longjmp
+   .ent     longjmp
+longjmp:
+   .set noreorder
+   lw    $16, 0($4)   #s0
+   lw    $17, 4($4)   #s1
+   lw    $18, 8($4)   #s2
+   lw    $19, 12($4)  #s3
+   lw    $20, 16($4)  #s4
+   lw    $21, 20($4)  #s5
+   lw    $22, 24($4)  #s6
+   lw    $23, 28($4)  #s7
+   lw    $30, 32($4)  #s8
+   lw    $28, 36($4)  #gp
+   lw    $29, 40($4)  #sp
+   lw    $31, 44($4)  #lr
+   jr    $31
+   ori   $2,  $5, 0
+
+   .set reorder
+   .end longjmp
+
+
+###################################################
+   .global   OS_AsmMult
+   .ent     OS_AsmMult
+OS_AsmMult:
+   .set noreorder
+   multu $4, $5
+   mflo  $2
+   mfhi  $4
+   jr    $31
+   sw    $4, 0($6)
+
+   .set reorder
+   .end OS_AsmMult
+
+
+###################################################
+   .global OS_Syscall
+   .ent OS_Syscall
+OS_Syscall:
+   .set noreorder
+   syscall 0
+   jr    $31
+   nop
+   .set reorder
+   .end OS_Syscall
+
+
diff --git a/tools/bootldr.c b/tools/bootldr.c
new file mode 100644 (file)
index 0000000..40b7646
--- /dev/null
@@ -0,0 +1,265 @@
+/*--------------------------------------------------------------------
+ * TITLE: Plasma Bootloader
+ * AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
+ * DATE CREATED: 12/17/05
+ * FILENAME: bootldr.c
+ * PROJECT: Plasma CPU core
+ * COPYRIGHT: Software placed into the public domain by the author.
+ *    Software 'as is' without warranty.  Author liable for nothing.
+ * DESCRIPTION:
+ *    Plasma bootloader.
+ *--------------------------------------------------------------------*/
+#include "plasma.h"
+
+#define MemoryRead(A) (*(volatile unsigned long*)(A))
+#define MemoryWrite(A,V) *(volatile unsigned long*)(A)=(V)
+
+extern int putchar(int ch);
+extern int puts(const char *string);
+extern int getch(void);
+extern int kbhit(void);
+extern int DdrInit(void);
+
+typedef void (*FuncPtr)(void);
+typedef unsigned long uint32;
+typedef unsigned short uint16;
+
+
+void FlashRead(uint16 *dst, uint32 byteOffset, int bytes)
+{
+   volatile uint32 *ptr=(uint32*)(FLASH_BASE + (byteOffset << 1));
+   *ptr = 0xff;                   //read mode
+   while(bytes > 0)
+   {
+      *dst++ = (uint16)*ptr++;
+      bytes -= 2;
+   }
+}
+
+
+void FlashWrite(uint16 *src, uint32 byteOffset, int bytes)
+{
+   volatile uint32 *ptr=(uint32*)(FLASH_BASE + (byteOffset << 1));
+   while(bytes > 0)
+   {
+      *ptr = 0x40;                //write mode
+      *ptr++ = *src++;            //write data
+      while((*ptr & 0x80) == 0)   //check status
+         ;
+      bytes -= 2;
+   }
+}
+
+
+void FlashErase(uint32 byteOffset)
+{
+   volatile uint32 *ptr=(uint32*)(FLASH_BASE + (byteOffset << 1));
+   *ptr = 0x20;                   //erase block
+   *ptr = 0xd0;                   //confirm
+   while((*ptr & 0x80) == 0)      //check status
+      ;
+}
+
+
+char *xtoa(unsigned long num)
+{
+   static char buf[12];
+   int i, digit;
+   buf[8] = 0;
+   for (i = 7; i >= 0; --i)
+   {
+      digit = num & 0xf;
+      buf[i] = digit + (digit < 10 ? '0' : 'A' - 10);
+      num >>= 4;
+   }
+   return buf;
+}
+
+
+unsigned long getnum(void)
+{
+   int i;
+   unsigned long ch, ch2, value=0;
+   for(i = 0; i < 16; )
+   {
+      ch = ch2 = getch();
+      if(ch == '\n' || ch == '\r')
+         break;
+      if('0' <= ch && ch <= '9')
+         ch -= '0';
+      else if('A' <= ch && ch <= 'Z')
+         ch = ch - 'A' + 10;
+      else if('a' <= ch && ch <= 'z')
+         ch = ch - 'a' + 10;
+      else if(ch == 8)
+      {
+         if(i > 0)
+         {
+            --i;
+            putchar(ch);
+            putchar(' ');
+            putchar(ch);
+         }
+         value >>= 4;
+         continue;
+      }
+      putchar(ch2);
+      value = (value << 4) + ch;
+      ++i;
+   }
+   putchar('\r');
+   putchar('\n');
+   return value;
+}
+
+
+int main(void)
+{
+   int i, j, ch;
+   unsigned long address, value, count;
+   FuncPtr funcPtr;
+   unsigned char *ptr1;
+
+   DdrInit();  //Harmless if SDRAM instead of DDR
+
+   puts("\nGreetings from the bootloader ");
+   puts(__DATE__);
+   puts(" ");
+   puts(__TIME__);
+   puts(":\n");
+   MemoryWrite(FLASH_BASE, 0xff);  //read mode
+   if((MemoryRead(GPIOA_IN) & 1) && (MemoryRead(FLASH_BASE) & 0xffff) == 0x3c1c)
+   {
+      puts("Boot from flash\n");
+      FlashRead((uint16*)RAM_EXTERNAL_BASE, 0, 1024*128);
+      funcPtr = (FuncPtr)RAM_EXTERNAL_BASE;
+      funcPtr();
+   }
+   for(;;)
+   {
+      puts("\nWaiting for binary image linked at 0x10000000\n");
+      puts("Other Menu Options:\n");
+      puts("1. Memory read word\n");
+      puts("2. Memory write word\n");
+      puts("3. Memory read byte\n");
+      puts("4. Memory write byte\n");
+      puts("5. Jump to address\n");
+      puts("6. Raw memory read\n");
+      puts("7. Raw memory write\n");
+      puts("8. Checksum\n");
+      puts("9. Dump\n");
+      puts("F. Copy 128KB from DDR to flash\n");
+      puts("> ");
+      ch = getch();
+      address = 0;
+      if('0' <= ch && ch <= '9')
+      {
+         putchar(ch);
+         puts("\nAddress in hex> ");
+         address = getnum();
+         puts("Address = ");
+         puts(xtoa(address));
+         puts("\n");
+      }
+      switch(ch)
+      {
+      case '1':
+         value = MemoryRead(address);
+         puts(xtoa(value));
+         puts("\n");
+         break;
+      case '2':
+         puts("\nValue in hex> ");
+         value = getnum();
+         puts(xtoa(value));
+         MemoryWrite(address, value);
+         break;
+      case '3':
+         value = *(unsigned char*)address;
+         puts(xtoa(value));
+         puts("\n");
+         break;
+      case '4':
+         puts("\nValue in hex> ");
+         value = getnum();
+         puts(xtoa(value));
+         *(unsigned char*)address = value;
+         break;
+      case '5':
+         funcPtr = (FuncPtr)address;
+         funcPtr();
+         break;
+      case '6':
+         puts("\nCount in hex> ");
+         count = getnum();
+         for(i = 0; i < count; ++i)
+         {
+            ch = *(unsigned char*)(address + i);
+            putchar(ch);
+         }
+         break;
+      case '7':
+         puts("\nCount in hex> ");
+         count = getnum();
+         for(i = 0; i < count; ++i)
+         {
+            ch = getch();
+            *(unsigned char*)(address+i) = ch;
+         }
+         break;
+      case '8':
+         puts("\nCount in hex> ");
+         count = getnum();
+         value = 0;
+         for(i = 0; i < count; ++i)
+         {
+            value += *(unsigned char*)(address+i);
+         }
+         puts(xtoa(value));
+         putchar('\n');
+         break;
+      case '9':
+         puts("\nCount in hex> ");
+         count = getnum();
+         value = 0;
+         for(i = 0; i < count; i += 4)
+         {
+            if((i & 15) == 0)
+               puts("\r\n");
+            value = *(unsigned long*)(address+i);
+            puts(xtoa(value));
+            putchar(' ');
+         }
+         puts("\r\n");
+         break;
+      case 'F':
+         puts("\nConfirm with 12345678> ");
+         value = getnum();
+         if(value == 0x12345678)
+         {
+            FlashErase(0);
+            FlashWrite((uint16*)RAM_EXTERNAL_BASE, 0, 1024*128);
+         }
+         break;
+      case 0x3c:   //raw test.bin file
+         ptr1 = (unsigned char*)0x10000000;
+         for(i = 0; i < 1024*1024; ++i)
+         {
+            ptr1[i] = (unsigned char)ch;
+            for(j = 0; j < 10000; ++j)
+            {
+               if(kbhit())
+                  break;
+            }
+            if(j >= 10000)
+               break;       //assume end of file
+            ch = getch();
+         }
+         funcPtr = (FuncPtr)0x10000000;
+         funcPtr();
+         break;
+      }
+   }
+   return 0;
+}
+
diff --git a/tools/convert.c b/tools/convert.c
new file mode 100644 (file)
index 0000000..f87e485
--- /dev/null
@@ -0,0 +1,258 @@
+//convert.c by Steve Rhoads 4/26/01
+//Now uses the ELF format (get gccmips_elf.zip)
+//set $gp and zero .sbss and .bss
+//Reads test.axf and creates code.txt
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define BUF_SIZE (1024*1024*4) 
+/*Assumes running on PC little endian*/
+#ifndef USE_BIG_ENDIAN
+#define ntohl(A) (((A)>>24)|(((A)&0x00ff0000)>>8)|(((A)&0xff00)<<8)|((A)<<24))
+#define ntohs(A) (uint16)((((A)&0xff00)>>8)|((A)<<8))
+#else
+#define ntohl(A) A
+#define ntohs(A) A
+#endif
+
+#define EI_NIDENT 16
+#define SHT_PROGBITS 1
+#define SHT_STRTAB 3
+#define SHT_NOBITS 8
+
+typedef unsigned int   uint32;
+typedef unsigned short uint16;
+typedef unsigned char  uint8;
+
+typedef struct
+{
+   uint8 e_ident[EI_NIDENT];
+   uint16 e_e_type;
+   uint16 e_machine;
+   uint32 e_version;
+   uint32 e_entry;
+   uint32 e_phoff;
+   uint32 e_shoff;
+   uint32 e_flags;
+   uint16 e_ehsize;
+   uint16 e_phentsize;
+   uint16 e_phnum;
+   uint16 e_shentsize;
+   uint16 e_shnum;
+   uint16 e_shstrndx;
+} ElfHeader;
+
+typedef struct
+{
+   uint32 p_type;
+   uint32 p_offset;
+   uint32 p_vaddr;
+   uint32 p_paddr;
+   uint32 p_filesz;
+   uint32 p_memsz;
+   uint32 p_flags;
+   uint32 p_align;
+} Elf32_Phdr;
+
+typedef struct
+{
+   uint32 sh_name;
+   uint32 sh_type;
+   uint32 sh_flags;
+   uint32 sh_addr;
+   uint32 sh_offset;
+   uint32 sh_size;
+   uint32 sh_link;
+   uint32 sh_info;
+   uint32 sh_addralign;
+   uint32 sh_entsize;
+} Elf32_Shdr;
+
+typedef struct 
+{
+   uint32 ri_gprmask;
+   uint32 ri_cprmask[4];
+   uint32 ri_gp_value;
+} ELF_RegInfo;
+
+#define PT_MIPS_REGINFO  0x70000000
+#define SHT_MIPS_REGINFO 0x70000006
+
+void set_low(uint8 *ptr, uint32 address, uint32 value)
+{
+   uint32 opcode;
+   opcode = *(uint32 *)(ptr + address);
+   opcode = ntohl(opcode);
+   opcode = (opcode & 0xffff0000) | (value & 0xffff);
+   opcode = ntohl(opcode);
+   *(uint32 *)(ptr + address) = opcode;
+}
+
+int main(int argc, char *argv[])
+{
+   FILE *infile, *outfile, *txtfile;
+   uint8 *buf, *code;
+   long size, stack_pointer;
+   uint32 length, d, i, gp_ptr = 0, gp_ptr_backup = 0;
+   uint32 bss_start = 0, bss_end = 0;
+
+   ElfHeader *elfHeader;
+   Elf32_Phdr *elfProgram;
+   ELF_RegInfo *elfRegInfo;
+   Elf32_Shdr *elfSection;
+   (void)argc; 
+   (void)argv;
+   (void)stack_pointer;
+
+   printf("test.axf -> code.txt & test.bin\n");
+   infile = fopen("test.axf", "rb");
+   if(infile == NULL)
+   {
+      printf("Can't open test.axf");
+      return 0;
+   }
+   buf = (uint8*)malloc(BUF_SIZE);
+   size = (int)fread(buf, 1, BUF_SIZE, infile);
+   fclose(infile);
+   code = (uint8*)malloc(BUF_SIZE);
+   memset(code, 0, BUF_SIZE);
+
+   elfHeader = (ElfHeader *)buf;
+   if(strncmp((char*)elfHeader->e_ident + 1, "ELF", 3))
+   {
+      printf("Error:  Not an ELF file!\n");
+      printf("Use the gccmips_elf.zip from opencores/projects/plasma!\n");
+      return -1;
+   }
+
+   elfHeader->e_entry = ntohl(elfHeader->e_entry);
+   elfHeader->e_phoff = ntohl(elfHeader->e_phoff);
+   elfHeader->e_shoff = ntohl(elfHeader->e_shoff);
+   elfHeader->e_flags = ntohl(elfHeader->e_flags);
+   elfHeader->e_phentsize = ntohs(elfHeader->e_phentsize);
+   elfHeader->e_phnum = ntohs(elfHeader->e_phnum);
+   elfHeader->e_shentsize = ntohs(elfHeader->e_shentsize);
+   elfHeader->e_shnum = ntohs(elfHeader->e_shnum);
+   printf("Entry=0x%x ", elfHeader->e_entry);
+   length = 0;
+
+   for(i = 0; i < elfHeader->e_phnum; ++i)
+   {
+      elfProgram = (Elf32_Phdr *)(buf + elfHeader->e_phoff +
+                         elfHeader->e_phentsize * i);
+      elfProgram->p_type = ntohl(elfProgram->p_type);
+      elfProgram->p_offset = ntohl(elfProgram->p_offset);
+      elfProgram->p_vaddr = ntohl(elfProgram->p_vaddr);
+      elfProgram->p_filesz = ntohl(elfProgram->p_filesz);
+      elfProgram->p_memsz = ntohl(elfProgram->p_memsz);
+      elfProgram->p_flags = ntohl(elfProgram->p_flags);
+
+      elfProgram->p_vaddr -= elfHeader->e_entry;
+
+      if(elfProgram->p_type == PT_MIPS_REGINFO)
+      {
+         elfRegInfo = (ELF_RegInfo*)(buf + elfProgram->p_offset);
+         gp_ptr = ntohl(elfRegInfo->ri_gp_value);
+      }
+      if(elfProgram->p_vaddr < BUF_SIZE)
+      {
+         //printf("[0x%x,0x%x,0x%x,0x%x,0x%x]\n", elfProgram->p_vaddr,
+         //   elfProgram->p_offset, elfProgram->p_filesz, elfProgram->p_memsz,
+         //   elfProgram->p_flags);
+         memcpy(code + elfProgram->p_vaddr, buf + elfProgram->p_offset,
+                 elfProgram->p_filesz);
+         length = elfProgram->p_vaddr + elfProgram->p_filesz;
+         //printf("length = %d 0x%x\n", length, length);
+      }
+   }
+
+   for(i = 0; i < elfHeader->e_shnum; ++i)
+   {
+      elfSection = (Elf32_Shdr *)(buf + elfHeader->e_shoff +
+                         elfHeader->e_shentsize * i);
+      elfSection->sh_name = ntohl(elfSection->sh_name);
+      elfSection->sh_type = ntohl(elfSection->sh_type);
+      elfSection->sh_addr = ntohl(elfSection->sh_addr);
+      elfSection->sh_offset = ntohl(elfSection->sh_offset);
+      elfSection->sh_size = ntohl(elfSection->sh_size);
+
+      if(elfSection->sh_type == SHT_MIPS_REGINFO)
+      {
+         elfRegInfo = (ELF_RegInfo*)(buf + elfSection->sh_offset);
+         gp_ptr = ntohl(elfRegInfo->ri_gp_value);
+      }
+      if(elfSection->sh_type == SHT_PROGBITS)
+      {
+         //printf("elfSection->sh_addr=0x%x\n", elfSection->sh_addr);
+         if(elfSection->sh_addr > gp_ptr_backup)
+            gp_ptr_backup = elfSection->sh_addr;
+      }
+      if(elfSection->sh_type == SHT_NOBITS)
+      {
+         if(bss_start == 0)
+         {
+            bss_start = elfSection->sh_addr;
+         }
+         bss_end = elfSection->sh_addr + elfSection->sh_size;
+      }
+   }
+
+   if(length > bss_start - elfHeader->e_entry)
+   {
+      length = bss_start - elfHeader->e_entry;
+   }
+   if(bss_start == length)
+   {
+      bss_start = length;
+      bss_end = length + 4;
+   }
+   if(gp_ptr == 0)
+      gp_ptr = gp_ptr_backup + 0x7ff0;
+
+#if 0
+   /*Initialize the $gp register for sdata and sbss */
+   printf("gp_ptr=0x%x ", gp_ptr);
+   /*modify the first opcodes in boot.asm */
+   /*modify the lui opcode */
+   set_low(code, 0, gp_ptr >> 16);
+   /*modify the ori opcode */
+   set_low(code, 4, gp_ptr & 0xffff);
+
+   /*Clear .sbss and .bss */
+   printf("sbss=0x%x bss_end=0x%x\nlength=0x%x ", bss_start, bss_end, length);
+   set_low(code, 8, bss_start >> 16);
+   set_low(code, 12, bss_start & 0xffff);
+   set_low(code, 16, bss_end >> 16);
+   set_low(code, 20, bss_end & 0xffff);
+
+   /*Set stack pointer */
+   if(elfHeader->e_entry < 0x10000000)
+      stack_pointer = bss_end + 512;
+   else
+      stack_pointer = bss_end + 1024 * 4;
+   stack_pointer &= ~7;
+   printf("SP=0x%x\n", stack_pointer);
+   set_low(code, 24, stack_pointer >> 16);
+   set_low(code, 28, stack_pointer & 0xffff);
+#endif
+
+   /*write out test.bin */
+   outfile = fopen("test.bin", "wb");
+   fwrite(code, length, 1, outfile);
+   fclose(outfile);
+
+   /*write out code.txt */
+   txtfile = fopen("code.txt", "w");
+   for(i = 0; i <= length; i += 4)
+   {
+      d = ntohl(*(uint32 *)(code + i));
+      fprintf(txtfile, "%8.8x\n", d);
+   }
+   fclose(txtfile);
+   free(buf);
+   printf("length=%d=0x%x\n", length, length);
+
+   return 0;
+}
+
diff --git a/tools/count.c b/tools/count.c
new file mode 100644 (file)
index 0000000..b0225a3
--- /dev/null
@@ -0,0 +1,142 @@
+/*count.c*/
+int putchar(int value);
+int puts(const char *string);
+
+char *name[] = {
+   "", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine",
+   "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen",
+   "sixteen", "seventeen", "eighteen", "nineteen",
+   "", "ten", "twenty", "thirty", "forty", "fifty", "sixty", "seventy",
+   "eighty", "ninety"
+};
+
+char *xtoa(unsigned long num)
+{
+   static char buf[12];
+   int i, digit;
+   buf[8] = 0;
+   for (i = 7; i >= 0; --i)
+   {
+      digit = num & 0xf;
+      buf[i] = digit + (digit < 10 ? '0' : 'A' - 10);
+      num >>= 4;
+   }
+   return buf;
+}
+
+char *itoa10(unsigned long num)
+{
+   static char buf[12];
+   int i;
+   buf[10] = 0;
+   for (i = 9; i >= 0; --i)
+   {
+      buf[i] = (char)((num % 10) + '0');
+      num /= 10;
+   }
+   return buf;
+}
+
+void number_text(unsigned long number)
+{
+   int digit;
+   puts(itoa10(number));
+   puts(": ");
+   if(number >= 1000000000)
+   {
+      digit = number / 1000000000;
+      puts(name[digit]);
+      puts(" billion ");
+      number %= 1000000000;
+   }
+   if(number >= 100000000)
+   {
+      digit = number / 100000000;
+      puts(name[digit]);
+      puts(" hundred ");
+      number %= 100000000;
+      if(number < 1000000)
+      {
+         puts("million ");
+      }
+   }
+   if(number >= 20000000)
+   {
+      digit = number / 10000000;
+      puts(name[digit + 20]);
+      putchar(' ');
+      number %= 10000000;
+      if(number < 1000000)
+      {
+         puts("million ");
+      }
+   }
+   if(number >= 1000000)
+   {
+      digit = number / 1000000;
+      puts(name[digit]);
+      puts(" million ");
+      number %= 1000000;
+   }
+   if(number >= 100000)
+   {
+      digit = number / 100000;
+      puts(name[digit]);
+      puts(" hundred ");
+      number %= 100000;
+      if(number < 1000)
+      {
+         puts("thousand ");
+      }
+   }
+   if(number >= 20000)
+   {
+      digit = number / 10000;
+      puts(name[digit + 20]);
+      putchar(' ');
+      number %= 10000;
+      if(number < 1000)
+      {
+         puts("thousand ");
+      }
+   }
+   if(number >= 1000)
+   {
+      digit = number / 1000;
+      puts(name[digit]);
+      puts(" thousand ");
+      number %= 1000;
+   }
+   if(number >= 100)
+   {
+      digit = number / 100;
+      puts(name[digit]);
+      puts(" hundred ");
+      number %= 100;
+   }
+   if(number >= 20)
+   {
+      digit = number / 10;
+      puts(name[digit + 20]);
+      putchar(' ');
+      number %= 10;
+   }
+   puts(name[number]);
+   putchar ('\r');
+   putchar ('\n');
+}
+
+
+int main()
+{
+   unsigned long number, i=0;
+
+   number = 3;
+   for(i = 0;; ++i)
+   {
+      number_text(number);
+      number *= 3;
+      //++number;
+   }
+}
+
diff --git a/tools/cpu.gif b/tools/cpu.gif
new file mode 100644 (file)
index 0000000..d21dfb6
Binary files /dev/null and b/tools/cpu.gif differ
diff --git a/tools/ddr_init.c b/tools/ddr_init.c
new file mode 100644 (file)
index 0000000..1a5863e
--- /dev/null
@@ -0,0 +1,88 @@
+/*--------------------------------------------------------------------
+ * TITLE: Plasma DDR Initialization
+ * AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
+ * DATE CREATED: 12/17/05
+ * FILENAME: ddr_init.c
+ * PROJECT: Plasma CPU core
+ * COPYRIGHT: Software placed into the public domain by the author.
+ *    Software 'as is' without warranty.  Author liable for nothing.
+ * DESCRIPTION:
+ *    Plasma DDR Initialization
+ *    Supports 64MB (512Mb) MT46V32M16 by default.
+ *    For 32 MB and 128 MB DDR parts change AddressLines and Bank shift:
+ *    For 32 MB change 13->12 and 11->10.  MT46V16M16
+ *    For 128 MB change 13->14 and 11->12. MT46V64M16
+ *--------------------------------------------------------------------*/
+#define DDR_BASE 0x10000000
+#define MemoryRead(A) (*(volatile int*)(A))
+#define MemoryWrite(A,V) *(volatile int*)(A)=(V)
+
+extern int putchar(int value);
+extern int puts(const char *string);
+extern void print_hex(unsigned long num);
+
+//SD_A  <= address_reg(25 downto 13);  --address row
+//SD_BA <= address_reg(12 downto 11);  --bank_address
+//cmd   := address_reg(6 downto 4);    --bits RAS & CAS & WE
+int DdrInitData[] = {
+// AddressLines    Bank        Command
+   (0x000 << 13) | (0 << 11) | (7 << 4),  //CKE=1; NOP="111"
+   (0x400 << 13) | (0 << 11) | (2 << 4),  //A10=1; PRECHARGE ALL="010"
+#ifndef DLL_DISABLE
+   (0x000 << 13) | (1 << 11) | (0 << 4),  //enable DLL; BA="01"; LMR="000"
+#else
+   (0x001 << 13) | (1 << 11) | (0 << 4),  //disable DLL; BA="01"; LMR="000"
+#endif
+   (0x121 << 13) | (0 << 11) | (0 << 4),  //reset DLL, CL=2, BL=2; LMR="000"
+   (0x400 << 13) | (0 << 11) | (2 << 4),  //A10=1; PRECHARGE ALL="010" 
+   (0x000 << 13) | (0 << 11) | (1 << 4),  //AUTO REFRESH="001"
+   (0x000 << 13) | (0 << 11) | (1 << 4),  //AUTO REFRESH="001
+   (0x021 << 13) | (0 << 11) | (0 << 4)   //clear DLL, CL=2, BL=2; LMR="000"
+};
+
+int DdrInit(void)
+{
+   int i, j, k=0;
+   for(i = 0; i < sizeof(DdrInitData)/sizeof(int); ++i)
+   {
+      MemoryWrite(DDR_BASE + DdrInitData[i], 0);
+      for(j = 0; j < 4; ++j)
+         ++k;
+   }
+   for(j = 0; j < 100; ++j)
+      ++k;
+   k += MemoryRead(DDR_BASE);  //Enable DDR
+   return k;
+}
+
+#ifdef DDR_TEST_MAIN
+int main()
+{
+   volatile int *ptr = (int*)DDR_BASE;
+   int i;
+
+   DdrInit();
+
+   ptr[0] = 0x12345678;
+   if(ptr[0] != 0x12345678)
+      putchar('X');
+   for(i = 0; i < 10; ++i)
+   {
+      ptr[i] = i;
+   }
+
+   for(i = 0; i < 10; ++i)
+   {
+      if(ptr[i] != i)
+         putchar('A' + i);
+   }
+   *(unsigned char*)DDR_BASE = 0x23;
+   *(unsigned char*)(DDR_BASE+1) = 0x45;
+   *(unsigned char*)(DDR_BASE+2) = 0x67;
+   *(unsigned char*)(DDR_BASE+3) = 0x89;
+   if(ptr[0] != 0x23456789)
+      putchar('Y');
+   puts("\r\ndone\r\n");
+   return 0;
+}
+#endif
diff --git a/tools/etermip.c b/tools/etermip.c
new file mode 100644 (file)
index 0000000..8120529
--- /dev/null
@@ -0,0 +1,448 @@
+/*--------------------------------------------------------------------
+ * TITLE: etermip
+ * AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
+ * DATE CREATED: 6/13/07
+ * FILENAME: etermip.c
+ * PROJECT: Plasma CPU core
+ * COPYRIGHT: Software placed into the public domain by the author.
+ *    Software 'as is' without warranty.  Author liable for nothing.
+ * DESCRIPTION:
+ *    A terminal program supporting downloading new Plasma applications
+ *    and Ethernet packet transfers.  Based on WinPcap example code.
+ *    Requires WinPcap library at http://www.winpcap.org/.
+ *--------------------------------------------------------------------*/
+#include <windows.h>
+#include <stdio.h>
+#include <conio.h>
+
+//#define SIMULATE_PLASMA
+//#define USE_WPCAP
+#ifdef SIMULATE_PLASMA
+#define USE_WPCAP
+#endif
+
+#ifdef USE_WPCAP
+#if 0
+   #include "pcap.h"
+#else
+   //From "pcap.h"
+   #define PCAP_ERRBUF_SIZE 256
+   typedef struct pcap_if {
+      struct pcap_if *next;
+      char *name;              /* name to hand to "pcap_open_live()" */
+      char *description;       /* textual description of interface, or NULL */
+      struct pcap_addr *addresses;
+      unsigned long flags;     /* PCAP_IF_ interface flags */
+   } pcap_if_t;
+   struct pcap_pkthdr {
+      struct timeval ts;       /* time stamp */
+      unsigned long caplen;    /* length of portion present */
+      unsigned long len;       /* length this packet (off wire) */
+   };
+   typedef struct pcap pcap_t;
+
+   int pcap_findalldevs(pcap_if_t **, char *);
+   void pcap_freealldevs(pcap_if_t *);
+   pcap_t *pcap_open_live(const char *, int, int, int, char *);
+   int pcap_setnonblock(pcap_t *, int, char *);
+   int pcap_sendpacket(pcap_t *, const u_char *, int);
+   const unsigned char *pcap_next(pcap_t *, struct pcap_pkthdr *);
+#endif
+
+//ETHER FIELD                 OFFSET   LENGTH   VALUE
+#define ETHERNET_DEST         0        //6
+#define ETHERNET_SOURCE       6        //6
+#define ETHERNET_FRAME_TYPE   12       //2      IP=0x0800; ARP=0x0806
+#define IP_PROTOCOL           23       //1      TCP=0x06;PING=0x01;UDP=0x11
+#define IP_SOURCE             26       //4
+
+static const unsigned char ethernetAddressNull[] =    {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+static const unsigned char ethernetAddressPhantom[] = {0x00, 0x10, 0xdd, 0xce, 0x15, 0xd4};
+static const unsigned char ethernetAddressPhantom2[] = {0x00, 0x10, 0xdd, 0xce, 0x15, 0xd5};
+
+static pcap_t *adhandle;
+#endif //USE_WPCAP
+
+static HANDLE serial_handle;
+static int PacketBytes, PacketLength, PacketChecksum, Checksum;
+static int ChecksumOk, ChecksumError;
+static unsigned char PacketData[2000];
+static int EthernetActive;
+
+#ifdef SIMULATE_PLASMA
+   extern void *IPFrameGet(int freeCount);
+   extern int IPProcessEthernetPacket(void *frameIn, int length);
+   extern void IPTick(void);
+   extern void IPInit(void (*frameSendFunction)(), unsigned char macAddress[6], char name[6]);
+   extern void HtmlInit(int UseFiles);
+   extern void ConsoleInit(void);
+   static void *ethFrame;
+#endif
+
+
+#ifdef USE_WPCAP
+int WinPcapInit(void)
+{
+       pcap_if_t *alldevs;
+       pcap_if_t *d;
+       int inum;
+       int i=0;
+   int choice = -1;
+       char errbuf[PCAP_ERRBUF_SIZE];
+
+   /* Retrieve the device list */
+       if(pcap_findalldevs(&alldevs, errbuf) == -1)
+       {
+               printf("Error in pcap_findalldevs: %s\n", errbuf);
+               exit(1);
+       }
+       
+       /* Print the list */
+       for(d = alldevs; d; d=d->next)
+       {
+               printf("%d. %s", ++i, d->name);
+               if (d->description)
+                       printf(" (%s)\n", d->description);
+               else
+                       printf(" (No description available)\n");
+      if(strstr(d->description, "eneric") == 0 && strstr(d->description, "Linux") == 0)
+      {
+         if(choice == -1)
+            choice = i;
+         else
+            choice = -2;
+      }
+       }
+       
+       if(i==0)
+       {
+               printf("\nNo interfaces found! Make sure WinPcap is installed.\n");
+               return -1;
+       }
+       
+   if(choice >= 0)
+      inum = choice;
+   else if(i == 1)
+      inum = 1;
+   else
+   {
+          printf("Enter the interface number (1-%d):",i);
+          scanf("%d", &inum);
+   }
+   printf("inum = %d\n", inum);
+       
+       if(inum < 1 || inum > i)
+       {
+               printf("\nInterface number out of range.\n");
+               /* Free the device list */
+               pcap_freealldevs(alldevs);
+               return -1;
+       }
+       
+       /* Jump to the selected adapter */
+       for(d=alldevs, i=0; i< inum-1 ;d=d->next, i++);
+       
+       /* Open the adapter */
+       if ((adhandle = pcap_open_live(d->name, // name of the device
+                                       65536,   // 65536 grants that the whole packet will be captured on all the MACs.
+                                       1,       // promiscuous mode (nonzero means promiscuous)
+                                       10,      // read timeout
+                                       errbuf   // error buffer
+                                       )) == NULL)
+       {
+               printf("\nUnable to open the adapter. %s is not supported by WinPcap\n", d->name);
+               /* Free the device list */
+               pcap_freealldevs(alldevs);
+               return -1;
+       }
+       
+       printf("\nlistening on %s...\n", d->description);
+       
+       /* At this point, we don't need any more the device list. Free it */
+       pcap_freealldevs(alldevs);
+   /* start the capture */
+   pcap_setnonblock(adhandle, 1, errbuf);
+
+   return 0;
+}
+
+
+void EthernetSendPacket(const unsigned char *packet, int length)
+{
+   if(EthernetActive == 0)
+      WinPcapInit();
+   EthernetActive = 1;\r
+   //if((rand() % 8) == 0) return;\r
+   pcap_sendpacket(adhandle, packet, length);
+}
+
+
+/* Callback function invoked by libpcap for every incoming packet */
+void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data)
+{
+#ifndef SIMULATE_PLASMA
+   int i, checksum;
+   unsigned char buf[80];
+   DWORD count;
+#else
+   int rc;
+#endif
+   (void)param;
+
+   if(EthernetActive == 0)
+      return;
+   if(pkt_data[ETHERNET_FRAME_TYPE] != 0x08)
+      return;  //not IP or ARP
+   if(pkt_data[ETHERNET_FRAME_TYPE+1] != 0x00 &&
+      pkt_data[ETHERNET_FRAME_TYPE+1] != 0x06)
+      return;  //not IP or ARP
+   if(memcmp(pkt_data, ethernetAddressNull, 6) &&      //not broadcast address
+      memcmp(pkt_data+ETHERNET_DEST, ethernetAddressPhantom, 6) &&
+      memcmp(pkt_data+ETHERNET_DEST, ethernetAddressPhantom2, 6))
+      return;
+
+#ifndef SIMULATE_PLASMA
+   //Send the ethernet packet over the serial port
+   buf[0] = 0xff;
+   buf[1] = (unsigned char)(header->len >> 8);
+   buf[2] = (unsigned char)header->len;
+   checksum = 0;
+   for(i = 0; i < (int)header->len; ++i)
+      checksum += pkt_data[i];
+   buf[3] = (unsigned char)checksum;
+   WriteFile(serial_handle, buf, 4, &count, NULL);
+   WriteFile(serial_handle, pkt_data, header->len, &count, NULL);
+#else
+   if(ethFrame == NULL)
+      ethFrame = IPFrameGet(0);
+   if(ethFrame == NULL)
+      return;
+   memcpy(ethFrame, pkt_data, header->len);
+   rc = IPProcessEthernetPacket(ethFrame, header->len);
+   if(rc)
+      ethFrame = NULL;
+#endif
+}
+
+
+static void UartPacketRead(int value)
+{
+   if(PacketBytes == 0 && value == 0xff)
+   {
+      ++PacketBytes;
+   }
+   else if(PacketBytes == 1)
+   {
+      ++PacketBytes;
+      PacketLength = value << 8;
+   }
+   else if(PacketBytes == 2)
+   {
+      ++PacketBytes;
+      PacketLength |= value;
+      if(PacketLength > 1000)
+      {
+         PacketBytes = 0;
+         printf("Eterm Length Bad! (%d)\n", PacketLength);
+      }
+   }
+   else if(PacketBytes == 3)
+   {
+      ++PacketBytes;
+      PacketChecksum = value;
+      Checksum = 0;
+   }
+   else if(PacketBytes >= 4)
+   {
+      if(PacketBytes - 4 < sizeof(PacketData))
+         PacketData[PacketBytes - 4] = (unsigned char)value;
+      Checksum += value;
+      ++PacketBytes;
+      if(PacketBytes - 4 >= PacketLength)
+      {
+         if((unsigned char)Checksum == PacketChecksum)
+         {
+            ++ChecksumOk;
+            EthernetSendPacket(PacketData, PacketLength);
+         }
+         else
+         {
+            ++ChecksumError;
+            //printf("ChecksumError(%d %d)!\n", ChecksumOk, ChecksumError);
+         }
+         PacketBytes = 0;
+      }
+   }
+}
+#endif //USE_WPCAP
+
+/**************************************************************/
+
+long SerialOpen(char *name, long baud)
+{
+   DCB dcb;
+   COMMTIMEOUTS comm_timeouts;
+   BOOL rc;
+   serial_handle = CreateFile(name, GENERIC_READ|GENERIC_WRITE,
+      0, NULL, OPEN_EXISTING, 0, NULL);
+   if(serial_handle == INVALID_HANDLE_VALUE) 
+      printf("Serial Port In Use!\n");
+   rc = SetupComm(serial_handle, 16000, 16000);
+   if(rc == FALSE) 
+      printf("Serial port already in use!!!\n");
+   rc = GetCommState(serial_handle, &dcb);
+   if(rc == FALSE) 
+      printf("ERROR2\n");
+   dcb.BaudRate = baud;
+   dcb.fBinary = 1;
+   dcb.fParity = 0;
+   dcb.ByteSize = 8;
+   dcb.StopBits = 0; //ONESTOPBIT;
+   dcb.fOutX = 0;
+   dcb.fInX = 0;
+   dcb.fNull = 0;
+   dcb.Parity = 0;
+   dcb.fOutxCtsFlow = 0;
+   dcb.fOutxDsrFlow = 0;
+   dcb.fOutX = 0;
+   dcb.fInX = 0;
+   dcb.fRtsControl = 0;
+   dcb.fDsrSensitivity = 0;
+   rc = SetCommState(serial_handle, &dcb);
+   if(rc == FALSE) 
+      printf("ERROR3\n");
+   rc = GetCommTimeouts(serial_handle, &comm_timeouts);
+   if(rc == FALSE) 
+      printf("ERROR4\n");
+   comm_timeouts.ReadIntervalTimeout = MAXDWORD;  //non-blocking read
+   comm_timeouts.ReadTotalTimeoutMultiplier = 0;
+   comm_timeouts.ReadTotalTimeoutConstant = 0;
+   comm_timeouts.WriteTotalTimeoutMultiplier = 0;  //blocking write
+   comm_timeouts.WriteTotalTimeoutConstant = 0;
+   rc = SetCommTimeouts(serial_handle, &comm_timeouts);
+   if(rc == FALSE) 
+      printf("ERROR5\n");
+   return(0);
+}
+
+
+long SerialRead(unsigned char *data, unsigned long length)
+{
+   DWORD count, bytes;
+   unsigned char buf[8];
+
+   count = 0;
+   for(;;)
+   {
+      ReadFile(serial_handle, buf, 1, &bytes, NULL);
+      if(bytes == 0)
+         break;
+#ifdef USE_WPCAP
+      if(buf[0] == 0xff || PacketBytes)
+         UartPacketRead(buf[0]);
+      else
+#endif
+         data[count++] = buf[0];
+      if(count >= length)
+         break;
+   }
+   return count;
+}
+
+//****************************************************
+
+#define BUF_SIZE 1024*1024
+void SendFile(void)
+{
+   FILE *in;
+   unsigned char *buf;
+   long length;
+   DWORD count;
+
+   in=fopen("test.bin", "rb");
+   if(in==NULL) {
+      printf("Can't find test.bin\n");
+      return;
+   }
+   buf = (unsigned char*)malloc(BUF_SIZE);
+   memset(buf, 0, BUF_SIZE);
+   length = (int)fread(buf, 1, BUF_SIZE, in);
+   fclose(in);
+   printf("Sending test.bin (length=%d bytes) to target...\n", length);
+   WriteFile(serial_handle, buf, length, &count, NULL);
+   printf("Done downloading\n");
+   free(buf);
+}
+
+
+int main(int argc, char *argv[])
+{
+   unsigned int ticksLast = GetTickCount();
+   int length;
+   unsigned char buf[80];
+   DWORD count;
+   unsigned int ticks;
+   int downloadSkip = 0;
+   (void)argc;
+   (void)argv;
+
+   //WinPcapInit();
+#ifndef SIMULATE_PLASMA
+   SerialOpen("COM1", 57600);
+   if(argc != 2 || strcmp(argv[1], "none"))
+      SendFile();
+   else
+      downloadSkip = 1;
+#else
+   IPInit(EthernetSendPacket, NULL, NULL);
+   HtmlInit(1);
+   ConsoleInit();
+#endif
+
+   for(;;)
+   {
+      // Read keypresses
+      while(kbhit())
+      {
+         buf[0] = (unsigned char)getch();
+         if(downloadSkip && buf[0] == '`')
+            SendFile();
+         WriteFile(serial_handle, buf, 1, &count, NULL);
+      }
+
+      // Read UART
+      for(;;)
+      {
+         length = SerialRead(buf, sizeof(buf));
+         if(length == 0)
+            break;
+         buf[length] = 0;
+         printf("%s", buf);
+      }
+
+#ifdef USE_WPCAP
+      // Read Ethernet
+      while(EthernetActive)
+      {
+         struct pcap_pkthdr header;
+         const u_char *pkt_data;
+         pkt_data = pcap_next(adhandle, &header);
+         if(pkt_data == NULL)
+            break;
+         if(EthernetActive)
+            packet_handler(NULL, &header, pkt_data);
+      }
+#endif
+      Sleep(10);
+      ticks = GetTickCount();
+      if(ticks - ticksLast > 1000)
+      {
+#ifdef SIMULATE_PLASMA
+         IPTick();
+#endif
+         ticksLast = ticks;
+      }
+   }
+}
+
diff --git a/tools/makefile b/tools/makefile
new file mode 100644 (file)
index 0000000..73c140a
--- /dev/null
@@ -0,0 +1,284 @@
+# The CC_X86 is for compiling tools on your PC.\r
+# The GCC_MIPS is for compiling code on the target.\r
+# Convert_bin changes test.axf into code.txt which is used by the VHDL.\r
+# Convert_bin == "objcopy -I elf32-big -O binary test.axf test.bin"\r
+\r
+\r
+ifeq ($(LANG),)\r
+\r
+# Customize for Windows\r
+# The MIPS gcc compiler must use the cygwin1.dll that came with the compiler.\r
+CC_X86 = cl /O1 /nologo\r
+CP = copy\r
+RM = del\r
+DWIN32 = -DWIN32\r
+BIN_MIPS = ..\gccmips_elf\r
+VHDL_DIR = ..\vhdl\r
+LINUX_PWD =\r
+GCC_MIPS  = $(BIN_MIPS)\gcc $(CFLAGS)\r
+AS_MIPS   = $(BIN_MIPS)\as\r
+LD_MIPS   = $(BIN_MIPS)\ld\r
+DUMP_MIPS = $(BIN_MIPS)\objdump\r
+CONVERT_BIN = $(LINUX_PWD)convert_bin.exe\r
+\r
+else\r
+\r
+# Customized for Linux\r
+# See http://www.opencores.com/projects.cgi/web/mips/linux_tools.htm\r
+CC_X86 = gcc -Wall -O -g\r
+CP = cp\r
+RM = rm -rf \r
+DWIN32 =\r
+BIN_MIPS = \r
+VHDL_DIR = ../vhdl\r
+LINUX_PWD = ./\r
+GCC_MIPS  = $(BIN_MIPS)mips-elf-gcc $(CFLAGS)\r
+AS_MIPS   = $(BIN_MIPS)mips-elf-as\r
+LD_MIPS   = $(BIN_MIPS)mips-elf-ld\r
+DUMP_MIPS = $(BIN_MIPS)mips-elf-objdump\r
+CONVERT_BIN = $(LINUX_PWD)convert_bin.exe\r
+#CONVERT_BIN = $(BIN_MIPS)mips-elf-objcopy -I elf32-big -O binary test.axf test.bin\r
+\r
+endif\r
+\r
+CFLAGS = -O2 -Wall -c -s \r
+\r
+all: convert_bin.exe tracehex.exe bintohex.exe ram_image.exe\r
+       @echo make targets = count, opcodes, pi, test, run, tohex,\\r
+       bootldr, toimage, eterm\r
+       \r
+clean:\r
+       -$(RM) *.o *.obj *.map *.lst *.hex *.txt *.exe *.axf\r
+\r
+#Same as "objcopy -I elf32-big -O binary test.axf test.bin"\r
+convert_bin.exe: convert.c\r
+       @$(CC_X86) -o convert_bin.exe convert.c\r
+\r
+convert_le.exe: convert.c\r
+       @$(CC_X86) -DLITTLE_ENDIAN -o convert_le.exe convert.c\r
+\r
+mlite.exe: mlite.c\r
+       @$(CC_X86) -o mlite.exe mlite.c $(DWIN32)\r
+\r
+tracehex.exe: tracehex.c\r
+       @$(CC_X86) -o tracehex.exe tracehex.c\r
+\r
+bintohex.exe: bintohex.c\r
+       @$(CC_X86) -o bintohex.exe bintohex.c\r
+\r
+ram_image.exe: ram_image.c\r
+       @$(CC_X86) -o ram_image.exe ram_image.c\r
+\r
+# Terminal program that will download a new image.\r
+# For Linux, use any serial port program at 57600 baud 8-bits;1-stop bit\r
+# This mode does not support Ethernet packet transfers.\r
+eterm: etermip.c\r
+       -@$(CC_X86) -o etermip.exe etermip.c\r
+\r
+# Terminal program that will download a new image and supports Ethernet\r
+# traffic over UART.  Get wpcap.lib from http://www.winpcap.org/.\r
+# Requires Windows OS\r
+# Uses wpcap.lib for receiving and transmitting raw Ethernet packets\r
+# Get wpcap.lib from http://www.winpcap.org/.\r
+etermip: etermip.c\r
+       @echo Get wpcap.lib from http://www.winpcap.org/\r
+       -@$(CC_X86) -DUSE_WPCAP -o etermip.exe etermip.c wpcap.lib\r
+\r
+nomult.exe: nomult.c\r
+       -@$(CC_X86) -o nomult.exe nomult.c\r
+\r
+download: etermip\r
+       @echo Reset board before downloading code\r
+       etermip\r
+\r
+opcodes: \r
+       $(AS_MIPS) -o opcodes.o opcodes.asm\r
+       $(LD_MIPS) -Ttext 0 -eentry -Map test.map -s -N -o test.axf opcodes.o\r
+       -@$(DUMP_MIPS) --disassemble test.axf > test.lst\r
+       $(CONVERT_BIN)\r
+       $(CP) code.txt $(VHDL_DIR)\r
+\r
+opcodes2: \r
+       $(AS_MIPS) -o opcodes.o opcodes.asm\r
+       $(LD_MIPS) -Ttext 0x10000000 -eentry -Map test.map -s -N -o test.axf opcodes.o\r
+       -@$(DUMP_MIPS) --disassemble test.axf > test.lst\r
+       $(CONVERT_BIN)\r
+       $(CP) code.txt $(VHDL_DIR)\r
+\r
+test: \r
+       $(AS_MIPS) -o boot.o boot.asm\r
+       $(GCC_MIPS) test.c\r
+       $(GCC_MIPS) no_os.c\r
+       $(LD_MIPS) -Ttext 0 -eentry -Map test.map -s -N -o test.axf \\r
+               boot.o test.o no_os.o\r
+       -@$(DUMP_MIPS) --disassemble test.axf > test.lst\r
+       $(CONVERT_BIN)\r
+       $(CP) code.txt $(VHDL_DIR)\r
+\r
+count: \r
+       $(AS_MIPS) -o boot.o boot.asm\r
+       $(GCC_MIPS) count.c\r
+       $(GCC_MIPS) no_os.c \r
+       $(LD_MIPS) -Ttext 0 -eentry -Map test.map -s -N -o test.axf \\r
+               boot.o count.o no_os.o \r
+       -$(DUMP_MIPS) --disassemble test.axf > test.lst\r
+       $(CONVERT_BIN)\r
+       $(CP) code.txt $(VHDL_DIR)\r
+\r
+count_le: \r
+       $(AS_MIPS) -EL -o boot.o boot.asm\r
+       $(GCC_MIPS) -EL count.c\r
+       $(GCC_MIPS) -EL no_os.c \r
+       $(LD_MIPS) -EL -Ttext 0 -eentry -Map test.map -s -N -o test.axf \\r
+               boot.o count.o no_os.o \r
+       -$(DUMP_MIPS) --disassemble test.axf > test.lst\r
+       $(CONVERT_BIN)\r
+       $(CP) code.txt $(VHDL_DIR)\r
+\r
+count2:\r
+       $(AS_MIPS) -o boot.o boot.asm\r
+       $(GCC_MIPS) count.c\r
+       $(GCC_MIPS) no_os.c\r
+       $(LD_MIPS) -Ttext 0x10000000 -eentry -Map test.map -s -N -o test.axf \\r
+               boot.o count.o no_os.o\r
+       -$(DUMP_MIPS) --disassemble test.axf > test.lst\r
+       $(CONVERT_BIN)\r
+       $(CP) code.txt $(VHDL_DIR)\r
+\r
+count3:\r
+       $(AS_MIPS) -o boot.o boot.asm\r
+       $(GCC_MIPS) count.c\r
+       $(GCC_MIPS) no_os.c\r
+       $(LD_MIPS) -Ttext 0x2000 -eentry -Map test.map -s -N -o test.axf \\r
+               boot.o count.o no_os.o\r
+       -$(DUMP_MIPS) --disassemble test.axf > test.lst\r
+       $(CONVERT_BIN)\r
+       $(CP) code.txt $(VHDL_DIR)\r
+\r
+count5: nomult.exe\r
+       $(AS_MIPS) -o boot.o boot.asm\r
+       $(AS_MIPS) -o mult_sim.o mult_sim.asm\r
+       $(GCC_MIPS) count.c\r
+       $(GCC_MIPS) no_os.c\r
+       $(LD_MIPS) -Ttext 0x10000000 -eentry -Map test.map -s -N -o test.axf \\r
+               boot.o mult_sim.o count.o no_os.o\r
+       -$(DUMP_MIPS) --disassemble test.axf > test.lst\r
+       $(CP) test.axf test_old.axf\r
+       nomult test.axf test.lst test.map\r
+       -$(DUMP_MIPS) --disassemble test.axf > test2.lst\r
+       $(CONVERT_BIN)\r
+       $(CP) code.txt $(VHDL_DIR)\r
+\r
+pi: \r
+       $(AS_MIPS) -o boot.o boot.asm\r
+       $(GCC_MIPS) pi.c\r
+       $(LD_MIPS) -Ttext 0 -eentry -Map test.map -s -N -o test.axf \\r
+               boot.o pi.o \r
+       @$(DUMP_MIPS) --disassemble test.axf > test.lst\r
+       $(CONVERT_BIN)\r
+       $(CP) code.txt $(VHDL_DIR)\r
+\r
+pi2:\r
+       $(AS_MIPS) -o boot.o boot.asm\r
+       $(GCC_MIPS) pi.c\r
+       $(LD_MIPS) -Ttext 0x10000000 -eentry -Map test.map -s -N -o test.axf \\r
+               boot.o pi.o \r
+       @$(DUMP_MIPS) --disassemble test.axf > test.lst\r
+       $(CONVERT_BIN)\r
+       $(CP) code.txt $(VHDL_DIR)\r
+\r
+pi5: nomult.exe\r
+       $(AS_MIPS) -o boot.o boot.asm\r
+       $(AS_MIPS) -o mult_sim.o mult_sim.asm\r
+       $(GCC_MIPS) pi.c\r
+       $(LD_MIPS) -Ttext 0x0 -eentry -Map test.map -s -N -o test.axf \\r
+               boot.o mult_sim.o pi.o \r
+       @$(DUMP_MIPS) --disassemble test.axf > test.lst\r
+       nomult test.axf test.lst test.map\r
+       @$(DUMP_MIPS) --disassemble test.axf > test2.lst\r
+       $(CONVERT_BIN)\r
+       $(CP) code.txt $(VHDL_DIR)\r
+\r
+ddr_test:\r
+       $(AS_MIPS) -o boot.o boot.asm\r
+       $(GCC_MIPS) ddr_init.c -DDDR_TEST_MAIN\r
+       $(GCC_MIPS) no_os.c\r
+       $(LD_MIPS) -Ttext 0x0 -eentry -Map test.map -s -N -o test.axf \\r
+               boot.o ddr_init.o no_os.o\r
+       @$(DUMP_MIPS) --disassemble test.axf > test.lst\r
+       $(CONVERT_BIN)\r
+       $(CP) code.txt $(VHDL_DIR)\r
+\r
+memtest:\r
+       $(AS_MIPS) -o boot.o boot.asm\r
+       $(GCC_MIPS) memtest.c\r
+       $(LD_MIPS) -Ttext 0x2000 -eentry -o test.axf boot.o memtest.o\r
+       $(CONVERT_BIN)\r
+       \r
+memtest2:\r
+       $(AS_MIPS) -o boot.o boot.asm\r
+       $(GCC_MIPS) -DINIT_DDR memtest.c\r
+       $(GCC_MIPS) ddr_init.c\r
+       $(LD_MIPS) -Ttext 0x0 -eentry -o test.axf boot.o memtest.o ddr_init.o\r
+       $(CONVERT_BIN)\r
+\r
+memtest3:\r
+       $(AS_MIPS) -o boot.o boot.asm\r
+       $(GCC_MIPS) memtest.c\r
+       $(LD_MIPS) -Ttext 0x10000000 -eentry -o test.axf boot.o memtest.o\r
+       $(CONVERT_BIN)\r
+\r
+bootldr:\r
+       $(AS_MIPS) -o boot.o boot.asm\r
+       $(GCC_MIPS) bootldr.c\r
+       $(GCC_MIPS) no_os.c\r
+       $(GCC_MIPS) -DDLL_DISABLE ddr_init.c\r
+       $(LD_MIPS) -Ttext 0 -eentry -Map test.map -s -N -o test.axf \\r
+               boot.o bootldr.o no_os.o ddr_init.o\r
+       @$(DUMP_MIPS) --disassemble test.axf > test.lst\r
+       $(CONVERT_BIN)\r
+       $(CP) code.txt $(VHDL_DIR)\r
+       @echo Next do "make toimage" for Xilinx or "make tohex" for Altera.\r
+\r
+bootldr2:\r
+       $(AS_MIPS) -o boot.o boot.asm\r
+       $(GCC_MIPS) bootldr.c\r
+       $(GCC_MIPS) no_os.c\r
+       $(GCC_MIPS) -DDLL_DISABLE ddr_init.c\r
+       $(LD_MIPS) -Ttext 0x1000 -eentry -Map test.map -s -N -o test.axf \\r
+               boot.o bootldr.o no_os.o ddr_init.o\r
+       @$(DUMP_MIPS) --disassemble test.axf > test.lst\r
+       $(CONVERT_BIN)\r
+       $(CP) code.txt $(VHDL_DIR)\r
+\r
+bootldr_little_endian: convert_le.exe\r
+       $(AS_MIPS) -EL -o boot.o boot.asm\r
+       $(GCC_MIPS) -EL bootldr.c\r
+       $(GCC_MIPS) -EL no_os.c\r
+       $(GCC_MIPS) -EL ddr_init.c\r
+       $(LD_MIPS) -EL -Ttext 0 -eentry -Map test.map -s -N -o test.axf \\r
+               boot.o bootldr.o no_os.o ddr_init.o\r
+       @$(DUMP_MIPS) --disassemble test.axf > test.lst\r
+       $(LINUX_PWD)convert_le.exe\r
+       $(CP) code.txt $(VHDL_DIR)\r
+\r
+# Run a MIPS opcode simulator\r
+run: mlite.exe\r
+       @$(LINUX_PWD)mlite.exe test.bin \r
+\r
+run_little_endian: mlite.exe\r
+       @$(LINUX_PWD)mlite.exe test.bin L\r
+\r
+disassemble: mlite.exe\r
+       $(LINUX_PWD)mlite.exe test.bin BD > test.txt\r
+\r
+# Used by Altera FPGAs for ram image\r
+tohex: bintohex.exe\r
+       $(LINUX_PWD)bintohex.exe test.bin\r
+       $(CP) code*.hex $(VHDL_DIR)\r
+\r
+# Used by Xilinx FPGAs for ram image\r
+toimage:\r
+       $(LINUX_PWD)ram_image.exe ../vhdl/ram_xilinx.vhd ../vhdl/code.txt ../vhdl/ram_image.vhd\r
+\r
+\r
diff --git a/tools/mlite.c b/tools/mlite.c
new file mode 100644 (file)
index 0000000..34d4d11
--- /dev/null
@@ -0,0 +1,999 @@
+/*-------------------------------------------------------------------
+-- TITLE: Plasma CPU in software.  Executes MIPS(tm) opcodes.
+-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
+-- DATE CREATED: 1/31/01
+-- FILENAME: mlite.c
+-- PROJECT: Plasma CPU core
+-- COPYRIGHT: Software placed into the public domain by the author.
+--    Software 'as is' without warranty.  Author liable for nothing.
+-- DESCRIPTION:
+--   Plasma CPU simulator in C code.  
+--   This file served as the starting point for the VHDL code.
+--   Assumes running on a little endian PC.
+--------------------------------------------------------------------*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+
+//#define ENABLE_CACHE
+#define SIMPLE_CACHE
+
+#define MEM_SIZE (1024*1024*2)
+#define ntohs(A) ( ((A)>>8) | (((A)&0xff)<<8) )
+#define htons(A) ntohs(A)
+#define ntohl(A) ( ((A)>>24) | (((A)&0xff0000)>>8) | (((A)&0xff00)<<8) | ((A)<<24) )
+#define htonl(A) ntohl(A)
+
+#ifndef WIN32
+//Support for Linux
+#define putch putchar
+#include <termios.h>
+#include <unistd.h>
+
+void Sleep(unsigned int value)
+{ 
+   usleep(value * 1000);
+}
+
+int kbhit(void)
+{
+   struct termios oldt, newt;
+   struct timeval tv;
+   fd_set read_fd;
+
+   tcgetattr(STDIN_FILENO, &oldt);
+   newt = oldt;
+   newt.c_lflag &= ~(ICANON | ECHO);
+   tcsetattr(STDIN_FILENO, TCSANOW, &newt);
+   tv.tv_sec=0;
+   tv.tv_usec=0;
+   FD_ZERO(&read_fd);
+   FD_SET(0,&read_fd);
+   if(select(1, &read_fd, NULL, NULL, &tv) == -1)
+      return 0;
+   //tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
+   if(FD_ISSET(0,&read_fd))
+      return 1;
+   return 0;
+}
+
+int getch(void)
+{
+   struct termios oldt, newt;
+   int ch;
+
+   tcgetattr(STDIN_FILENO, &oldt);
+   newt = oldt;
+   newt.c_lflag &= ~(ICANON | ECHO);
+   tcsetattr(STDIN_FILENO, TCSANOW, &newt);
+   ch = getchar();
+   //tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
+   return ch;
+}
+#else
+//Support for Windows
+#include <conio.h>
+extern void __stdcall Sleep(unsigned long value);
+#endif
+
+#define UART_WRITE        0x20000000
+#define UART_READ         0x20000000
+#define IRQ_MASK          0x20000010
+#define IRQ_STATUS        0x20000020
+#define CONFIG_REG        0x20000070
+#define MMU_PROCESS_ID    0x20000080
+#define MMU_FAULT_ADDR    0x20000090
+#define MMU_TLB           0x200000a0
+
+#define IRQ_UART_READ_AVAILABLE  0x001
+#define IRQ_UART_WRITE_AVAILABLE 0x002
+#define IRQ_COUNTER18_NOT        0x004
+#define IRQ_COUNTER18            0x008
+#define IRQ_MMU                  0x200
+
+#define MMU_ENTRIES 4
+#define MMU_MASK (1024*4-1)
+
+typedef struct
+{
+   unsigned int virtualAddress;
+   unsigned int physicalAddress;
+} MmuEntry;
+
+typedef struct {
+   int r[32];
+   int pc, pc_next, epc;
+   unsigned int hi;
+   unsigned int lo;
+   int status;
+   int userMode;
+   int processId;
+   int exceptionId;
+   int faultAddr;
+   int irqStatus;
+   int skip;
+   unsigned char *mem;
+   int wakeup;
+   int big_endian;
+   MmuEntry mmuEntry[MMU_ENTRIES];
+} State;
+
+static char *opcode_string[]={
+   "SPECIAL","REGIMM","J","JAL","BEQ","BNE","BLEZ","BGTZ",
+   "ADDI","ADDIU","SLTI","SLTIU","ANDI","ORI","XORI","LUI",
+   "COP0","COP1","COP2","COP3","BEQL","BNEL","BLEZL","BGTZL",
+   "?","?","?","?","?","?","?","?",
+   "LB","LH","LWL","LW","LBU","LHU","LWR","?",
+   "SB","SH","SWL","SW","?","?","SWR","CACHE",
+   "LL","LWC1","LWC2","LWC3","?","LDC1","LDC2","LDC3"
+   "SC","SWC1","SWC2","SWC3","?","SDC1","SDC2","SDC3"
+};
+
+static char *special_string[]={
+   "SLL","?","SRL","SRA","SLLV","?","SRLV","SRAV",
+   "JR","JALR","MOVZ","MOVN","SYSCALL","BREAK","?","SYNC",
+   "MFHI","MTHI","MFLO","MTLO","?","?","?","?",
+   "MULT","MULTU","DIV","DIVU","?","?","?","?",
+   "ADD","ADDU","SUB","SUBU","AND","OR","XOR","NOR",
+   "?","?","SLT","SLTU","?","DADDU","?","?",
+   "TGE","TGEU","TLT","TLTU","TEQ","?","TNE","?",
+   "?","?","?","?","?","?","?","?"
+};
+
+static char *regimm_string[]={
+   "BLTZ","BGEZ","BLTZL","BGEZL","?","?","?","?",
+   "TGEI","TGEIU","TLTI","TLTIU","TEQI","?","TNEI","?",
+   "BLTZAL","BEQZAL","BLTZALL","BGEZALL","?","?","?","?",
+   "?","?","?","?","?","?","?","?"
+};
+
+static unsigned int HWMemory[8];
+
+
+static int mem_read(State *s, int size, unsigned int address)
+{
+   unsigned int value=0, ptr;
+
+   s->irqStatus |= IRQ_UART_WRITE_AVAILABLE;
+   switch(address)
+   {
+      case UART_READ: 
+         if(kbhit())
+            HWMemory[0] = getch();
+         s->irqStatus &= ~IRQ_UART_READ_AVAILABLE; //clear bit
+         return HWMemory[0];
+      case IRQ_MASK: 
+         return HWMemory[1];
+      case IRQ_MASK + 4:
+         Sleep(10);
+         return 0;
+      case IRQ_STATUS: 
+         if(kbhit())
+            s->irqStatus |= IRQ_UART_READ_AVAILABLE;
+         return s->irqStatus;
+      case MMU_PROCESS_ID:
+         return s->processId;
+      case MMU_FAULT_ADDR:
+         return s->faultAddr;
+   }
+
+   ptr = (unsigned int)s->mem + (address % MEM_SIZE);
+
+   if(0x10000000 <= address && address < 0x10000000 + 1024*1024)
+      ptr += 1024*1024;
+
+   switch(size) 
+   {
+      case 4: 
+         if(address & 3)
+            printf("Unaligned access PC=0x%x address=0x%x\n", (int)s->pc, (int)address);
+         assert((address & 3) == 0);
+         value = *(int*)ptr;
+         if(s->big_endian) 
+            value = ntohl(value);
+         break;
+      case 2:
+         assert((address & 1) == 0);
+         value = *(unsigned short*)ptr;
+         if(s->big_endian) 
+            value = ntohs((unsigned short)value);
+         break;
+      case 1:
+         value = *(unsigned char*)ptr;
+         break;
+      default: 
+         printf("ERROR");
+   }
+   return(value);
+}
+
+static void mem_write(State *s, int size, int unsigned address, unsigned int value)
+{
+   unsigned int ptr;
+
+   switch(address)
+   {
+      case UART_WRITE: 
+         putch(value); 
+         fflush(stdout);
+         return;
+      case IRQ_MASK:   
+         HWMemory[1] = value; 
+         return;
+      case IRQ_STATUS: 
+         s->irqStatus = value; 
+         return;
+      case CONFIG_REG:
+         return;
+      case MMU_PROCESS_ID:
+         //printf("processId=%d\n", value);
+         s->processId = value;
+         return;
+   }
+
+   if(MMU_TLB <= address && address <= MMU_TLB+MMU_ENTRIES * 8)
+   {
+      //printf("TLB 0x%x 0x%x\n", address - MMU_TLB, value);
+      ptr = (unsigned int)s->mmuEntry + address - MMU_TLB;
+      *(int*)ptr = value;
+      s->irqStatus &= ~IRQ_MMU;
+      return;
+   }
+
+   ptr = (unsigned int)s->mem + (address % MEM_SIZE);
+
+   if(0x10000000 <= address && address < 0x10000000 + 1024*1024)
+      ptr += 1024*1024;
+
+   switch(size) 
+   {
+      case 4: 
+         assert((address & 3) == 0);
+         if(s->big_endian) 
+            value = htonl(value);
+         *(int*)ptr = value;
+         break;
+      case 2:
+         assert((address & 1) == 0);
+         if(s->big_endian) 
+            value = htons((unsigned short)value);
+         *(short*)ptr = (unsigned short)value; 
+         break;
+      case 1:
+         *(char*)ptr = (unsigned char)value; 
+         break;
+      default: 
+         printf("ERROR");
+   }
+}
+
+#ifdef ENABLE_CACHE
+/************* Optional MMU and cache implementation *************/
+/* TAG = VirtualAddress | ProcessId | WriteableBit */
+unsigned int mmu_lookup(State *s, unsigned int processId, 
+                         unsigned int address, int write)
+{
+   int i;
+   unsigned int compare, tag;
+
+   if(processId == 0 || s->userMode == 0)
+      return address;
+   //if(address < 0x30000000)
+   //   return address;
+   compare = (address & ~MMU_MASK) | (processId << 1);
+   for(i = 0; i < MMU_ENTRIES; ++i)
+   {
+      tag = s->mmuEntry[i].virtualAddress;
+      if((tag & ~1) == compare && (write == 0 || (tag & 1)))
+         return s->mmuEntry[i].physicalAddress | (address & MMU_MASK);
+   }
+   //printf("\nMMUTlbMiss 0x%x PC=0x%x w=%d pid=%d user=%d\n", 
+   //   address, s->pc, write, processId, s->userMode);
+   //printf("m");
+   s->exceptionId = 1;
+   s->faultAddr = address & ~MMU_MASK;
+   s->irqStatus |= IRQ_MMU;
+   return address;
+}
+
+
+#define CACHE_SET_ASSOC_LN2   0
+#define CACHE_SET_ASSOC       (1 << CACHE_SET_ASSOC_LN2)
+#define CACHE_SIZE_LN2        (13 - CACHE_SET_ASSOC_LN2)  //8 KB
+#define CACHE_SIZE            (1 << CACHE_SIZE_LN2)
+#define CACHE_LINE_SIZE_LN2   2                           //4 bytes
+#define CACHE_LINE_SIZE       (1 << CACHE_LINE_SIZE_LN2)
+
+static int cacheData[CACHE_SET_ASSOC][CACHE_SIZE/sizeof(int)];
+static int cacheAddr[CACHE_SET_ASSOC][CACHE_SIZE/CACHE_LINE_SIZE];
+static int cacheSetNext;
+static int cacheMiss, cacheWriteBack, cacheCount;
+
+static void cache_init(void)
+{
+   int set, i;
+   for(set = 0; set < CACHE_SET_ASSOC; ++set)
+   {
+      for(i = 0; i < CACHE_SIZE/CACHE_LINE_SIZE; ++i)
+         cacheAddr[set][i] = 0xffff0000;
+   }
+}
+
+/* Write-back cache memory tagged by virtual address and processId */
+/* TAG = virtualAddress | processId | dirtyBit */
+static int cache_load(State *s, unsigned int address, int write)
+{
+   int set, i, pid, miss, offsetAddr, offsetData, offsetMem;
+   unsigned int addrTagMatch, addrPrevMatch=0;
+   unsigned int addrPrev;
+   unsigned int addressPhysical, tag;
+
+   ++cacheCount;
+   addrTagMatch = address & ~(CACHE_SIZE-1);
+   offsetAddr = (address & (CACHE_SIZE-1)) >> CACHE_LINE_SIZE_LN2;
+
+   /* Find match */
+   miss = 1;
+   for(set = 0; set < CACHE_SET_ASSOC; ++set)
+   {
+      addrPrevMatch = cacheAddr[set][offsetAddr] & ~(CACHE_SIZE-1);
+      if(addrPrevMatch == addrTagMatch)
+      {
+         miss = 0;
+         break;
+      }
+   }
+
+   /* Cache miss? */
+   if(miss)
+   {
+      ++cacheMiss;
+      set = cacheSetNext;
+      cacheSetNext = (cacheSetNext + 1) & (CACHE_SET_ASSOC-1);
+   }
+   //else if(write || (address >> 28) != 0x1)
+   //{
+   //   tag = cacheAddr[set][offsetAddr];
+   //   pid = (tag & (CACHE_SIZE-1)) >> 1; 
+   //   if(pid != s->processId)
+   //      miss = 1;
+   //}
+
+   if(miss)
+   {
+      offsetData = address & (CACHE_SIZE-1) & ~(CACHE_LINE_SIZE-1);
+
+      /* Cache line dirty? */
+      if(cacheAddr[set][offsetAddr] & 1)
+      {
+         /* Write back cache line */
+         tag = cacheAddr[set][offsetAddr];
+         addrPrev = tag & ~(CACHE_SIZE-1);
+         addrPrev |= address & (CACHE_SIZE-1);
+         pid = (tag & (CACHE_SIZE-1)) >> 1; 
+         addressPhysical = mmu_lookup(s, pid, addrPrev, 1);   //virtual->physical
+         if(s->exceptionId)
+            return 0;
+         offsetMem = addressPhysical & ~(CACHE_LINE_SIZE-1);
+         for(i = 0; i < CACHE_LINE_SIZE; i += 4)
+            mem_write(s, 4, offsetMem + i, cacheData[set][(offsetData + i) >> 2]);
+         ++cacheWriteBack;
+      }
+
+      /* Read cache line */
+      addressPhysical = mmu_lookup(s, s->processId, address, write); //virtual->physical
+      if(s->exceptionId)
+         return 0;
+      offsetMem = addressPhysical & ~(CACHE_LINE_SIZE-1);
+      cacheAddr[set][offsetAddr] = addrTagMatch;
+      for(i = 0; i < CACHE_LINE_SIZE; i += 4)
+         cacheData[set][(offsetData + i) >> 2] = mem_read(s, 4, offsetMem + i);
+   }
+   cacheAddr[set][offsetAddr] |= write;
+   return set;
+}
+
+static int cache_read(State *s, int size, unsigned int address)
+{
+   int set, offset;
+   int value;
+
+   if((address & 0xfe000000) != 0x10000000)
+      return mem_read(s, size, address);
+
+   set = cache_load(s, address, 0);
+   if(s->exceptionId)
+      return 0;
+   offset = (address & (CACHE_SIZE-1)) >> 2;
+   value = cacheData[set][offset];
+   if(s->big_endian)
+      address ^= 3;
+   switch(size) 
+   {
+      case 2: 
+         value = (value >> ((address & 2) << 3)) & 0xffff;
+         break;
+      case 1:
+         value = (value >> ((address & 3) << 3)) & 0xff;
+         break;
+   }
+   return value;
+}
+
+static void cache_write(State *s, int size, int unsigned address, unsigned int value)
+{
+   int set, offset;
+   unsigned int mask;
+
+   if((address >> 28) != 0x1) // && (s->processId == 0 || s->userMode == 0))
+   {
+      mem_write(s, size, address, value);
+      return;
+   }
+
+   set = cache_load(s, address, 1);
+   if(s->exceptionId)
+      return;
+   offset = (address & (CACHE_SIZE-1)) >> 2;
+   if(s->big_endian)
+      address ^= 3;
+   switch(size) 
+   {
+      case 2:
+         value &= 0xffff;
+         value |= value << 16;
+         mask = 0xffff << ((address & 2) << 3);
+         break;
+      case 1:
+         value &= 0xff;
+         value |= (value << 8) | (value << 16) | (value << 24);
+         mask = 0xff << ((address & 3) << 3);
+         break;
+      case 4:
+      default:
+         mask = 0xffffffff;
+         break;
+   }
+   cacheData[set][offset] = (value & mask) | (cacheData[set][offset] & ~mask);
+}
+
+#define mem_read cache_read
+#define mem_write cache_write
+
+#else
+static void cache_init(void) {}
+#endif
+
+
+#ifdef SIMPLE_CACHE
+
+//Write through direct mapped 4KB cache
+#define CACHE_MISS 0x1ff
+static unsigned int cacheData[1024];
+static unsigned int cacheAddr[1024]; //9-bit addresses
+static int cacheTry, cacheMiss, cacheInit;
+
+static int cache_read(State *s, int size, unsigned int address)
+{
+   int offset;
+   unsigned int value, value2, address2=address;
+
+   if(cacheInit == 0)
+   {
+      cacheInit = 1;
+      for(offset = 0; offset < 1024; ++offset)
+         cacheAddr[offset] = CACHE_MISS;
+   }
+
+   offset = address >> 20;
+   if(offset != 0x100 && offset != 0x101)
+      return mem_read(s, size, address);
+
+   ++cacheTry;
+   offset = (address >> 2) & 0x3ff;
+   if(cacheAddr[offset] != (address >> 12) || cacheAddr[offset] == CACHE_MISS)
+   {
+      ++cacheMiss;
+      cacheAddr[offset] = address >> 12;
+      cacheData[offset] = mem_read(s, 4, address & ~3);
+   }
+   value = cacheData[offset];
+   if(s->big_endian)
+      address ^= 3;
+   switch(size) 
+   {
+      case 2: 
+         value = (value >> ((address & 2) << 3)) & 0xffff;
+         break;
+      case 1:
+         value = (value >> ((address & 3) << 3)) & 0xff;
+         break;
+   }
+
+   //Debug testing
+   value2 = mem_read(s, size, address2);
+   if(value != value2)
+      printf("miss match\n");
+   //if((cacheTry & 0xffff) == 0) printf("\n***cache(%d,%d)\n ", cacheMiss, cacheTry);
+   return value;
+}
+
+static void cache_write(State *s, int size, int unsigned address, unsigned int value)
+{
+   int offset;
+
+   mem_write(s, size, address, value);
+
+   offset = address >> 20;
+   if(offset != 0x100 && offset != 0x101)
+      return;
+
+   offset = (address >> 2) & 0x3ff;
+   if(size != 4)
+   {
+      cacheAddr[offset] = CACHE_MISS;
+      return;
+   }
+   cacheAddr[offset] = address >> 12;
+   cacheData[offset] = value;
+}
+
+#define mem_read cache_read
+#define mem_write cache_write
+#endif  //SIMPLE_CACHE
+/************* End optional cache implementation *************/
+
+
+void mult_big(unsigned int a, 
+              unsigned int b,
+              unsigned int *hi, 
+              unsigned int *lo)
+{
+   unsigned int ahi, alo, bhi, blo;
+   unsigned int c0, c1, c2;
+   unsigned int c1_a, c1_b;
+
+   ahi = a >> 16;
+   alo = a & 0xffff;
+   bhi = b >> 16;
+   blo = b & 0xffff;
+
+   c0 = alo * blo;
+   c1_a = ahi * blo;
+   c1_b = alo * bhi;
+   c2 = ahi * bhi;
+
+   c2 += (c1_a >> 16) + (c1_b >> 16);
+   c1 = (c1_a & 0xffff) + (c1_b & 0xffff) + (c0 >> 16);
+   c2 += (c1 >> 16);
+   c0 = (c1 << 16) + (c0 & 0xffff);
+   *hi = c2;
+   *lo = c0;
+}
+
+void mult_big_signed(int a, 
+                     int b,
+                     unsigned int *hi, 
+                     unsigned int *lo)
+{
+   unsigned int ahi, alo, bhi, blo;
+   unsigned int c0, c1, c2;
+   int c1_a, c1_b;
+
+   ahi = a >> 16;
+   alo = a & 0xffff;
+   bhi = b >> 16;
+   blo = b & 0xffff;
+
+   c0 = alo * blo;
+   c1_a = ahi * blo;
+   c1_b = alo * bhi;
+   c2 = ahi * bhi;
+
+   c2 += (c1_a >> 16) + (c1_b >> 16);
+   c1 = (c1_a & 0xffff) + (c1_b & 0xffff) + (c0 >> 16);
+   c2 += (c1 >> 16);
+   c0 = (c1 << 16) + (c0 & 0xffff);
+   *hi = c2;
+   *lo = c0;
+}
+
+//execute one cycle of a Plasma CPU
+void cycle(State *s, int show_mode)
+{
+   unsigned int opcode;
+   unsigned int op, rs, rt, rd, re, func, imm, target;
+   int imm_shift, branch=0, lbranch=2, skip2=0;
+   int *r=s->r;
+   unsigned int *u=(unsigned int*)s->r;
+   unsigned int ptr, epc, rSave;
+
+   opcode = mem_read(s, 4, s->pc);
+   op = (opcode >> 26) & 0x3f;
+   rs = (opcode >> 21) & 0x1f;
+   rt = (opcode >> 16) & 0x1f;
+   rd = (opcode >> 11) & 0x1f;
+   re = (opcode >> 6) & 0x1f;
+   func = opcode & 0x3f;
+   imm = opcode & 0xffff;
+   imm_shift = (((int)(short)imm) << 2) - 4;
+   target = (opcode << 6) >> 4;
+   ptr = (short)imm + r[rs];
+   r[0] = 0;
+   if(show_mode) 
+   {
+      printf("%8.8x %8.8x ", s->pc, opcode);
+      if(op == 0) 
+         printf("%8s ", special_string[func]);
+      else if(op == 1) 
+         printf("%8s ", regimm_string[rt]);
+      else 
+         printf("%8s ", opcode_string[op]);
+      printf("$%2.2d $%2.2d $%2.2d $%2.2d ", rs, rt, rd, re);
+      printf("%4.4x", imm);
+      if(show_mode == 1)
+         printf(" r[%2.2d]=%8.8x r[%2.2d]=%8.8x", rs, r[rs], rt, r[rt]);
+      printf("\n");
+   }
+   if(show_mode > 5) 
+      return;
+   epc = s->pc + 4;
+   if(s->pc_next != s->pc + 4)
+      epc |= 2;  //branch delay slot
+   s->pc = s->pc_next;
+   s->pc_next = s->pc_next + 4;
+   if(s->skip) 
+   {
+      s->skip = 0;
+      return;
+   }
+   rSave = r[rt];
+   switch(op) 
+   {
+      case 0x00:/*SPECIAL*/
+         switch(func) 
+         {
+            case 0x00:/*SLL*/  r[rd]=r[rt]<<re;          break;
+            case 0x02:/*SRL*/  r[rd]=u[rt]>>re;          break;
+            case 0x03:/*SRA*/  r[rd]=r[rt]>>re;          break;
+            case 0x04:/*SLLV*/ r[rd]=r[rt]<<r[rs];       break;
+            case 0x06:/*SRLV*/ r[rd]=u[rt]>>r[rs];       break;
+            case 0x07:/*SRAV*/ r[rd]=r[rt]>>r[rs];       break;
+            case 0x08:/*JR*/   s->pc_next=r[rs];         break;
+            case 0x09:/*JALR*/ r[rd]=s->pc_next; s->pc_next=r[rs]; break;
+            case 0x0a:/*MOVZ*/ if(!r[rt]) r[rd]=r[rs];   break;  /*IV*/
+            case 0x0b:/*MOVN*/ if(r[rt]) r[rd]=r[rs];    break;  /*IV*/
+            case 0x0c:/*SYSCALL*/ epc|=1; s->exceptionId=1; break;
+            case 0x0d:/*BREAK*/   epc|=1; s->exceptionId=1; break;
+            case 0x0f:/*SYNC*/ s->wakeup=1;              break;
+            case 0x10:/*MFHI*/ r[rd]=s->hi;              break;
+            case 0x11:/*FTHI*/ s->hi=r[rs];              break;
+            case 0x12:/*MFLO*/ r[rd]=s->lo;              break;
+            case 0x13:/*MTLO*/ s->lo=r[rs];              break;
+            case 0x18:/*MULT*/ mult_big_signed(r[rs],r[rt],&s->hi,&s->lo); break;
+            case 0x19:/*MULTU*/ mult_big(r[rs],r[rt],&s->hi,&s->lo); break;
+            case 0x1a:/*DIV*/  s->lo=r[rs]/r[rt]; s->hi=r[rs]%r[rt]; break;
+            case 0x1b:/*DIVU*/ s->lo=u[rs]/u[rt]; s->hi=u[rs]%u[rt]; break;
+            case 0x20:/*ADD*/  r[rd]=r[rs]+r[rt];        break;
+            case 0x21:/*ADDU*/ r[rd]=r[rs]+r[rt];        break;
+            case 0x22:/*SUB*/  r[rd]=r[rs]-r[rt];        break;
+            case 0x23:/*SUBU*/ r[rd]=r[rs]-r[rt];        break;
+            case 0x24:/*AND*/  r[rd]=r[rs]&r[rt];        break;
+            case 0x25:/*OR*/   r[rd]=r[rs]|r[rt];        break;
+            case 0x26:/*XOR*/  r[rd]=r[rs]^r[rt];        break;
+            case 0x27:/*NOR*/  r[rd]=~(r[rs]|r[rt]);     break;
+            case 0x2a:/*SLT*/  r[rd]=r[rs]<r[rt];        break;
+            case 0x2b:/*SLTU*/ r[rd]=u[rs]<u[rt];        break;
+            case 0x2d:/*DADDU*/r[rd]=r[rs]+u[rt];        break;
+            case 0x31:/*TGEU*/ break;
+            case 0x32:/*TLT*/  break;
+            case 0x33:/*TLTU*/ break;
+            case 0x34:/*TEQ*/  break;
+            case 0x36:/*TNE*/  break;
+            default: printf("ERROR0(*0x%x~0x%x)\n", s->pc, opcode);
+               s->wakeup=1;
+         }
+         break;
+      case 0x01:/*REGIMM*/
+         switch(rt) {
+            case 0x10:/*BLTZAL*/ r[31]=s->pc_next;
+            case 0x00:/*BLTZ*/   branch=r[rs]<0;    break;
+            case 0x11:/*BGEZAL*/ r[31]=s->pc_next;
+            case 0x01:/*BGEZ*/   branch=r[rs]>=0;   break;
+            case 0x12:/*BLTZALL*/r[31]=s->pc_next;
+            case 0x02:/*BLTZL*/  lbranch=r[rs]<0;   break;
+            case 0x13:/*BGEZALL*/r[31]=s->pc_next;
+            case 0x03:/*BGEZL*/  lbranch=r[rs]>=0;  break;
+            default: printf("ERROR1\n"); s->wakeup=1;
+          }
+         break;
+      case 0x03:/*JAL*/    r[31]=s->pc_next;
+      case 0x02:/*J*/      s->pc_next=(s->pc&0xf0000000)|target; break;
+      case 0x04:/*BEQ*/    branch=r[rs]==r[rt];     break;
+      case 0x05:/*BNE*/    branch=r[rs]!=r[rt];     break;
+      case 0x06:/*BLEZ*/   branch=r[rs]<=0;         break;
+      case 0x07:/*BGTZ*/   branch=r[rs]>0;          break;
+      case 0x08:/*ADDI*/   r[rt]=r[rs]+(short)imm;  break;
+      case 0x09:/*ADDIU*/  u[rt]=u[rs]+(short)imm;  break;
+      case 0x0a:/*SLTI*/   r[rt]=r[rs]<(short)imm;  break;
+      case 0x0b:/*SLTIU*/  u[rt]=u[rs]<(unsigned int)(short)imm; break;
+      case 0x0c:/*ANDI*/   r[rt]=r[rs]&imm;         break;
+      case 0x0d:/*ORI*/    r[rt]=r[rs]|imm;         break;
+      case 0x0e:/*XORI*/   r[rt]=r[rs]^imm;         break;
+      case 0x0f:/*LUI*/    r[rt]=(imm<<16);         break;
+      case 0x10:/*COP0*/
+         if((opcode & (1<<23)) == 0)  //move from CP0
+         {
+            if(rd == 12)
+               r[rt]=s->status;
+            else
+               r[rt]=s->epc;
+         }
+         else                         //move to CP0
+         {
+            s->status=r[rt]&1;
+            if(s->processId && (r[rt]&2))
+            {
+               s->userMode|=r[rt]&2;
+               //printf("CpuStatus=%d %d %d\n", r[rt], s->status, s->userMode);
+               //s->wakeup = 1;
+               //printf("pc=0x%x\n", epc);
+            }
+         }
+         break;
+//      case 0x11:/*COP1*/ break;
+//      case 0x12:/*COP2*/ break;
+//      case 0x13:/*COP3*/ break;
+      case 0x14:/*BEQL*/   lbranch=r[rs]==r[rt];    break;
+      case 0x15:/*BNEL*/   lbranch=r[rs]!=r[rt];    break;
+      case 0x16:/*BLEZL*/  lbranch=r[rs]<=0;        break;
+      case 0x17:/*BGTZL*/  lbranch=r[rs]>0;         break;
+//      case 0x1c:/*MAD*/  break;   /*IV*/
+      case 0x20:/*LB*/   r[rt]=(signed char)mem_read(s,1,ptr);  break;
+      case 0x21:/*LH*/   r[rt]=(signed short)mem_read(s,2,ptr); break;
+      case 0x22:/*LWL*/  
+                         //target=8*(ptr&3);
+                         //r[rt]=(r[rt]&~(0xffffffff<<target))|
+                         //      (mem_read(s,4,ptr&~3)<<target); break;
+      case 0x23:/*LW*/   r[rt]=mem_read(s,4,ptr);   break;
+      case 0x24:/*LBU*/  r[rt]=(unsigned char)mem_read(s,1,ptr); break;
+      case 0x25:/*LHU*/  r[rt]=(unsigned short)mem_read(s,2,ptr); break;
+      case 0x26:/*LWR*/  
+                         //target=32-8*(ptr&3);
+                         //r[rt]=(r[rt]&~((unsigned int)0xffffffff>>target))|
+                         //((unsigned int)mem_read(s,4,ptr&~3)>>target); 
+                         break;
+      case 0x28:/*SB*/   mem_write(s,1,ptr,r[rt]);  break;
+      case 0x29:/*SH*/   mem_write(s,2,ptr,r[rt]);  break;
+      case 0x2a:/*SWL*/  
+                         //mem_write(s,1,ptr,r[rt]>>24);  
+                         //mem_write(s,1,ptr+1,r[rt]>>16);
+                         //mem_write(s,1,ptr+2,r[rt]>>8);
+                         //mem_write(s,1,ptr+3,r[rt]); break;
+      case 0x2b:/*SW*/   mem_write(s,4,ptr,r[rt]);  break;
+      case 0x2e:/*SWR*/  break; //fixme
+      case 0x2f:/*CACHE*/break;
+      case 0x30:/*LL*/   r[rt]=mem_read(s,4,ptr);   break;
+//      case 0x31:/*LWC1*/ break;
+//      case 0x32:/*LWC2*/ break;
+//      case 0x33:/*LWC3*/ break;
+//      case 0x35:/*LDC1*/ break;
+//      case 0x36:/*LDC2*/ break;
+//      case 0x37:/*LDC3*/ break;
+//      case 0x38:/*SC*/     *(int*)ptr=r[rt]; r[rt]=1; break;
+      case 0x38:/*SC*/     mem_write(s,4,ptr,r[rt]); r[rt]=1; break;
+//      case 0x39:/*SWC1*/ break;
+//      case 0x3a:/*SWC2*/ break;
+//      case 0x3b:/*SWC3*/ break;
+//      case 0x3d:/*SDC1*/ break;
+//      case 0x3e:/*SDC2*/ break;
+//      case 0x3f:/*SDC3*/ break;
+      default: printf("ERROR2 address=0x%x opcode=0x%x\n", s->pc, opcode); 
+         s->wakeup=1;
+   }
+   s->pc_next += (branch || lbranch == 1) ? imm_shift : 0;
+   s->pc_next &= ~3;
+   s->skip = (lbranch == 0) | skip2;
+
+   if(s->exceptionId)
+   {
+      r[rt] = rSave;
+      s->epc = epc; 
+      s->pc_next = 0x3c;
+      s->skip = 1; 
+      s->exceptionId = 0;
+      s->userMode = 0;
+      //s->wakeup = 1;
+      return;
+   }
+}
+
+void show_state(State *s)
+{
+   int i,j;
+   printf("pid=%d userMode=%d, epc=0x%x\n", s->processId, s->userMode, s->epc);
+   for(i = 0; i < 4; ++i) 
+   {
+      printf("%2.2d ", i * 8);
+      for(j = 0; j < 8; ++j) 
+      {
+         printf("%8.8x ", s->r[i*8+j]);
+      }
+      printf("\n");
+   }
+   //printf("%8.8lx %8.8lx %8.8lx %8.8lx\n", s->pc, s->pc_next, s->hi, s->lo);
+   j = s->pc;
+   for(i = -4; i <= 8; ++i) 
+   {
+      printf("%c", i==0 ? '*' : ' ');
+      s->pc = j + i * 4;
+      cycle(s, 10);
+   }
+   s->pc = j;
+}
+
+void do_debug(State *s)
+{
+   int ch;
+   int i, j=0, watch=0, addr;
+   s->pc_next = s->pc + 4;
+   s->skip = 0;
+   s->wakeup = 0;
+   show_state(s);
+   ch = ' ';
+   for(;;) 
+   {
+      if(ch != 'n')
+      {
+         if(watch) 
+            printf("0x%8.8x=0x%8.8x\n", watch, mem_read(s, 4, watch));
+         printf("1=Debug 2=Trace 3=Step 4=BreakPt 5=Go 6=Memory ");
+         printf("7=Watch 8=Jump 9=Quit> ");
+      }
+      ch = getch();
+      if(ch != 'n')
+         printf("\n");
+      switch(ch) 
+      {
+      case '1': case 'd': case ' ': 
+         cycle(s, 0); show_state(s); break;
+      case 'n': 
+         cycle(s, 1); break;
+      case '2': case 't': 
+         cycle(s, 0); printf("*"); cycle(s, 10); break;
+      case '3': case 's':
+         printf("Count> ");
+         scanf("%d", &j);
+         for(i = 0; i < j; ++i) 
+            cycle(s, 1);
+         show_state(s);
+         break;
+      case '4': case 'b':
+         printf("Line> ");
+         scanf("%x", &j);
+         printf("break point=0x%x\n", j);
+         break;
+      case '5': case 'g':
+         s->wakeup = 0;
+         cycle(s, 0);
+         while(s->wakeup == 0) 
+         {
+            if(s->pc == j) 
+               break;
+            cycle(s, 0);
+         }
+         show_state(s);
+         break;
+      case 'G':
+         s->wakeup = 0;
+         cycle(s, 1);
+         while(s->wakeup == 0) 
+         {
+            if(s->pc == j) 
+               break;
+            cycle(s, 1);
+         }
+         show_state(s);
+         break;
+      case '6': case 'm':
+         printf("Memory> ");
+         scanf("%x", &j);
+         for(i = 0; i < 8; ++i) 
+         {
+            printf("%8.8x ", mem_read(s, 4, j+i*4));
+         }
+         printf("\n");
+         break;
+      case '7': case 'w':
+         printf("Watch> ");
+         scanf("%x", &watch);
+         break;
+      case '8': case 'j':
+         printf("Jump> ");
+         scanf("%x", &addr);
+         s->pc = addr;
+         s->pc_next = addr + 4;
+         show_state(s);
+         break;
+      case '9': case 'q': 
+         return;
+      }
+   }
+}
+/************************************************************/
+
+int main(int argc,char *argv[])
+{
+   State state, *s=&state;
+   FILE *in;
+   int bytes, index;
+   printf("Plasma emulator\n");
+   memset(s, 0, sizeof(State));
+   s->big_endian = 1;
+   s->mem = (unsigned char*)malloc(MEM_SIZE);
+   memset(s->mem, 0, MEM_SIZE);
+   if(argc <= 1) 
+   {
+      printf("   Usage:  mlite file.exe\n");
+      printf("           mlite file.exe B   {for big_endian}\n");
+      printf("           mlite file.exe L   {for little_endian}\n");
+      printf("           mlite file.exe BD  {disassemble big_endian}\n");
+      printf("           mlite file.exe LD  {disassemble little_endian}\n");
+
+      return 0;
+   }
+   in = fopen(argv[1], "rb");
+   if(in == NULL) 
+   { 
+      printf("Can't open file %s!\n",argv[1]); 
+      getch(); 
+      return(0); 
+   }
+   bytes = fread(s->mem, 1, MEM_SIZE, in);
+   fclose(in);
+   memcpy(s->mem + 1024*1024, s->mem, 1024*1024);  //internal 8KB SRAM
+   printf("Read %d bytes.\n", bytes);
+   cache_init();
+   if(argc == 3 && argv[2][0] == 'B') 
+   {
+      printf("Big Endian\n");
+      s->big_endian = 1;
+   }
+   if(argc == 3 && argv[2][0] == 'L') 
+   {
+      printf("Big Endian\n");
+      s->big_endian = 0;
+   }
+   s->processId = 0;
+   if(argc == 3 && argv[2][0] == 'S') 
+   {  /*make big endian*/
+      printf("Big Endian\n");
+      for(index = 0; index < bytes+3; index += 4) 
+      {
+         *(unsigned int*)&s->mem[index] = htonl(*(unsigned int*)&s->mem[index]);
+      }
+      in = fopen("big.exe", "wb");
+      fwrite(s->mem, bytes, 1, in);
+      fclose(in);
+      return(0);
+   }
+   if(argc == 3 && argv[2][1] == 'D') 
+   {  /*dump image*/
+      for(index = 0; index < bytes; index += 4) {
+         s->pc = index;
+         cycle(s, 10);
+      }
+      free(s->mem);
+      return(0);
+   }
+   s->pc = 0x0;
+   index = mem_read(s, 4, 0);
+   if((index & 0xffffff00) == 0x3c1c1000)
+      s->pc = 0x10000000;
+   do_debug(s);
+   free(s->mem);
+   return(0);
+}
+
diff --git a/tools/no_os.c b/tools/no_os.c
new file mode 100644 (file)
index 0000000..07dd9bd
--- /dev/null
@@ -0,0 +1,54 @@
+#include "plasma.h"
+
+#define MemoryRead(A) (*(volatile unsigned int*)(A))
+#define MemoryWrite(A,V) *(volatile unsigned int*)(A)=(V)
+
+int putchar(int value)
+{
+   while((MemoryRead(IRQ_STATUS) & IRQ_UART_WRITE_AVAILABLE) == 0)
+      ;
+   MemoryWrite(UART_WRITE, value);
+   return 0;
+}
+
+int puts(const char *string)
+{
+   while(*string)
+   {
+      if(*string == '\n')
+         putchar('\r');
+      putchar(*string++);
+   }
+   return 0;
+}
+
+void print_hex(unsigned long num)
+{
+   long i;
+   unsigned long j;
+   for(i = 28; i >= 0; i -= 4) 
+   {
+      j = (num >> i) & 0xf;
+      if(j < 10) 
+         putchar('0' + j);
+      else 
+         putchar('a' - 10 + j);
+   }
+}
+
+void OS_InterruptServiceRoutine(unsigned int status)
+{
+   (void)status;
+   putchar('I');
+}
+
+int kbhit(void)
+{
+   return MemoryRead(IRQ_STATUS) & IRQ_UART_READ_AVAILABLE;
+}
+
+int getch(void)
+{
+   while(!kbhit()) ;
+   return MemoryRead(UART_READ);
+}
diff --git a/tools/opcodes.asm b/tools/opcodes.asm
new file mode 100644 (file)
index 0000000..1482219
--- /dev/null
@@ -0,0 +1,1108 @@
+##################################################################
+# TITLE: Opcode Tester
+# AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
+# DATE CREATED: 1/10/02
+# FILENAME: opcodes.asm
+# PROJECT: Plasma CPU core
+# COPYRIGHT: Software placed into the public domain by the author.
+#    Software 'as is' without warranty.  Author liable for nothing.
+# DESCRIPTION:
+#    This assembly file tests all of the opcodes supported by the
+#    Plasma core.
+#    This test assumes that address 0x20000000 is the UART write register
+#    Successful tests will print out "A" or "AB" or "ABC" or ....
+#    Missing letters or letters out of order indicate a failure.
+##################################################################
+       .text
+       .align  2
+       .globl  entry
+       .ent    entry
+entry:
+   .set noreorder
+
+   la    $gp, _gp           #initialize stack pointer
+   la    $4, __bss_start    #$4 = .sbss_start
+   la    $5, _end           #$5 = .bss_end
+   nop                      #no stack needed
+   nop
+
+   b     StartTest
+   nop                      #nops required to place ISR at 0x3c
+   nop
+
+OS_AsmPatchValue:
+   #Code to place at address 0x3c
+   lui   $26, 0x1000
+   ori   $26, $26, 0x3c
+   jr    $26
+   nop
+
+InterruptVector:            #Address=0x3c
+   mfc0  $26,$14            #C0_EPC=14 (Exception PC)
+   jr    $26
+   add   $4,$4,5
+   
+StartTest:
+   mtc0  $0,$12             #disable interrupts
+   lui   $20,0x2000         #serial port write address
+   ori   $21,$0,'\n'        #<CR> letter
+   ori   $22,$0,'X'         #'X' letter
+   ori   $23,$0,'\r'
+   ori   $24,$0,0x0f80      #temp memory
+
+   sb    $23,0($20)
+   sb    $21,0($20)
+   sb    $23,0($20)
+   sb    $21,0($20)
+   sb    $23,0($20)
+   sb    $21,0($20)
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #Patch interrupt vector to 0x1000003c
+   la    $5, OS_AsmPatchValue
+   sub   $6,$5,0x1000
+   blez  $6,NoPatch
+   
+   lw    $6, 0($5)
+   sw    $6, 0x3c($0)
+   lw    $6, 4($5)
+   sw    $6, 0x40($0)
+   lw    $6, 8($5)
+   sw    $6, 0x44($0)
+   lw    $6, 12($5)
+   sw    $6, 0x48($0)
+NoPatch:
+
+   ######################################
+   #Arithmetic Instructions
+   ######################################
+ArthmeticTest:
+   ori   $2,$0,'A'
+   sb    $2,0($20)
+   ori   $2,$0,'r'
+   sb    $2,0($20)
+   ori   $2,$0,'i'
+   sb    $2,0($20)
+   ori   $2,$0,'t'
+   sb    $2,0($20)
+   ori   $2,$0,'h'
+   sb    $2,0($20)
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #a: ADD
+   ori   $2,$0,'a'
+   sb    $2,0($20)
+   ori   $3,$0,5
+   ori   $4,$0,60
+   add   $2,$3,$4
+   sb    $2,0($20)    #A
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #b: ADDI
+   ori   $2,$0,'b'
+   sb    $2,0($20)
+   ori   $4,$0,60
+   addi  $2,$4,5
+   sb    $2,0($20)    #A
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #c: ADDIU
+   ori   $2,$0,'c'
+   sb    $2,0($20)
+   ori   $4,$0,50
+   addiu $5,$4,15
+   sb    $5,0($20)    #A
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #d: ADDU
+   ori   $2,$0,'d'
+   sb    $2,0($20)
+   ori   $3,$0,5
+   ori   $4,$0,60
+   add   $2,$3,$4
+   sb    $2,0($20)    #A
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #e: DIV
+   ori   $2,$0,'e'
+   sb    $2,0($20)
+   ori   $2,$0,65*117+41
+   ori   $3,$0,117
+   div   $2,$3
+   nop
+   mflo  $4
+   sb    $4,0($20)    #A
+   mfhi  $4
+   addi  $4,$4,66-41
+   sb    $4,0($20)    #B
+   li    $2,-67*19
+   ori   $3,$0,19
+   div   $2,$3
+   nop
+   mflo  $4
+   sub   $4,$0,$4
+   sb    $4,0($20)    #C
+   ori   $2,$0,68*23
+   li    $3,-23
+   div   $2,$3
+   nop
+   mflo  $4
+   sub   $4,$0,$4
+   sb    $4,0($20)    #D
+   li    $2,-69*13
+   li    $3,-13
+   div   $2,$3
+   mflo  $4
+   sb    $4,0($20)    #E
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #f: DIVU
+   ori   $2,$0,'f'
+   sb    $2,0($20)
+   ori   $2,$0,65*13
+   ori   $3,$0,13
+   divu  $2,$3
+   nop
+   mflo  $4
+   sb    $4,0($20)    #A
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #g: MULT
+   ori   $2,$0,'g'
+   sb    $2,0($20)
+   ori   $2,$0,5
+   ori   $3,$0,13
+   mult  $2,$3
+   nop
+   mflo  $4
+   sb    $4,0($20)    #A
+   li    $2,-5
+   ori   $3,$0,13
+   mult  $2,$3
+   mfhi  $5
+   mflo  $4
+   sub   $4,$0,$4
+   addu  $4,$4,$5
+   addi  $4,$4,2
+   sb    $4,0($20)    #B
+   ori   $2,$0,5
+   li    $3,-13
+   mult  $2,$3
+   mfhi  $5
+   mflo  $4
+   sub   $4,$0,$4
+   addu  $4,$4,$5
+   addi  $4,$4,3
+   sb    $4,0($20)    #C
+   li    $2,-5
+   li    $3,-13
+   mult  $2,$3
+   mfhi  $5
+   mflo  $4
+   addu  $4,$4,$5
+   addi  $4,$4,3
+   sb    $4,0($20)    #D
+   lui   $4,0xfe98
+   ori   $4,$4,0x62e5
+   lui   $5,0x6
+   ori   $5,0x8db8
+   mult  $4,$5
+   mfhi  $6
+   addiu $7,$6,2356+1+'E' #E
+   sb    $7,0($20)
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #h: MULTU
+   ori   $2,$0,'h'
+   sb    $2,0($20)
+   ori   $2,$0,5
+   ori   $3,$0,13
+   multu $2,$3
+   nop
+   mflo  $4
+   sb    $4,0($20)    #A
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #i: SLT
+   ori   $2,$0,'i'
+   sb    $2,0($20)
+   ori   $2,$0,10
+   ori   $3,$0,12
+   slt   $4,$2,$3
+   addi  $5,$4,64
+   sb    $5,0($20)    #A
+   slt   $4,$3,$2
+   addi  $5,$4,66
+   sb    $5,0($20)    #B
+   li    $2,0xfffffff0
+   slt   $4,$2,$3
+   addi  $5,$4,66
+   sb    $5,0($20)    #C
+   slt   $4,$3,$2
+   addi  $5,$4,68
+   sb    $5,0($20)    #D
+   li    $3,0xffffffff
+   slt   $4,$2,$3
+   addi  $5,$4,68
+   sb    $5,0($20)    #E
+   slt   $4,$3,$2
+   addi  $5,$4,70
+   sb    $5,0($20)    #F
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #j: SLTI
+   ori   $2,$0,'j'
+   sb    $2,0($20)
+   ori   $2,$0,10
+   slti  $4,$2,12
+   addi  $5,$4,64
+   sb    $5,0($20)    #A
+   slti  $4,$2,8
+   addi  $5,$4,66
+   sb    $5,0($20)    #B
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #k: SLTIU
+   ori   $2,$0,'k'
+   sb    $2,0($20)
+   ori   $2,$0,10
+   sltiu $4,$2,12
+   addi  $5,$4,64
+   sb    $5,0($20)    #A
+   sltiu $4,$2,8
+   addi  $5,$4,66
+   sb    $5,0($20)    #B
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #l: SLTU
+   ori   $2,$0,'l'
+   sb    $2,0($20)
+   ori   $2,$0,10
+   ori   $3,$0,12
+   slt   $4,$2,$3
+   addi  $5,$4,64
+   sb    $5,0($20)    #A
+   slt   $4,$3,$2
+   addi  $5,$4,66
+   sb    $5,0($20)    #B
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #m: SUB
+   ori   $2,$0,'m'
+   sb    $2,0($20)
+   ori   $3,$0,70
+   ori   $4,$0,5
+   sub   $2,$3,$4
+   sb    $2,0($20)    #A
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #n: SUBU
+   ori   $2,$0,'n'
+   sb    $2,0($20)
+   ori   $3,$0,70
+   ori   $4,$0,5
+   sub   $2,$3,$4
+   sb    $2,0($20)    #A
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   ######################################
+   #Branch and Jump Instructions
+   ######################################
+BranchTest:
+   ori   $2,$0,'B'
+   sb    $2,0($20)
+   ori   $2,$0,'r'
+   sb    $2,0($20)
+   ori   $2,$0,'a'
+   sb    $2,0($20)
+   ori   $2,$0,'n'
+   sb    $2,0($20)
+   ori   $2,$0,'c'
+   sb    $2,0($20)
+   ori   $2,$0,'h'
+   sb    $2,0($20)
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #a: B
+   ori   $2,$0,'a'
+   sb    $2,0($20)
+   ori   $10,$0,'A'
+   ori   $11,$0,'B'
+   b     $B1
+   sb    $10,0($20)
+   sb    $22,0($20)
+$B1:
+   sb    $11,0($20)
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #b: BAL
+   ori   $2,$0,'b'
+   sb    $2,0($20)
+   ori   $10,$0,'A'
+   ori   $11,$0,'B'
+   ori   $12,$0,'C'
+   ori   $13,$0,'D'
+   ori   $14,$0,'E'
+   ori   $15,$0,'X'
+   bal   $BAL1
+   sb    $10,0($20)
+   sb    $13,0($20)
+   b     $BAL2
+   sb    $14,0($20)
+   sb    $15,0($20)
+$BAL1:
+   sb    $11,0($20)
+   jr    $31
+   sb    $12,0($20)
+   sb    $22,0($20)
+$BAL2:
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #c: BEQ
+   ori   $2,$0,'c'
+   sb    $2,0($20)
+   ori   $10,$0,'A'
+   ori   $11,$0,'B'
+   ori   $12,$0,'C'
+   ori   $13,$0,'D'
+   ori   $2,$0,100
+   ori   $3,$0,123
+   ori   $4,$0,123
+   beq   $2,$3,$BEQ1
+   sb    $10,0($20)
+   sb    $11,0($20)
+   beq   $3,$4,$BEQ1
+   sb    $12,0($20)
+   sb    $22,0($20)
+$BEQ1:
+   sb    $13,0($20)
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #d: BGEZ
+   ori   $2,$0,'d'
+   sb    $2,0($20)
+   ori   $10,$0,'A'
+   ori   $11,$0,'B'
+   ori   $12,$0,'C'
+   ori   $13,$0,'D'
+   or    $15,$0,'X'
+   ori   $2,$0,100
+   li    $3,0xffff1234
+   ori   $4,$0,123
+   bgez  $3,$BGEZ1
+   sb    $10,0($20)
+   sb    $11,0($20)
+   bgez  $2,$BGEZ1
+   sb    $12,0($20)
+   sb    $22,0($20)
+$BGEZ1:
+   bgez  $0,$BGEZ2
+   nop
+   sb    $15,0($20)
+$BGEZ2:
+   sb    $13,0($20)
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #e: BGEZAL
+   ori   $2,$0,'e'
+   sb    $2,0($20)
+   ori   $10,$0,'A'
+   ori   $11,$0,'B'
+   ori   $12,$0,'C'
+   ori   $13,$0,'D'
+   ori   $14,$0,'E'
+   ori   $15,$0,'X'
+   li    $3,0xffff1234
+   bgezal $3,$BGEZAL1
+   nop
+   sb    $10,0($20)
+   bgezal $0,$BGEZAL1
+   nop
+   sb    $13,0($20)
+   b     $BGEZAL2
+   sb    $14,0($20)
+   sb    $15,0($20)
+$BGEZAL1:
+   sb    $11,0($20)
+   jr    $31
+   sb    $12,0($20)
+   sb    $22,0($20)
+$BGEZAL2:
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #f: BGTZ
+   ori   $2,$0,'f'
+   sb    $2,0($20)
+   ori   $10,$0,'A'
+   ori   $11,$0,'B'
+   ori   $12,$0,'C'
+   ori   $13,$0,'D'
+   ori   $2,$0,100
+   li    $3,0xffff1234
+   bgtz  $3,$BGTZ1
+   sb    $10,0($20)
+   sb    $11,0($20)
+   bgtz  $2,$BGTZ1
+   sb    $12,0($20)
+   sb    $22,0($20)
+$BGTZ1:
+   sb    $13,0($20)
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #g: BLEZ
+   ori   $2,$0,'g'
+   sb    $2,0($20)
+   ori   $10,$0,'A'
+   ori   $11,$0,'B'
+   ori   $12,$0,'C'
+   ori   $13,$0,'D'
+   ori   $2,$0,100
+   li    $3,0xffff1234
+   blez  $2,$BLEZ1
+   sb    $10,0($20)
+   sb    $11,0($20)
+   blez  $3,$BLEZ1
+   sb    $12,0($20)
+   sb    $22,0($20)
+$BLEZ1:
+   blez  $0,$BLEZ2
+   nop
+   sb    $22,0($20)
+$BLEZ2:
+   sb    $13,0($20)
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #h: BLTZ
+   ori   $2,$0,'h'
+   sb    $2,0($20)
+   ori   $10,$0,'A'
+   ori   $11,$0,'B'
+   ori   $12,$0,'C'
+   ori   $13,$0,'D'
+   ori   $14,$0,'E'
+   ori   $2,$0,100
+   li    $3,0xffff1234
+   ori   $4,$0,0
+   bltz  $2,$BLTZ1
+   sb    $10,0($20)
+   sb    $11,0($20)
+   bltz  $3,$BLTZ1
+   sb    $12,0($20)
+   sb    $22,0($20)
+$BLTZ1:
+   bltz  $4,$BLTZ2
+   nop
+   sb    $13,0($20)
+$BLTZ2:
+   sb    $14,0($20)
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #i: BLTZAL
+   ori   $2,$0,'i'
+   sb    $2,0($20)
+   ori   $10,$0,'A'
+   ori   $11,$0,'B'
+   ori   $12,$0,'C'
+   ori   $13,$0,'D'
+   ori   $14,$0,'E'
+   ori   $15,$0,'X'
+   li    $3,0xffff1234
+   bltzal $0,$BLTZAL1
+   nop
+   sb    $10,0($20)
+   bltzal $3,$BLTZAL1
+   nop
+   sb    $13,0($20)
+   b     $BLTZAL2
+   sb    $14,0($20)
+   sb    $15,0($20)
+$BLTZAL1:
+   sb    $11,0($20)
+   jr    $31
+   sb    $12,0($20)
+   sb    $22,0($20)
+$BLTZAL2:
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #j: BNE
+   ori   $2,$0,'j'
+   sb    $2,0($20)
+   ori   $10,$0,'A'
+   ori   $11,$0,'B'
+   ori   $12,$0,'C'
+   ori   $13,$0,'D'
+   ori   $2,$0,100
+   ori   $3,$0,123
+   ori   $4,$0,123
+   bne   $3,$4,$BNE1
+   sb    $10,0($20)
+   sb    $11,0($20)
+   bne   $2,$3,$BNE1
+   sb    $12,0($20)
+   sb    $22,0($20)
+$BNE1:
+   sb    $13,0($20)
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #k: J
+   ori   $2,$0,'k'
+   sb    $2,0($20)
+   ori   $10,$0,'A'
+   ori   $11,$0,'B'
+   ori   $15,$0,'X'
+   j     $J1
+   sb    $10,0($20)
+   sb    $15,0($20)
+$J1:
+   sb    $11,0($20)
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #l: JAL
+   ori   $2,$0,'l'
+   sb    $2,0($20)
+   ori   $10,$0,'A'
+   ori   $11,$0,'B'
+   ori   $12,$0,'C'
+   ori   $13,$0,'D'
+   ori   $14,$0,'E'
+   ori   $15,$0,'X'
+   jal   $JAL1
+   sb    $10,0($20)
+   sb    $13,0($20)
+   b     $JAL2
+   sb    $14,0($20)
+   sb    $15,0($20)
+$JAL1:
+   sb    $11,0($20)
+   jr    $31
+   sb    $12,0($20)
+   sb    $22,0($20)
+$JAL2:
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #m: JALR
+   ori   $2,$0,'m'
+   sb    $2,0($20)
+   ori   $10,$0,'A'
+   ori   $11,$0,'B'
+   ori   $12,$0,'C'
+   ori   $13,$0,'D'
+   ori   $14,$0,'E'
+   ori   $15,$0,'X'
+   la    $3,$JALR1
+   jalr  $3
+   sb    $10,0($20)
+   sb    $13,0($20)
+   b     $JALR2
+   sb    $14,0($20)
+   sb    $15,0($20)
+$JALR1:
+   sb    $11,0($20)
+   jr    $31
+   sb    $12,0($20)
+   sb    $22,0($20)
+$JALR2:
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #n: JR
+   ori   $2,$0,'n'
+   sb    $2,0($20)
+   ori   $10,$0,'A'
+   ori   $11,$0,'B'
+   ori   $15,$0,'X'
+   la    $3,$JR1
+   jr    $3
+   sb    $10,0($20)
+   sb    $15,0($20)
+$JR1:
+   sb    $11,0($20)
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #o: NOP
+   ori   $2,$0,'o'
+   sb    $2,0($20)
+   ori   $2,$0,65
+   nop
+   sb    $2,0($20)
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+#   b     LoadTest
+
+BreakTest:
+   #p: BREAK
+   ori   $2,$0,'p'
+   sb    $2,0($20)
+   ori   $2,$0,'z'
+   ori   $4,$0,59
+   break 0
+   addi  $4,$4,1
+   sb    $4,0($20)
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #q: SYSCALL
+   ori   $2,$0,'q'
+   sb    $2,0($20)
+   ori   $4,$0,61
+   syscall 0
+   addi  $4,$4,-1
+   sb    $4,0($20)
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+
+   ######################################
+   #Load, Store, and Memory Control Instructions
+   ######################################
+LoadTest:
+   ori   $2,$0,'L'
+   sb    $2,0($20)
+   ori   $2,$0,'o'
+   sb    $2,0($20)
+   ori   $2,$0,'a'
+   sb    $2,0($20)
+   ori   $2,$0,'d'
+   sb    $2,0($20)
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #a: LB
+   ori   $2,$0,'a'
+   sb    $2,0($20)
+   or    $2,$0,$24
+   li    $3,0x414243fc
+   sw    $3,16($2)
+   lb    $4,16($2)
+   sb    $4,0($20)
+   lb    $4,17($2)
+   sb    $4,0($20)
+   lb    $4,18($2)
+   sb    $4,0($20)
+   lb    $2,19($2)
+   sra   $3,$2,8
+   addi  $3,$3,0x45
+   sb    $3,0($20)
+   addi  $2,$2,0x49
+   sb    $2,0($20)
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #b: LBU
+   ori   $2,$0,'b'
+   sb    $2,0($20)
+   or    $2,$0,$24
+   li    $3,0x41424344
+   sw    $3,16($2)
+   lb    $4,16($2)
+   sb    $4,0($20)
+   lb    $4,17($2)
+   sb    $4,0($20)
+   lb    $4,18($2)
+   sb    $4,0($20)
+   lb    $2,19($2)
+   sb    $2,0($20)
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #c: LH
+   ori   $2,$0,'c'
+   sb    $2,0($20)
+   or    $2,$0,$24
+   li    $3,0x00410042
+   sw    $3,16($2)
+   lh    $4,16($2)
+   sb    $4,0($20)
+   lh    $2,18($2)
+   sb    $2,0($20)
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #d: LHU
+   ori   $2,$0,'d'
+   sb    $2,0($20)
+   or    $2,$0,$24
+   li    $3,0x00410042
+   sw    $3,16($2)
+   lh    $4,16($2)
+   sb    $4,0($20)
+   lh    $2,18($2)
+   sb    $2,0($20)
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #e: LW
+   ori   $2,$0,'e'
+   sb    $2,0($20)
+   or    $2,$0,$24
+   li    $3,'A'
+   sw    $3,16($2)
+   ori   $3,$0,0
+   lw    $2,16($2)
+   sb    $2,0($20)
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #f: LWL & LWR
+   ori   $2,$0,'f'
+   sb    $2,0($20)
+   or    $2,$0,$24
+   li    $3,'A'
+   sw    $3,16($2)
+   ori   $3,$0,0
+   lwl   $2,16($2)
+   lwr   $2,16($2)
+   sb    $2,0($20)
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #g: SB
+   ori   $2,$0,'g'
+   sb    $2,0($20)
+   ori   $2,$0,'A'
+   sb    $2,0($20)
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #h: SH
+   ori   $2,$0,'h'
+   sb    $2,0($20)
+   or    $4,$0,$24
+   ori   $2,$0,0x4142
+   sh    $2,16($4)
+   lb    $3,16($4)
+   sb    $3,0($20)
+   lb    $2,17($4)
+   sb    $2,0($20)
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #i: SW
+   ori   $2,$0,'i'
+   sb    $2,0($20)
+   or    $2,$0,$24
+   li    $3,0x41424344
+   sw    $3,16($2)
+   lb    $4,16($2)
+   sb    $4,0($20)
+   lb    $4,17($2)
+   sb    $4,0($20)
+   lb    $4,18($2)
+   sb    $4,0($20)
+   lb    $2,19($2)
+   sb    $2,0($20)
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #j: SWL & SWR
+   ori   $2,$0,'j'
+   sb    $2,0($20)
+   or    $2,$0,$24
+   li    $3,0x41424344
+   swl   $3,16($2)
+   swr   $3,16($2)
+   lb    $4,16($2)
+   sb    $4,0($20)
+   lb    $4,17($2)
+   sb    $4,0($20)
+   lb    $4,18($2)
+   sb    $4,0($20)
+   lb    $2,19($2)
+   sb    $2,0($20)
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+
+   ######################################
+   #Logical Instructions
+   ######################################
+LogicalTest:
+   ori   $2,$0,'L'
+   sb    $2,0($20)
+   ori   $2,$0,'o'
+   sb    $2,0($20)
+   ori   $2,$0,'g'
+   sb    $2,0($20)
+   ori   $2,$0,'i'
+   sb    $2,0($20)
+   ori   $2,$0,'c'
+   sb    $2,0($20)
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #a: AND
+   ori   $2,$0,'a'
+   sb    $2,0($20)
+   ori   $2,$0,0x0741
+   ori   $3,$0,0x60f3
+   and   $4,$2,$3
+   sb    $4,0($20)
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #b: ANDI
+   ori   $2,$0,'b'
+   sb    $2,0($20)
+   ori   $2,$0,0x0741
+   andi  $4,$2,0x60f3
+   sb    $4,0($20)
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #c: LUI
+   ori   $2,$0,'c'
+   sb    $2,0($20)
+   lui   $2,0x41
+   srl   $3,$2,16
+   sb    $3,0($20)
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #d: NOR
+   ori   $2,$0,'d'
+   sb    $2,0($20)
+   li    $2,0xf0fff08e
+   li    $3,0x0f0f0f30
+   nor   $4,$2,$3
+   sb    $4,0($20)
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #e: OR
+   ori   $2,$0,'e'
+   sb    $2,0($20)
+   ori   $2,$0,0x40
+   ori   $3,$0,0x01
+   or    $4,$2,$3
+   sb    $4,0($20)
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #f: ORI
+   ori   $2,$0,'f'
+   sb    $2,0($20)
+   ori   $2,$0,0x40
+   ori   $4,$2,0x01
+   sb    $4,0($20)
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #g: XOR
+   ori   $2,$0,'g'
+   sb    $2,0($20)
+   ori   $2,$0,0xf043
+   ori   $3,$0,0xf002
+   xor   $4,$2,$3
+   sb    $4,0($20)
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #h: XORI
+   ori   $2,$0,'h'
+   sb    $2,0($20)
+   ori   $2,$0,0xf043
+   xor   $4,$2,0xf002
+   sb    $4,0($20)
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   ######################################
+   #Move Instructions
+   ######################################
+MoveTest:
+   ori   $2,$0,'M'
+   sb    $2,0($20)
+   ori   $2,$0,'o'
+   sb    $2,0($20)
+   ori   $2,$0,'v'
+   sb    $2,0($20)
+   ori   $2,$0,'e'
+   sb    $2,0($20)
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #a: MFHI
+   ori   $2,$0,'a'
+   sb    $2,0($20)
+   ori   $2,$0,65
+   mthi  $2
+   mfhi  $3
+   sb    $3,0($20)
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #b: MFLO
+   ori   $2,$0,'b'
+   sb    $2,0($20)
+   ori   $2,$0,65
+   mtlo  $2
+   mflo  $3
+   sb    $3,0($20)
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #c: MTHI
+   ori   $2,$0,'c'
+   sb    $2,0($20)
+   ori   $2,$0,65
+   mthi  $2
+   mfhi  $3
+   sb    $3,0($20)
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #d: MTLO
+   ori   $2,$0,'d'
+   sb    $2,0($20)
+   ori   $2,$0,65
+   mtlo  $2
+   mflo  $3
+   sb    $3,0($20)
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+
+   ######################################
+   #Shift Instructions
+   ######################################
+ShiftTest:
+   ori   $2,$0,'S'
+   sb    $2,0($20)
+   ori   $2,$0,'h'
+   sb    $2,0($20)
+   ori   $2,$0,'i'
+   sb    $2,0($20)
+   ori   $2,$0,'f'
+   sb    $2,0($20)
+   ori   $2,$0,'t'
+   sb    $2,0($20)
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #a: SLL
+   ori   $2,$0,'a'
+   sb    $2,0($20)
+   li    $2,0x40414243
+   sll   $3,$2,8
+   srl   $3,$3,24
+   sb    $3,0($20)
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #b: SLLV
+   ori   $2,$0,'b'
+   sb    $2,0($20)
+   li    $2,0x40414243
+   ori   $3,$0,8
+   sllv  $3,$2,$3
+   srl   $3,$3,24
+   sb    $3,0($20)
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #c: SRA
+   ori   $2,$0,'c'
+   sb    $2,0($20)
+   li    $2,0x40414243
+   sra   $3,$2,16
+   sb    $3,0($20)
+   li    $2,0x84000000
+   sra   $3,$2,25
+   sub   $3,$3,0x80
+   sb    $3,0($20)
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #d: SRAV
+   ori   $2,$0,'d'
+   sb    $2,0($20)
+   li    $2,0x40414243
+   ori   $3,$0,16
+   srav  $3,$2,$3
+   sb    $3,0($20)
+   ori   $3,$0,25
+   li    $2,0x84000000
+   srav  $3,$2,$3
+   sub   $3,$3,0x80
+   sb    $3,0($20)
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #e: SRL
+   ori   $2,$0,'e'
+   sb    $2,0($20)
+   li    $2,0x40414243
+   srl   $3,$2,16
+   sb    $3,0($20)
+   li    $2,0x84000000
+   srl   $3,$2,25
+   sb    $3,0($20)
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+   #f: SRLV
+   ori   $2,$0,'f'
+   sb    $2,0($20)
+   li    $2,0x40414243
+   ori   $3,$0,16
+   srlv  $4,$2,$3
+   sb    $4,0($20)
+   ori   $3,$0,25
+   li    $2,0x84000000
+   srlv  $3,$2,$3
+   sb    $3,0($20)
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+
+   ori   $2,$0,'D'
+   sb    $2,0($20)
+   ori   $2,$0,'o'
+   sb    $2,0($20)
+   ori   $2,$0,'n'
+   sb    $2,0($20)
+   ori   $2,$0,'e'
+   sb    $2,0($20)
+   sb    $23,0($20)
+   sb    $21,0($20)
+
+
+$DONE:
+   j     $DONE
+   nop
+
+   .set reorder
+       .end    entry
+
diff --git a/tools/output.txt b/tools/output.txt
new file mode 100644 (file)
index 0000000..bfc4302
--- /dev/null
@@ -0,0 +1,43 @@
+12345678 091a2b3c 048d159e 02468acf 01234567 0091a2b3 0048d159 002468ac 
+00123456 00091a2b 00048d15 0002468a 00012345 000091a2 000048d1 00002468 
+00001234 0000091a 0000048d 00000246 00000123 00000091 00000048 00000024 
+00000012 00000009 00000004 00000002 00000001 00000000 00000000 00000000 
+
+92345678 c91a2b3c e48d159e f2468acf f9234567 fc91a2b3 fe48d159 ff2468ac 
+ff923456 ffc91a2b ffe48d15 fff2468a fff92345 fffc91a2 fffe48d1 ffff2468 
+ffff9234 ffffc91a ffffe48d fffff246 fffff923 fffffc91 fffffe48 ffffff24 
+ffffff92 ffffffc9 ffffffe4 fffffff2 fffffff9 fffffffc fffffffe ffffffff 
+
+12345678 2468acf0 48d159e0 91a2b3c0 23456780 468acf00 8d159e00 1a2b3c00 
+34567800 68acf000 d159e000 a2b3c000 45678000 8acf0000 159e0000 2b3c0000 
+56780000 acf00000 59e00000 b3c00000 67800000 cf000000 9e000000 3c000000 
+78000000 f0000000 e0000000 c0000000 80000000 00000000 00000000 00000000 
+
+
+0 7 14 21 28 35 42 49 56 63 70 
+038f5ae5 038f5e06 038f6127 038f6448 038f6769 038f6a8a 
+05fb4e83 060091a4 0605d4c5 060b17e6 06105b07 06159e28 
+00012345 000091a2 00006117 000048d1 00003a41 0000308b 0000299c 00002468 
+0000205d 
+00000000 00000001 00000000 00000001 00000000 00000003 00000001 00000005 
+00000000 
+
+00001234 00001235 00001236 00001237 00001238 00001239 0000123a 0000123b 
+0000123c 0000123d 
+00001234 00001233 00001232 00001231 00001230 0000122f 0000122e 0000122d 
+0000122c 0000122b 
+
+00000220 00005335 00005115 ffffedcb 00001246 00001222
+
+0 0 0
+1 1 1
+2 2 2
+3 3 3
+4 4 4
+5 5 5
+6 6 6
+7 7 7
+8 8 8
+9 9 9
+
+3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101
diff --git a/tools/pi.c b/tools/pi.c
new file mode 100644 (file)
index 0000000..b201622
--- /dev/null
@@ -0,0 +1,35 @@
+/*Calculate the value of PI.  Takes a long time!*/
+#ifndef WIN32
+int putchar(char ch)
+{
+   *(int*)0x20000000 = ch;
+   return 0;
+}
+
+void OS_InterruptServiceRoutine(unsigned int status)
+{
+   (void)status;
+}
+#endif
+
+void print_num(unsigned long num)
+{
+   unsigned long digit,offset;
+   for(offset=1000;offset;offset/=10) {
+      digit=num/offset;
+      putchar(digit+'0');
+      num-=digit*offset;
+   }
+}
+
+long a=10000,b,c=56,d,e,f[57],g;
+int main()
+{
+   long a5=a/5;
+   for(;b-c;) f[b++]=a5;
+   for(;d=0,g=c*2;c-=14,print_num(e+d/a),e=d%a)for(b=c;d+=f[b]*a,
+     f[b]=d%--g,d/=g--,--b;d*=b);
+   putchar('\n');
+   return 0;
+}
+
diff --git a/tools/plasma.h b/tools/plasma.h
new file mode 100644 (file)
index 0000000..4dc73cb
--- /dev/null
@@ -0,0 +1,52 @@
+/*--------------------------------------------------------------------
+ * TITLE: Plasma Hardware Defines
+ * AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
+ * DATE CREATED: 12/17/05
+ * FILENAME: plasma.h
+ * PROJECT: Plasma CPU core
+ * COPYRIGHT: Software placed into the public domain by the author.
+ *    Software 'as is' without warranty.  Author liable for nothing.
+ * DESCRIPTION:
+ *    Plasma Hardware Defines
+ *--------------------------------------------------------------------*/
+#ifndef __PLASMA_H__
+#define __PLASMA_H__
+
+/*********** Hardware addesses ***********/
+#define RAM_INTERNAL_BASE 0x00000000 //8KB
+#define RAM_EXTERNAL_BASE 0x10000000 //1MB
+#define RAM_EXTERNAL_SIZE 0x00100000
+#define MISC_BASE         0x20000000
+#define UART_WRITE        0x20000000
+#define UART_READ         0x20000000
+#define IRQ_MASK          0x20000010
+#define IRQ_STATUS        0x20000020
+#define GPIO0_OUT         0x20000030
+#define GPIO0_CLEAR       0x20000040
+#define GPIOA_IN          0x20000050
+#define COUNTER_REG       0x20000060
+#define ETHERNET_REG      0x20000070
+#define FLASH_BASE        0x30000000
+
+/*********** GPIO out bits ***************/
+#define ETHERNET_MDIO     0x00200000
+#define ETHERNET_MDIO_WE  0x00400000
+#define ETHERENT_MDC      0x00800000
+#define ETHERNET_ENABLE   0x01000000
+
+/*********** Interrupt bits **************/
+#define IRQ_UART_READ_AVAILABLE  0x01
+#define IRQ_UART_WRITE_AVAILABLE 0x02
+#define IRQ_COUNTER18_NOT        0x04
+#define IRQ_COUNTER18            0x08
+#define IRQ_ETHERNET_RECEIVE     0x10
+#define IRQ_ETHERNET_TRANSMIT    0x20
+#define IRQ_GPIO31_NOT           0x40
+#define IRQ_GPIO31               0x80
+
+/*********** Ethernet buffers ************/
+#define ETHERNET_RECEIVE  0x13ff0000
+#define ETHERNET_TRANSMIT 0x13fe0000
+
+#endif //__PLASMA_H__
+
diff --git a/tools/ram_image.c b/tools/ram_image.c
new file mode 100644 (file)
index 0000000..e831459
--- /dev/null
@@ -0,0 +1,133 @@
+/* ram_image.c by Steve Rhoads 11/7/05 \r
+ * This program take the ram_xilinx.vhd file as input\r
+ * and the code.txt file as input.\r
+ * It then creates ram_image.vhd as output with the\r
+ * initialization vectors set to the contents of code.txt.\r
\r
+ UPDATED: 09/07/10 Olivier Rinaudo (orinaudo@gmail.com)\r
+ new behaviour: 8KB expandable to 64KB of internal RAM\r
+ to be used with new ram_image.vhd enabling expandable \r
+ internal ram.\r
+ */\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+\r
+//1MB buffer\r
+#define BUF_SIZE (1024*1024)\r
+//we have (up to) 8 blocks composed by 4 RAMB16_S9 instance (one per byte)\r
+//each RAMB have 64 hex rows -> max=8*4*64\r
+#define RAM_BLOCKS (8)\r
+#define RAM_SPLIT (4)\r
+#define RAM_ROWS (64)\r
+#define RAM_ROWS_TOTAL (RAM_BLOCKS*RAM_SPLIT*RAM_ROWS)\r
+#define RAM_DWORDPERROW (8)\r
+\r
+\r
+int main(int argc, char *argv[])\r
+{\r
+   FILE *file;\r
+   int i, iposinrow, iblock, irowinsplit, index, size, count;\r
+   char *buf, *ptr, *ptr_list[RAM_ROWS_TOTAL], text[80];\r
+   unsigned int *code;\r
+\r
+   if(argc < 4)\r
+   {\r
+      printf("Usage: ram_image <in.vhd> <in_code.txt> <out.vhd>\n");\r
+      printf("Usage: ram_image ram_xilinx.vhd code.txt ram_image.vhd\n");\r
+      return 0;\r
+   }\r
+\r
+   buf = (char*)malloc(BUF_SIZE);\r
+   code = (unsigned int*)malloc(BUF_SIZE);\r
+\r
+   //Read ram_xilinx.vhd\r
+   file = fopen(argv[1], "rb");\r
+   if(file == NULL)\r
+   {\r
+      printf("Can't open '%s'!\n", argv[1]);\r
+      return -1;\r
+   }\r
+   size = fread(buf, 1, BUF_SIZE, file);\r
+   fclose(file);\r
+\r
+   //Read code.txt\r
+   file = fopen(argv[2], "r");\r
+   if(file == NULL)\r
+   {\r
+      printf("Can't open '%s'!\n", argv[2]);\r
+      return -1;\r
+   }\r
+   //store DWORDs in code buffer\r
+   for(count = 0; count < RAM_ROWS_TOTAL*RAM_DWORDPERROW; ++count)\r
+   {\r
+      if(feof(file))\r
+      {  \r
+         count--;\r
+         break;\r
+      }   \r
+      fscanf(file, "%x", &code[count]);\r
+   }\r
+   fclose(file);\r
+\r
+   //Find 'INIT_00 => X"'\r
+   \r
+   //start at buf, then seek next occurence\r
+   ptr = buf;\r
+   for(i = 0; i < RAM_ROWS_TOTAL; ++i)\r
+   {\r
+      sprintf(text, "INIT_%2.2X => X\"", i % RAM_ROWS);\r
+      ptr = strstr(ptr, text);\r
+      if(ptr == NULL)\r
+      {\r
+         printf("ERROR: Can't find '%s', block %d, instance %d in '%s'!\n",\r
+            text, (i/(RAM_SPLIT*RAM_ROWS)),\r
+            (i%(RAM_SPLIT*RAM_ROWS))/RAM_ROWS, argv[1]);\r
+         return -1;\r
+      }\r
+      ptr_list[i] = ptr + strlen(text);\r
+   }\r
+\r
+   //Modify vhdl source code\r
+   iposinrow = RAM_DWORDPERROW*8-2; //start filling from end of line\r
+   iblock = 0;\r
+   irowinsplit = 0;\r
+   for(i = 0; i < count; ++i)\r
+   {\r
+      sprintf(text, "%8.8x", code[i]);\r
+      index = iblock*RAM_ROWS*RAM_SPLIT+irowinsplit; \r
+\r
+      ptr_list[index][iposinrow]              = text[0];\r
+      ptr_list[index][iposinrow+1]            = text[1];\r
+      ptr_list[index+RAM_ROWS][iposinrow]     = text[2];\r
+      ptr_list[index+RAM_ROWS][iposinrow+1]   = text[3];\r
+      ptr_list[index+RAM_ROWS*2][iposinrow]   = text[4];\r
+      ptr_list[index+RAM_ROWS*2][iposinrow+1] = text[5];\r
+      ptr_list[index+RAM_ROWS*3][iposinrow]   = text[6];\r
+      ptr_list[index+RAM_ROWS*3][iposinrow+1] = text[7];\r
+      iposinrow -= 2;\r
+      if(iposinrow < 0)\r
+      { \r
+        iposinrow = RAM_DWORDPERROW*8-2; //reset row\r
+        irowinsplit++;\r
+        if (irowinsplit>RAM_ROWS-1)\r
+        { \r
+          irowinsplit = 0;\r
+          iblock++;\r
+        }\r
+      } \r
+   }\r
+\r
+   //Write ram_image.vhd\r
+   file = fopen(argv[3], "wb");\r
+   if(file == NULL)\r
+   {\r
+      printf("Can't write '%s'!\n", argv[3]);\r
+      return -1;\r
+   }\r
+   fwrite(buf, 1, size, file);\r
+   fclose(file);\r
+   free(buf);\r
+   free(code);\r
+   return 0;\r
+}\r
diff --git a/tools/test.c b/tools/test.c
new file mode 100644 (file)
index 0000000..d1fa625
--- /dev/null
@@ -0,0 +1,237 @@
+/*-------------------------------------------------------------------\r
+-- TITLE: Plasma CPU test code\r
+-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)\r
+-- DATE CREATED: 4/21/01\r
+-- FILENAME: test.c\r
+-- PROJECT: Plasma CPU core\r
+-- COPYRIGHT: Software placed into the public domain by the author.\r
+--    Software 'as is' without warranty.  Author liable for nothing.\r
+-- DESCRIPTION:\r
+--   The executable image of this file is used as input to the VHDL.\r
+--\r
+--   This file must not contain any global or static data since\r
+--   there isn't a loader to relocate the .data segment and since\r
+--   having static data causes the opcodes to begin at a different\r
+--   location in the resulting executable file.\r
+--\r
+--   Save the opcodes in "code.txt".\r
+--\r
+--   Testing subversion.\r
+--------------------------------------------------------------------*/\r
+#ifndef WIN32\r
+#undef putchar\r
+#define putchar(C) *(volatile unsigned char*)0x20000000=(unsigned char)(C)\r
+#endif\r
+\r
+void print_hex(unsigned long num);\r
+\r
+char text[]="Testing the Plasma core.\n";\r
+char buf[20];\r
+int xyz=0xbadbeef;\r
+int abc;\r
+\r
+char *strcpy2(char *s, const char *t)\r
+{\r
+   char *tmp=s;\r
+   while((int)(*s++=*t++)) ;\r
+   return(tmp);\r
+}\r
+\r
+static void itoa2(long n, char *s, int base, long *digits)\r
+{\r
+   long i,j,sign;\r
+   unsigned long n2;\r
+   char number[20];\r
+   for(i=0;i<15;++i) {\r
+      number[i]=' ';\r
+   }\r
+   number[15]=0;\r
+   if(n>=0||base!=10) {\r
+      sign=1;\r
+   } else {\r
+      sign=-1;\r
+   }\r
+   n2=n*sign;\r
+   for(j=14;j>=0;--j) {\r
+      i=n2%base;\r
+      n2/=base;\r
+      number[j]=i<10?'0'+i:'a'+i-10;\r
+      if(n2==0&&15-j>=*digits) break;\r
+   } \r
+   if(sign==-1) {\r
+      number[--j]='-';\r
+   }\r
+   if(*digits==0||*digits<15-j) {\r
+      strcpy2(s,&number[j]);\r
+      *digits=15-j;\r
+   } else {\r
+      strcpy2(s,&number[15-*digits]);\r
+   }\r
+}\r
+\r
+void print(long num,long base,long digits)\r
+{\r
+   char *ptr,buffer[128];\r
+   itoa2(num,buffer,base,&digits);\r
+   ptr=buffer;\r
+   while(*ptr) {\r
+      putchar(*ptr++);          /* Put the character out */\r
+      if(ptr[-1]=='\n') *--ptr='\r';\r
+   }\r
+}              \r
+\r
+void print_string(char *p)\r
+{\r
+   int i;\r
+   for(i=0;p[i];++i) {\r
+      putchar(p[i]);\r
+   }\r
+}\r
+\r
+int prime()\r
+{\r
+   int i,j;\r
+   //show all prime numbers less than 1000\r
+   for(i=3;i<1000;i+=2) {\r
+      for(j=3;j<i;j+=2) {\r
+         if(i%j==0) {\r
+            j=0;\r
+            break;\r
+         }\r
+      }\r
+      if(j) {\r
+         print(i,10,0);\r
+         putchar(' ');\r
+      }\r
+   }\r
+   putchar('\n');\r
+   return 0;\r
+}\r
+\r
+int main(void)\r
+{\r
+   long i,j;\r
+   char char_buf[16];\r
+   short short_buf[16];\r
+   long long_buf[16];\r
+\r
+#if 1 \r
+   //test shift\r
+   j=0x12345678;\r
+   for(i=0;i<32;++i) {\r
+      print_hex(j>>i);\r
+      putchar(' ');\r
+   }\r
+   putchar('\n');\r
+   j=0x92345678;\r
+   for(i=0;i<32;++i) {\r
+      print_hex(j>>i);\r
+      putchar(' ');\r
+   }\r
+   putchar('\n');\r
+   j=0x12345678;\r
+   for(i=0;i<32;++i) {\r
+      print_hex(j<<i);\r
+      putchar(' ');\r
+   }\r
+   putchar('\n');\r
+   putchar('\n');\r
+#endif\r
+  \r
+#if 1 \r
+   //test multiply and divide\r
+   j=7;\r
+   for(i=0;i<=10;++i) {\r
+      print(j*i,10,0);\r
+      putchar(' ');\r
+   }\r
+   putchar('\n');\r
+   j=0x321;\r
+   for(i=0;i<=5;++i) {\r
+      print_hex(j*(i+0x12345));\r
+      putchar(' ');\r
+   }\r
+   putchar('\n');\r
+   j=0x54321;\r
+   for(i=0;i<=5;++i) {\r
+      print_hex(j*(i+0x123));\r
+      putchar(' ');\r
+   }\r
+   putchar('\n');\r
+   j=0x12345;\r
+   for(i=1;i<10;++i) {\r
+      print_hex(j/i);\r
+      putchar(' ');\r
+   }\r
+   putchar('\n');\r
+   for(i=1;i<10;++i) {\r
+      print_hex(j%i);\r
+      putchar(' ');\r
+   }\r
+   putchar('\n');\r
+   putchar('\n');\r
+#endif\r
+\r
+#if 1\r
+   //test addition and subtraction\r
+   j=0x1234;\r
+   for(i=0;i<10;++i) {\r
+      print_hex(j+i);\r
+      putchar(' ');\r
+   }\r
+   putchar('\n');\r
+   for(i=0;i<10;++i) {\r
+      print_hex(j-i);\r
+      putchar(' ');\r
+   }\r
+   putchar('\n');\r
+   putchar('\n');\r
+#endif\r
+  \r
+#if 1 \r
+   //test bit operations\r
+   i=0x1234;\r
+   j=0x4321;\r
+   print_hex(i&j);\r
+   putchar(' ');\r
+   print_hex(i|j);\r
+   putchar(' ');\r
+   print_hex(i^j);\r
+   putchar(' ');\r
+   print_hex(~i);\r
+   putchar(' ');\r
+   print_hex(i+0x12);\r
+   putchar(' ');\r
+   print_hex(i-0x12);\r
+   putchar('\n');\r
+   putchar('\n');\r
+#endif\r
+  \r
+#if 1 \r
+   //test memory access\r
+   for(i=0;i<10;++i) {\r
+      char_buf[i]=i;\r
+      short_buf[i]=i;\r
+      long_buf[i]=i;\r
+   }\r
+   for(i=0;i<10;++i) {\r
+      j=char_buf[i];\r
+      print(j,10,0);\r
+      putchar(' ');\r
+      j=short_buf[i];\r
+      print(j,10,0);\r
+      putchar(' ');\r
+      j=long_buf[i];\r
+      print(j,10,0);\r
+      putchar('\n');\r
+   }\r
+   putchar('\n');\r
+#endif\r
+   \r
+   prime();\r
+   \r
+   putchar('d'); putchar('o'); putchar('n'); putchar('e'); putchar('\n');\r
+\r
+   for(;;) ;\r
+}\r
+\r
diff --git a/tools/tracehex.c b/tools/tracehex.c
new file mode 100644 (file)
index 0000000..880ecc2
--- /dev/null
@@ -0,0 +1,177 @@
+/***********************************************************
+| tracehex by Steve Rhoads 12/25/01
+| This tool modifies trace files from the free VHDL simulator 
+| http://www.symphonyeda.com/.
+| The binary numbers are converted to hex values.
+************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#define BUF_SIZE (1024*1024*4)
+#define LINE_SIZE 10000
+
+char drop_char[10000];
+
+int main(int argc, char *argv[])
+{
+   FILE *file;
+   char *buf,*ptr_in,*ptr_out,*line_store,*line;
+   char *line_start,*source_start;
+   int bytes,digits,value,isbinary,col,col_num,row,drop_cnt;
+   int col_index,line_index,back_count,drop_start=0;
+   int digits_length=0;
+   (void)argc;
+   (void)argv;
+
+   printf("tracehex\n");
+
+   /* Reading trace.txt */
+   file=fopen("trace.txt","r");
+   if(file==NULL) {
+      printf("Can't open file\n");
+      return -1;
+   }
+   line_store=(char*)malloc(LINE_SIZE);
+   line_store[0]=' ';
+   line=line_store+1;
+   buf=(char*)malloc(BUF_SIZE*2);
+   if(buf==NULL) {
+      printf("Can't malloc!\n");
+      return -1;
+   }
+   ptr_out=buf+BUF_SIZE;
+   bytes=fread(buf,1,BUF_SIZE-1,file);
+   buf[bytes]=0;
+   fclose(file);
+
+   digits=0;
+   value=0;
+   isbinary=0;
+   col=0;
+   col_num=0;
+   row=0;
+   line_start=ptr_out;
+   source_start=buf;
+   for(ptr_in=strstr(buf,"=");*ptr_in;++ptr_in) {
+      ++col;
+      if(drop_start==0&&*ptr_in==' ') {
+         for(drop_start=3;drop_start<30;++drop_start) {
+            if(ptr_in[drop_start]!=' ') {
+               break;
+            }
+         }
+         for(;drop_start<30;++drop_start) {
+            if(ptr_in[drop_start]==' ') {
+               break;
+            }
+         }
+         drop_start-=2;
+      }
+      if(col<4) {
+         drop_char[col]=1;
+         continue;
+      }
+      if(drop_start<=col&&col<=drop_start+2) {
+         drop_char[col]=1;
+         continue;
+      }
+      if(col<drop_start) {
+         *ptr_out++=*ptr_in;
+         continue;
+      }
+      
+      /* convert binary number to hex */
+      if(isbinary&&(*ptr_in=='0'||*ptr_in=='1')) {
+         value=value*2+*ptr_in-'0';
+         ++digits;
+         drop_char[col_num++]=1;
+      } else if(isbinary&&*ptr_in=='Z') {
+         value=1000;
+         ++digits;
+         drop_char[col_num++]=1;
+      } else if(isbinary&&(*ptr_in=='U'||*ptr_in=='X')) {
+         value=10000;
+         ++digits;
+         drop_char[col_num++]=1;
+      } else {
+         if(*ptr_in=='\n') {
+            col=0;
+            isbinary=0;
+            ++row;
+         }
+         if(isspace(*ptr_in)) {
+            if(col>10) {
+               isbinary=1;
+               col_num=col;
+               for(digits_length=1;!isspace(ptr_in[digits_length]);++digits_length) ;
+               --digits_length;
+            }
+         } else {
+            isbinary=0;
+         }
+         *ptr_out++=*ptr_in;
+         digits=0;
+         value=0;
+      }
+      /* convert every four binary digits to a hex digit */
+      if(digits&&(digits_length%4)==0) {
+         drop_char[--col_num]=0;
+         if(value<100) {
+            *ptr_out++=value<10?value+'0':value-10+'A';
+         } else if(value<5000) {
+            *ptr_out++='Z';
+         } else {
+            *ptr_out++='U';
+         }
+         digits=0;
+         value=0;
+      }
+      --digits_length;
+   }
+   *ptr_out=0;
+
+   /* now process the header */
+   file=fopen("trace2.txt","w");
+   col=0;
+   line[0]=0;
+   for(ptr_in=buf;*ptr_in;++ptr_in) {
+      if(*ptr_in=='=') {
+         break;
+      }
+      line[col++]=*ptr_in;
+      if(*ptr_in=='\n') {
+         line[col]=0;
+         line_index=0;
+         for(col_index=0;col_index<col;++col_index) {
+            if(drop_char[col_index]) {
+               back_count=0;
+               while(line[line_index-back_count]!=' '&&back_count<10) {
+                  ++back_count;
+               }
+               if(line[line_index-back_count-1]!=' ') {
+                  --back_count;
+               }
+               strcpy(line+line_index-back_count,line+line_index-back_count+1);
+            } else {
+               ++line_index;
+            }
+         }
+         fprintf(file,"%s",line);
+         col=0;
+      }
+   }
+   drop_cnt=0;
+   for(col_index=13;col_index<sizeof(drop_char);++col_index) {
+      if(drop_char[col_index]) {
+         ++drop_cnt;
+      }
+   }
+   fprintf(file,"%s",buf+BUF_SIZE+drop_cnt);
+
+   fclose(file);
+   free(line_store);
+   free(buf);
+   return 0;
+}
diff --git a/vhdl/alu.vhd b/vhdl/alu.vhd
new file mode 100644 (file)
index 0000000..df7599b
--- /dev/null
@@ -0,0 +1,61 @@
+---------------------------------------------------------------------
+-- TITLE: Arithmetic Logic Unit
+-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
+-- DATE CREATED: 2/8/01
+-- FILENAME: alu.vhd
+-- PROJECT: Plasma CPU core
+-- COPYRIGHT: Software placed into the public domain by the author.
+--    Software 'as is' without warranty.  Author liable for nothing.
+-- DESCRIPTION:
+--    Implements the ALU.
+---------------------------------------------------------------------
+library ieee;
+use ieee.std_logic_1164.all;
+use work.mlite_pack.all;
+
+entity alu is
+   generic(alu_type  : string := "DEFAULT");
+   port(a_in         : in  std_logic_vector(31 downto 0);
+        b_in         : in  std_logic_vector(31 downto 0);
+        alu_function : in  alu_function_type;
+        c_alu        : out std_logic_vector(31 downto 0));
+end; --alu
+
+architecture logic of alu is
+   signal do_add    : std_logic;
+   signal sum       : std_logic_vector(32 downto 0);
+   signal less_than : std_logic;
+begin
+
+   do_add <= '1' when alu_function = ALU_ADD else '0';
+   sum <= bv_adder(a_in, b_in, do_add);
+   less_than <= sum(32) when a_in(31) = b_in(31) or alu_function = ALU_LESS_THAN 
+                else a_in(31);
+
+   GENERIC_ALU: if alu_type = "DEFAULT" generate
+      c_alu <= sum(31 downto 0) when alu_function=ALU_ADD or
+                                              alu_function=ALU_SUBTRACT else
+               ZERO(31 downto 1) & less_than when alu_function=ALU_LESS_THAN or 
+                                alu_function=ALU_LESS_THAN_SIGNED else
+               a_in or  b_in    when alu_function=ALU_OR else
+               a_in and b_in    when alu_function=ALU_AND else
+               a_in xor b_in    when alu_function=ALU_XOR else
+               a_in nor b_in    when alu_function=ALU_NOR else
+               ZERO;
+   end generate;
+
+   AREA_OPTIMIZED_ALU: if alu_type/="DEFAULT" generate
+      c_alu <= sum(31 downto 0) when alu_function=ALU_ADD or 
+                                         alu_function=ALU_SUBTRACT else (others => 'Z');
+      c_alu <= ZERO(31 downto 1) & less_than when alu_function=ALU_LESS_THAN or 
+                                         alu_function=ALU_LESS_THAN_SIGNED else 
+                                                                                 (others => 'Z');
+      c_alu <= a_in or  b_in    when alu_function=ALU_OR else (others => 'Z');
+      c_alu <= a_in and b_in    when alu_function=ALU_AND else (others => 'Z');
+      c_alu <= a_in xor b_in    when alu_function=ALU_XOR else (others => 'Z');
+      c_alu <= a_in nor b_in    when alu_function=ALU_NOR else (others => 'Z');
+      c_alu <= ZERO             when alu_function=ALU_NOTHING else (others => 'Z');
+   end generate;
+    
+end; --architecture logic
+
diff --git a/vhdl/build_dir/ISE_scripts/.svn/all-wcprops b/vhdl/build_dir/ISE_scripts/.svn/all-wcprops
new file mode 100644 (file)
index 0000000..842ad96
--- /dev/null
@@ -0,0 +1,23 @@
+K 25
+svn:wc:ra_dav:version-url
+V 66
+/ocsvn/plasma/!svn/ver/371/plasma/trunk/vhdl/build_dir/ISE_scripts
+END
+makeprom.cmds
+K 25
+svn:wc:ra_dav:version-url
+V 80
+/ocsvn/plasma/!svn/ver/371/plasma/trunk/vhdl/build_dir/ISE_scripts/makeprom.cmds
+END
+loadprom.cmds
+K 25
+svn:wc:ra_dav:version-url
+V 80
+/ocsvn/plasma/!svn/ver/371/plasma/trunk/vhdl/build_dir/ISE_scripts/loadprom.cmds
+END
+main.scrs
+K 25
+svn:wc:ra_dav:version-url
+V 76
+/ocsvn/plasma/!svn/ver/371/plasma/trunk/vhdl/build_dir/ISE_scripts/main.scrs
+END
diff --git a/vhdl/build_dir/ISE_scripts/.svn/entries b/vhdl/build_dir/ISE_scripts/.svn/entries
new file mode 100644 (file)
index 0000000..4afaab3
--- /dev/null
@@ -0,0 +1,130 @@
+10
+
+dir
+397
+http://opencores.org/ocsvn/plasma/plasma/trunk/vhdl/build_dir/ISE_scripts
+http://opencores.org/ocsvn/plasma
+
+
+
+2009-09-19T14:27:52.013014Z
+371
+rhoads
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+8fa3edc1-71da-4d9b-a61a-8b20347ad903
+\f
+makeprom.cmds
+file
+
+
+
+
+2011-02-13T19:50:04.000000Z
+742e945d0e311b859783e976a933792f
+2009-09-19T14:27:52.013014Z
+371
+rhoads
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+227
+\f
+loadprom.cmds
+file
+
+
+
+
+2011-02-13T19:50:04.000000Z
+eb02daa158e0488719dacaa14047ce1d
+2009-09-19T14:27:52.013014Z
+371
+rhoads
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+106
+\f
+main.scrs
+file
+
+
+
+
+2011-02-13T19:50:04.000000Z
+2a2930a7a56192b5a15054584820bf1b
+2009-09-19T14:27:52.013014Z
+371
+rhoads
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+101
+\f
diff --git a/vhdl/build_dir/ISE_scripts/.svn/text-base/loadprom.cmds.svn-base b/vhdl/build_dir/ISE_scripts/.svn/text-base/loadprom.cmds.svn-base
new file mode 100644 (file)
index 0000000..0803e2e
--- /dev/null
@@ -0,0 +1,6 @@
+setMode -bscan
+setCable -p auto
+identify
+assignFile -p 2 -file generated/main.mcs
+program -e -p 2 -v
+quit
diff --git a/vhdl/build_dir/ISE_scripts/.svn/text-base/main.scrs.svn-base b/vhdl/build_dir/ISE_scripts/.svn/text-base/main.scrs.svn-base
new file mode 100644 (file)
index 0000000..c58f9b9
--- /dev/null
@@ -0,0 +1,7 @@
+run
+-ifn main.prj
+-ifmt VHDL
+-ofn main.ngc
+-ofmt NGC -p XC3S500E-FG320-4
+-opt_mode Area
+-opt_level 2
diff --git a/vhdl/build_dir/ISE_scripts/.svn/text-base/makeprom.cmds.svn-base b/vhdl/build_dir/ISE_scripts/.svn/text-base/makeprom.cmds.svn-base
new file mode 100644 (file)
index 0000000..e484f0a
--- /dev/null
@@ -0,0 +1,8 @@
+setMode -pff
+setSubmode -pffserial
+addPromDevice -p 1 -name xcf04s
+addDesign -version 0 -name 0
+addDeviceChain -index 0
+addDevice -p 1 -file generated/main.bit
+generate -format mcs -fillvalue FF -output generated/main.mcs
+quit
diff --git a/vhdl/build_dir/ISE_scripts/loadprom.cmds b/vhdl/build_dir/ISE_scripts/loadprom.cmds
new file mode 100644 (file)
index 0000000..0803e2e
--- /dev/null
@@ -0,0 +1,6 @@
+setMode -bscan
+setCable -p auto
+identify
+assignFile -p 2 -file generated/main.mcs
+program -e -p 2 -v
+quit
diff --git a/vhdl/build_dir/ISE_scripts/main.scrs b/vhdl/build_dir/ISE_scripts/main.scrs
new file mode 100644 (file)
index 0000000..c58f9b9
--- /dev/null
@@ -0,0 +1,7 @@
+run
+-ifn main.prj
+-ifmt VHDL
+-ofn main.ngc
+-ofmt NGC -p XC3S500E-FG320-4
+-opt_mode Area
+-opt_level 2
diff --git a/vhdl/build_dir/ISE_scripts/makeprom.cmds b/vhdl/build_dir/ISE_scripts/makeprom.cmds
new file mode 100644 (file)
index 0000000..e484f0a
--- /dev/null
@@ -0,0 +1,8 @@
+setMode -pff
+setSubmode -pffserial
+addPromDevice -p 1 -name xcf04s
+addDesign -version 0 -name 0
+addDeviceChain -index 0
+addDevice -p 1 -file generated/main.bit
+generate -format mcs -fillvalue FF -output generated/main.mcs
+quit
diff --git a/vhdl/build_dir/Makefile b/vhdl/build_dir/Makefile
new file mode 100644 (file)
index 0000000..5ffd488
--- /dev/null
@@ -0,0 +1,144 @@
+# Makefile for Plasma on the s3Esk\r
+# For Linux development environment using free GHDL simulator and\r
+# Xilinx synthesis tools.\r
+# Derives from the DDRSDRAM-on-s3Esk makefile\r
+#\r
+# This makefile was created by me, Dan Clemmensen. I hereby place it in\r
+# the public domain, releasing any rights. I retain the right to re-use\r
+# this work as the basis for a derived work.\r
+#\r
+# Use GHDL for simulation, and then use the Xilinx tools in batch mode for\r
+# synthesis and download. \r
+# Before you use this makefile for the first time, you will need to build \r
+# the plasma tools.  After that, you can do the rest of the development \r
+# using this makefile, unless you change a tool.\r
+# Place this makefile and the associated ISE_scripts directory in a \r
+# subdirectory of the VHDL directory.  We use this approach because the Xilinx\r
+# tools create a large number of temporary files in the working directory.\r
+#\r
+# Usage:\r
+# make clean    # removes derived files and directories \r
+# make load     # builds everthing from scratch and \r
+#               #   loads the flash mem on the target\r
+# make simtest  # builds and runs as a GHDL simulation\r
+# make view     # displays the results of the simulation\r
+\r
+# To help isolate problems, you may run a series of steps instead of the whole\r
+# "make load." Look below to see them.\r
+\r
+# VHDL_DIR is the top-level VHDL directory for Plasma. \r
+VHDL_DIR = ..\r
+# PROJ_VHDL comprises files used in both the actual target and the sim\r
+PROJ_VHDL = \\r
+      $(VHDL_DIR)/mlite_pack.vhd \\r
+      $(VHDL_DIR)/plasma_3e.vhd \\r
+      $(VHDL_DIR)/ddr_ctrl.vhd \\r
+      $(VHDL_DIR)/plasma.vhd \\r
+      generated/ram_image.vhd \\r
+      $(VHDL_DIR)/uart.vhd \\r
+      $(VHDL_DIR)/eth_dma.vhd \\r
+      $(VHDL_DIR)/mlite_cpu.vhd \\r
+      $(VHDL_DIR)/alu.vhd \\r
+      $(VHDL_DIR)/bus_mux.vhd \\r
+      $(VHDL_DIR)/control.vhd \\r
+      $(VHDL_DIR)/mem_ctrl.vhd \\r
+      $(VHDL_DIR)/mult.vhd \\r
+      $(VHDL_DIR)/pipeline.vhd \\r
+      $(VHDL_DIR)/pc_next.vhd \\r
+      $(VHDL_DIR)/reg_bank.vhd \\r
+      $(VHDL_DIR)/shifter.vhd \\r
+      $(VHDL_DIR)/cache.vhd\r
+\r
+# TARGET_VHDL comprises files used on the target but not in sim\r
+TARGET_VHDL =\r
+\r
+# SIM_VHDL comprises files used in sim but not on the target\r
+# for this  sim, these simulate the rest of the S3Esk board\r
+SIM_DIR = $(VHDL_DIR)/simulation\r
+SIM_VHDL = \\r
+      $(VHDL_DIR)/mt46v16m16.vhd \\r
+      $(VHDL_DIR)/tbench.vhd\r
+\r
+SIM_TOP = tbench\r
+GCC_PARAMS=\r
+\r
+OBJS = $(VHDL:.vhd=.o)\r
+\r
+# GHDL config\r
+OBJDIR = obj\r
+ISE_DIR=/opt/Xilinx/11.1/ISE\r
+GHDL_LIBS = $(ISE_DIR)/ghdl/unisim\r
+GHDL_FLAGS = --ieee=synopsys -fexplicit -P$(GHDL_LIBS)\r
+GHDL_FLAGS += --workdir=$(OBJDIR) --warn-no-vital-generic\r
+\r
+%.o: %.vhd\r
+       ghdl -a $(GHDL_FLAGS) $<\r
+\r
+all: simtest\r
+\r
+old:  workdir $(OBJS)\r
+\r
+# invocation strings for helper tools to build Xilinx BRAM memory images.\r
+TOOLS = ../../tools\r
+# generate the ram_image.vhd\r
+generated: \r
+       rm -rf generated\r
+       mkdir generated\r
+       $(TOOLS)/ram_image.exe $(VHDL_DIR)/ram_xilinx.vhd $(TOOLS)/code.txt generated/ram_image.vhd\r
+\r
+NAME=main\r
+workdir:\r
+       mkdir -p $(OBJDIR)\r
+\r
+clean:\r
+       rm -rf *.o *.cf $(OBJDIR) tb *.vcd main $(SIM_TOP) *.ghw\r
+       rm -f *.bit *.bgn *_pad.txt *_pad.csv *.xpi *.srp *.ngc *.par\r
+       rm -f *.lst *.ngd *.ngm *.pcf *.mrp *.unroutes *.pad\r
+       rm -f *.bld *.ncd *.twr *.drc\r
+       rm -rf xst $(NAME).prj\r
+       rm -rf generated\r
+\r
+simtest: workdir generated\r
+       ghdl -i $(GHDL_FLAGS) $(PROJ_VHDL) $(SIM_VHDL)\r
+       ghdl -m $(GHDL_FLAGS) $(SIM_TOP)\r
+sim:\r
+       ghdl -r $(SIM_TOP) --stop-time=10ms --wave=generated/out.ghw 2> /dev/null\r
+\r
+view:\r
+       gtkwave generated/out.ghw view.sav\r
+\r
+#Xilinx ISE actions. Uses a wrapper script named "xilinx" to run the ISE batch commands\r
+\r
+# create an ISE project file from the list of VHDL files\r
+$(NAME).prj: $(PROJ_VHDL) $(TARGET_VHDL)\r
+       echo $(PROJ_VHDL) $(TARGET_VHDL)|tr " " "\n">$(NAME).prj\r
+\r
+bitfile:  generated step0 step1 step2 step3 step4 step5\r
+\r
+step0: $(NAME).prj \r
+       xilinx xst -ifn ISE_scripts/$(NAME).scrs -ofn $(NAME).srp\r
+step1:\r
+       xilinx ngdbuild -nt on -uc ../spartan3e.ucf $(NAME).ngc $(NAME).ngd\r
+step2:\r
+       xilinx map -pr b $(NAME).ngd -o $(NAME).ncd $(NAME).pcf\r
+step3:\r
+       xilinx par -w -ol high $(NAME).ncd $(NAME).ncd $(NAME).pcf\r
+step4:\r
+       xilinx trce -v 10 -o $(NAME).twr $(NAME).ncd $(NAME).pcf\r
+step5:\r
+       xilinx bitgen $(NAME).ncd generated/$(NAME).bit -w #-f $(NAME).ut\r
+\r
+generated/main.bit: bitfile\r
+\r
+mcs:  generated/main.bit\r
+       xilinx impact -batch ISE_scripts/makeprom.cmds\r
+\r
+generated/main.mcs: mcs\r
+\r
+load: generated/main.mcs\r
+       xilinx impact -batch ISE_scripts/loadprom.cmds\r
+\r
+impact:\r
+       xilinx impact\r
+ise: $(NAME).prj\r
+       xilinx ise\r
diff --git a/vhdl/bus_mux.vhd b/vhdl/bus_mux.vhd
new file mode 100644 (file)
index 0000000..0d94858
--- /dev/null
@@ -0,0 +1,136 @@
+---------------------------------------------------------------------
+-- TITLE: Bus Multiplexer / Signal Router
+-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
+-- DATE CREATED: 2/8/01
+-- FILENAME: bus_mux.vhd
+-- PROJECT: Plasma CPU core
+-- COPYRIGHT: Software placed into the public domain by the author.
+--    Software 'as is' without warranty.  Author liable for nothing.
+-- DESCRIPTION:
+--    This entity is the main signal router.  
+--    It multiplexes signals from multiple sources to the correct location.
+--    The outputs are as follows:
+--       a_bus        : goes to the ALU
+--       b_bus        : goes to the ALU
+--       reg_dest_out : goes to the register bank
+--       take_branch  : goes to pc_next
+---------------------------------------------------------------------
+library ieee;
+use ieee.std_logic_1164.all;
+use work.mlite_pack.all;
+
+entity bus_mux is
+   port(imm_in       : in  std_logic_vector(15 downto 0);
+        reg_source   : in  std_logic_vector(31 downto 0);
+        a_mux        : in  a_source_type;
+        a_out        : out std_logic_vector(31 downto 0);
+
+        reg_target   : in  std_logic_vector(31 downto 0);
+        b_mux        : in  b_source_type;
+        b_out        : out std_logic_vector(31 downto 0);
+
+        c_bus        : in  std_logic_vector(31 downto 0);
+        c_memory     : in  std_logic_vector(31 downto 0);
+        c_pc         : in  std_logic_vector(31 downto 2);
+        c_pc_plus4   : in  std_logic_vector(31 downto 2);
+        c_mux        : in  c_source_type;
+        reg_dest_out : out std_logic_vector(31 downto 0);
+
+        branch_func  : in  branch_function_type;
+        take_branch  : out std_logic);
+end; --entity bus_mux
+
+architecture logic of bus_mux is
+begin
+
+--Determine value of a_bus
+amux: process(reg_source, imm_in, a_mux, c_pc) 
+begin
+   case a_mux is
+   when A_FROM_REG_SOURCE =>
+      a_out <= reg_source;
+   when A_FROM_IMM10_6 =>
+      a_out <= ZERO(31 downto 5) & imm_in(10 downto 6);
+   when A_FROM_PC =>
+      a_out <= c_pc & "00";
+   when others =>
+      a_out <= c_pc & "00";
+   end case;
+end process;
+
+--Determine value of b_bus
+bmux: process(reg_target, imm_in, b_mux) 
+begin
+   case b_mux is
+   when B_FROM_REG_TARGET =>
+      b_out <= reg_target;
+   when B_FROM_IMM =>
+      b_out <= ZERO(31 downto 16) & imm_in;
+   when B_FROM_SIGNED_IMM =>
+      if imm_in(15) = '0' then
+         b_out(31 downto 16) <= ZERO(31 downto 16);
+      else
+         b_out(31 downto 16) <= "1111111111111111";
+      end if;
+      b_out(15 downto 0) <= imm_in;
+   when B_FROM_IMMX4 =>
+      if imm_in(15) = '0' then
+         b_out(31 downto 18) <= "00000000000000";
+      else
+         b_out(31 downto 18) <= "11111111111111";
+      end if;
+      b_out(17 downto 0) <= imm_in & "00";
+   when others =>
+      b_out <= reg_target;
+   end case;
+end process;
+
+--Determine value of c_bus                                                             
+cmux: process(c_bus, c_memory, c_pc, c_pc_plus4, imm_in, c_mux) 
+begin
+   case c_mux is
+   when C_FROM_ALU =>  -- | C_FROM_SHIFT | C_FROM_MULT =>
+      reg_dest_out <= c_bus;
+   when C_FROM_MEMORY =>
+      reg_dest_out <= c_memory;
+   when C_FROM_PC =>
+      reg_dest_out <= c_pc(31 downto 2) & "00"; 
+   when C_FROM_PC_PLUS4 =>
+      reg_dest_out <= c_pc_plus4 & "00";
+   when C_FROM_IMM_SHIFT16 =>
+      reg_dest_out <= imm_in & ZERO(15 downto 0);
+   when others =>
+      reg_dest_out <= c_bus;
+   end case;
+end process;
+
+--Determine value of take_branch
+pc_mux: process(branch_func, reg_source, reg_target) 
+   variable is_equal : std_logic;
+begin
+   if reg_source = reg_target then
+      is_equal := '1';
+   else
+      is_equal := '0';
+   end if;
+   case branch_func is
+   when BRANCH_LTZ =>
+      take_branch <= reg_source(31);
+   when BRANCH_LEZ =>
+      take_branch <= reg_source(31) or is_equal;
+   when BRANCH_EQ =>
+      take_branch <= is_equal;
+   when BRANCH_NE =>
+      take_branch <= not is_equal;
+   when BRANCH_GEZ =>
+      take_branch <= not reg_source(31);
+   when BRANCH_GTZ =>
+      take_branch <= not reg_source(31) and not is_equal;
+   when BRANCH_YES =>
+      take_branch <= '1';
+   when others =>
+      take_branch <= '0';
+   end case;
+end process;
+
+end; --architecture logic
diff --git a/vhdl/cache.vhd b/vhdl/cache.vhd
new file mode 100644 (file)
index 0000000..e3afc84
--- /dev/null
@@ -0,0 +1,177 @@
+---------------------------------------------------------------------
+-- TITLE: Cache Controller
+-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
+-- DATE CREATED: 12/22/08
+-- FILENAME: cache.vhd
+-- PROJECT: Plasma CPU core
+-- COPYRIGHT: Software placed into the public domain by the author.
+--    Software 'as is' without warranty.  Author liable for nothing.
+-- DESCRIPTION:
+--    Control 4KB unified cache that uses the upper 4KB of the 8KB
+--    internal RAM.  Only lowest 2MB of DDR is cached.
+--    Only include file for Xilinx FPGAs.
+---------------------------------------------------------------------
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+library UNISIM;
+use UNISIM.vcomponents.all;
+use work.mlite_pack.all;
+
+entity cache is
+   generic(memory_type : string := "DEFAULT");
+   port(clk            : in std_logic;
+        reset          : in std_logic;
+        address_next   : in std_logic_vector(31 downto 2);
+        byte_we_next   : in std_logic_vector(3 downto 0);
+        cpu_address    : in std_logic_vector(31 downto 2);
+        mem_busy       : in std_logic;
+
+        cache_access   : out std_logic;   --access 4KB cache
+        cache_checking : out std_logic;   --checking if cache hit
+        cache_miss     : out std_logic);  --cache miss
+end; --cache
+
+architecture logic of cache is
+   subtype state_type is std_logic_vector(1 downto 0);
+   constant STATE_IDLE     : state_type := "00";
+   constant STATE_CHECKING : state_type := "01";
+   constant STATE_MISSED   : state_type := "10";
+   constant STATE_WAITING  : state_type := "11";
+
+   signal state_reg        : state_type;
+   signal state            : state_type;
+   signal state_next       : state_type;
+
+   signal cache_address    : std_logic_vector(10 downto 0);
+   signal cache_tag_in     : std_logic_vector(8 downto 0);
+   signal cache_tag_reg    : std_logic_vector(8 downto 0);
+   signal cache_tag_out    : std_logic_vector(8 downto 0);
+   signal cache_we         : std_logic;
+begin
+
+   cache_proc: process(clk, reset, mem_busy, cache_address, 
+      state_reg, state, state_next, 
+      address_next, byte_we_next, cache_tag_in, --Stage1
+      cache_tag_reg, cache_tag_out,             --Stage2
+      cpu_address) --Stage3
+   begin
+
+      case state_reg is
+      when STATE_IDLE =>            --cache idle
+         cache_checking <= '0';
+         cache_miss <= '0'; 
+         state <= STATE_IDLE;
+      when STATE_CHECKING =>        --current read in cached range, check if match
+         cache_checking <= '1';
+         if cache_tag_out /= cache_tag_reg or cache_tag_out = ONES(8 downto 0) then
+            cache_miss <= '1';
+            state <= STATE_MISSED;
+         else
+            cache_miss <= '0';
+            state <= STATE_IDLE;
+         end if;
+      when STATE_MISSED =>          --current read cache miss
+         cache_checking <= '0';
+         cache_miss <= '1';
+         if mem_busy = '1' then
+            state <= STATE_MISSED;
+         else
+            state <= STATE_WAITING;
+         end if;
+      when STATE_WAITING =>         --waiting for memory access to complete
+         cache_checking <= '0';
+         cache_miss <= '0';
+         if mem_busy = '1' then
+            state <= STATE_WAITING;
+         else
+            state <= STATE_IDLE;
+         end if;
+      when others =>
+         cache_checking <= '0';
+         cache_miss <= '0';
+         state <= STATE_IDLE;
+      end case; --state
+
+      if state = STATE_IDLE then    --check if next access in cached range
+         cache_address <= '0' & address_next(11 downto 2);
+         if address_next(30 downto 21) = "0010000000" then  --first 2MB of DDR
+            cache_access <= '1';
+            if byte_we_next = "0000" then     --read cycle
+               cache_we <= '0';
+               state_next <= STATE_CHECKING;  --need to check if match
+            else
+               cache_we <= '1';               --update cache tag
+               state_next <= STATE_WAITING;
+            end if;
+         else
+            cache_access <= '0';
+            cache_we <= '0';
+            state_next <= STATE_IDLE;
+         end if;
+      else
+         cache_address <= '0' & cpu_address(11 downto 2);
+         cache_access <= '0';
+         if state = STATE_MISSED then
+            cache_we <= '1';                  --update cache tag
+         else
+            cache_we <= '0';
+         end if;
+         state_next <= state;
+      end if;
+
+      if byte_we_next = "0000" or byte_we_next = "1111" then  --read or 32-bit write
+         cache_tag_in <= address_next(20 downto 12);
+      else
+         cache_tag_in <= ONES(8 downto 0);  --invalid tag
+      end if;
+
+      if reset = '1' then
+         state_reg <= STATE_IDLE;
+         cache_tag_reg <= ZERO(8 downto 0);
+      elsif rising_edge(clk) then
+         state_reg <= state_next;
+         if state = STATE_IDLE and state_reg /= STATE_MISSED then
+            cache_tag_reg <= cache_tag_in;
+         end if;
+      end if;
+
+   end process;
+
+   cache_xilinx: if memory_type = "XILINX_16X" generate
+   begin
+      cache_tag: RAMB16_S9  --Xilinx specific
+      port map (
+         DO   => cache_tag_out(7 downto 0),
+         DOP  => cache_tag_out(8 downto 8), 
+         ADDR => cache_address,             --registered
+         CLK  => clk, 
+         DI   => cache_tag_in(7 downto 0),  --registered
+         DIP  => cache_tag_in(8 downto 8),
+         EN   => '1',
+         SSR  => ZERO(0),
+         WE   => cache_we);
+   end generate; --cache_xilinx
+      
+   cache_generic: if memory_type /= "XILINX_16X" generate
+   begin
+      cache_tag: process(clk, cache_address, cache_tag_in, cache_we)
+         constant ADDRESS_WIDTH : natural := 10;
+         type storage_array is
+            array(natural range 0 to 2 ** ADDRESS_WIDTH - 1) of 
+            std_logic_vector(8 downto 0);
+         variable storage : storage_array;
+         variable index   : natural := 0;
+      begin
+         if rising_edge(clk) then
+            index := conv_integer(cache_address(ADDRESS_WIDTH-1 downto 0));
+            if cache_we = '1' then
+               storage(index) := cache_tag_in;
+            end if;
+            cache_tag_out <= storage(index);
+         end if;
+      end process; --cache_tag
+   end generate; --cache_generic
+
+end; --logic
+
diff --git a/vhdl/code.txt b/vhdl/code.txt
new file mode 100644 (file)
index 0000000..934d128
--- /dev/null
@@ -0,0 +1,658 @@
+3c1c0000
+379c8a34
+3c040000
+34840a48
+3c050000
+34a50a64
+3c1d0000
+37bd0c60
+ac800000
+0085182a
+1460fffd
+24840004
+0c0001d5
+00000000
+0800000e
+23bdff98
+afa10010
+afa20014
+afa30018
+afa4001c
+afa50020
+afa60024
+afa70028
+afa8002c
+afa90030
+afaa0034
+afab0038
+afac003c
+afad0040
+afae0044
+afaf0048
+afb8004c
+afb90050
+afbf0054
+401a7000
+235afffc
+afba0058
+0000d810
+afbb005c
+0000d812
+afbb0060
+23a50000
+3c062000
+8cc40020
+8cc60010
+0c00020a
+00862024
+8fa10010
+8fa20014
+8fa30018
+8fa4001c
+8fa50020
+8fa60024
+8fa70028
+8fa8002c
+8fa90030
+8faa0034
+8fab0038
+8fac003c
+8fad0040
+8fae0044
+8faf0048
+8fb8004c
+8fb90050
+8fbf0054
+8fba0058
+8fbb005c
+03600011
+8fbb0060
+03600013
+23bd0068
+341b0001
+03400008
+409b6000
+40026000
+03e00008
+40846000
+3c050000
+24a50160
+8ca60000
+ac06003c
+8ca60004
+ac060040
+8ca60008
+ac060044
+8ca6000c
+03e00008
+ac060048
+3c1a1000
+375a003c
+03400008
+00000000
+ac900000
+ac910004
+ac920008
+ac93000c
+ac940010
+ac950014
+ac960018
+ac97001c
+ac9e0020
+ac9c0024
+ac9d0028
+ac9f002c
+03e00008
+34020000
+8c900000
+8c910004
+8c920008
+8c93000c
+8c940010
+8c950014
+8c960018
+8c97001c
+8c9e0020
+8c9c0024
+8c9d0028
+8c9f002c
+03e00008
+34a20000
+00850019
+00001012
+00002010
+03e00008
+acc40000
+3c020000
+24420a48
+a0400008
+24050007
+00403825
+3083000f
+2862000a
+10400003
+00a73021
+10000002
+24620030
+24620037
+a0c20000
+24a5ffff
+04a1fff6
+00042102
+3c020000
+03e00008
+24420a48
+3c020000
+24420a58
+a040000a
+00803025
+24050009
+00404025
+3c07cccc
+34e7cccd
+00c70019
+00a82021
+24a5ffff
+00004810
+000918c2
+00031080
+00431021
+00021040
+00c21023
+24420030
+a0820000
+04a1fff4
+00603025
+3c020000
+03e00008
+24420a58
+27bdffe0
+afbf0018
+afb10014
+afb00010
+0c000090
+00808825
+0c0001ef
+00402025
+3c040000
+0c0001ef
+24840980
+3c023b9a
+3442c9ff
+0051102b
+1040001e
+3c030004
+34634b83
+00111242
+00430019
+3c030000
+246309cc
+00002810
+000581c2
+00101080
+00431021
+8c440000
+0c0001ef
+00000000
+3c040000
+0c0001ef
+24840984
+00101140
+00501023
+00021080
+00501023
+00021100
+00501021
+000210c0
+00501023
+00021940
+00621823
+00031880
+00701821
+00031a40
+02238823
+3c0205f5
+3442e0ff
+0051102b
+10400023
+3c0255e6
+34423b89
+02220019
+3c030000
+246309cc
+00002810
+00058642
+00101080
+00431021
+8c440000
+0c0001ef
+00000000
+3c040000
+0c0001ef
+24840990
+00101040
+00501021
+00021180
+00501023
+00021080
+00501023
+00021100
+00501023
+00021140
+00501021
+00021200
+02228823
+3c02000f
+3442423f
+0051102b
+14400005
+3c020131
+3c040000
+0c0001ef
+2484099c
+3c020131
+34422cff
+0051102b
+10400021
+3c026b5f
+3442ca6b
+02220019
+3c030000
+246309cc
+00002810
+00058582
+26020014
+00021080
+00431021
+8c440000
+0c0001ef
+00000000
+0c0001de
+24040020
+00101940
+00701823
+00031180
+00431023
+000210c0
+00501021
+00021880
+00431021
+000211c0
+02228823
+3c02000f
+3442423f
+0051102b
+14400009
+3c02431b
+3c040000
+0c0001ef
+2484099c
+3c02000f
+3442423f
+0051102b
+10400017
+3c02431b
+3442de83
+02220019
+3c030000
+246309cc
+00002810
+00058482
+00101080
+00431021
+8c440000
+0c0001ef
+00000000
+3c040000
+0c0001ef
+248409a8
+00101940
+00701823
+00031180
+00431023
+000210c0
+00501021
+00021180
+02228823
+3c020001
+3442869f
+0051102b
+10400020
+3c030a7c
+34635ac5
+00111142
+00430019
+3c030000
+246309cc
+00002810
+000581c2
+00101080
+00431021
+8c440000
+0c0001ef
+00000000
+3c040000
+0c0001ef
+24840990
+00101040
+00501021
+00021980
+00431021
+00021080
+00501021
+00021080
+00501021
+00021140
+02228823
+2e2203e8
+10400005
+2e224e20
+3c040000
+0c0001ef
+248409b4
+2e224e20
+1440001f
+2e2203e8
+3c02d1b7
+34421759
+02220019
+3c030000
+246309cc
+00002810
+00058342
+26020014
+00021080
+00431021
+8c440000
+0c0001ef
+00000000
+0c0001de
+24040020
+00101080
+00501021
+000210c0
+00501023
+00021100
+00501021
+00021100
+02228823
+2e2203e8
+10400008
+3c021062
+3c040000
+0c0001ef
+248409b4
+2e2203e8
+14400017
+2e220064
+3c021062
+34424dd3
+02220019
+3c030000
+246309cc
+00002810
+00058182
+00101080
+00431021
+8c440000
+0c0001ef
+00000000
+3c040000
+0c0001ef
+248409c0
+00101140
+00501023
+00021080
+00501021
+000210c0
+02228823
+2e220064
+14400017
+2e220014
+3c0251eb
+3442851f
+02220019
+3c030000
+246309cc
+00002810
+00058142
+00101080
+00431021
+8c440000
+0c0001ef
+00000000
+3c040000
+0c0001ef
+24840990
+00101040
+00501021
+000210c0
+00501021
+00021080
+02228823
+2e220014
+14400014
+3c030000
+3c02cccc
+3442cccd
+02220019
+246309cc
+00002810
+000580c2
+26020014
+00021080
+00431021
+8c440000
+0c0001ef
+00000000
+0c0001de
+24040020
+00101080
+00501021
+00021040
+02228823
+3c030000
+246309cc
+00111080
+00431021
+8c440000
+0c0001ef
+00000000
+0c0001de
+2404000d
+0c0001de
+2404000a
+8fbf0018
+8fb10014
+8fb00010
+03e00008
+27bd0020
+27bdffe8
+afbf0014
+afb00010
+24100003
+0c0000a8
+02002025
+00101040
+1000fffc
+02028021
+3c022000
+34420020
+8c420000
+00000000
+30420002
+14400008
+3c022000
+3c032000
+34630020
+8c620000
+00000000
+30420002
+1040fffc
+3c022000
+ac440000
+03e00008
+00000000
+27bdffe0
+afb00010
+00808025
+afbf0018
+afb10014
+92020000
+00000000
+1040000d
+2411000a
+00000000
+14510003
+00000000
+0c0001de
+2404000d
+92040000
+0c0001de
+26100001
+92020000
+00000000
+1440fff5
+00000000
+8fbf0018
+8fb10014
+8fb00010
+00001025
+03e00008
+27bd0020
+27bdffe8
+afbf0010
+0c0001de
+24040049
+8fbf0010
+00000000
+03e00008
+27bd0018
+3c022000
+34420020
+8c420000
+03e00008
+30420001
+27bdffe8
+afbf0010
+0c000212
+00000000
+1040fffd
+3c022000
+8c420000
+8fbf0010
+00000000
+03e00008
+27bd0018
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+6e696e65
+74790000
+65696768
+74790000
+73657665
+6e747900
+73697874
+79000000
+66696674
+79000000
+666f7274
+79000000
+74686972
+74790000
+7477656e
+74790000
+6e696e65
+7465656e
+00000000
+65696768
+7465656e
+00000000
+73657665
+6e746565
+6e000000
+73697874
+65656e00
+66696674
+65656e00
+666f7572
+7465656e
+00000000
+74686972
+7465656e
+00000000
+7477656c
+76650000
+656c6576
+656e0000
+74656e00
+6e696e65
+00000000
+65696768
+74000000
+73657665
+6e000000
+73697800
+66697665
+00000000
+666f7572
+00000000
+74687265
+65000000
+74776f00
+6f6e6500
+00000000
+3a200000
+2062696c
+6c696f6e
+20000000
+2068756e
+64726564
+20000000
+6d696c6c
+696f6e20
+00000000
+206d696c
+6c696f6e
+20000000
+74686f75
+73616e64
+20000000
+2074686f
+7573616e
+64200000
+0000097c
+00000978
+00000974
+0000096c
+00000964
+0000095c
+00000958
+00000950
+00000948
+00000940
+0000093c
+00000934
+0000092c
+00000920
+00000914
+0000090c
+00000904
+000008f8
+000008ec
+000008e0
+0000097c
+0000093c
+000008d8
+000008d0
+000008c8
+000008c0
+000008b8
+000008b0
+000008a8
+000008a0
+00000000
diff --git a/vhdl/control.vhd b/vhdl/control.vhd
new file mode 100644 (file)
index 0000000..aa240bf
--- /dev/null
@@ -0,0 +1,482 @@
+---------------------------------------------------------------------\r
+-- TITLE: Controller / Opcode Decoder\r
+-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)\r
+-- DATE CREATED: 2/8/01\r
+-- FILENAME: control.vhd\r
+-- PROJECT: Plasma CPU core\r
+-- COPYRIGHT: Software placed into the public domain by the author.\r
+--    Software 'as is' without warranty.  Author liable for nothing.\r
+-- NOTE:  MIPS(tm) is a registered trademark of MIPS Technologies.\r
+--    MIPS Technologies does not endorse and is not associated with\r
+--    this project.\r
+-- DESCRIPTION:\r
+--    Controls the CPU by decoding the opcode and generating control \r
+--    signals to the rest of the CPU.\r
+--    This entity decodes the MIPS(tm) opcode into a \r
+--    Very-Long-Word-Instruction.  \r
+--    The 32-bit opcode is converted to a \r
+--       6+6+6+16+4+2+4+3+2+2+3+2+4 = 60 bit VLWI opcode.\r
+--    Based on information found in:\r
+--       "MIPS RISC Architecture" by Gerry Kane and Joe Heinrich\r
+--       and "The Designer's Guide to VHDL" by Peter J. Ashenden\r
+---------------------------------------------------------------------\r
+library ieee;\r
+use ieee.std_logic_1164.all;\r
+use work.mlite_pack.all;\r
+\r
+entity control is\r
+   port(opcode       : in  std_logic_vector(31 downto 0);\r
+        intr_signal  : in  std_logic;\r
+        rs_index     : out std_logic_vector(5 downto 0);\r
+        rt_index     : out std_logic_vector(5 downto 0);\r
+        rd_index     : out std_logic_vector(5 downto 0);\r
+        imm_out      : out std_logic_vector(15 downto 0);\r
+        alu_func     : out alu_function_type;\r
+        shift_func   : out shift_function_type;\r
+        mult_func    : out mult_function_type;\r
+        branch_func  : out branch_function_type;\r
+        a_source_out : out a_source_type;\r
+        b_source_out : out b_source_type;\r
+        c_source_out : out c_source_type;\r
+        pc_source_out: out pc_source_type;\r
+        mem_source_out:out mem_source_type;\r
+        exception_out: out std_logic);\r
+end; --entity control\r
+\r
+architecture logic of control is\r
+begin\r
+\r
+control_proc: process(opcode, intr_signal) \r
+   variable op, func       : std_logic_vector(5 downto 0);\r
+   variable rs, rt, rd     : std_logic_vector(5 downto 0);\r
+   variable rtx            : std_logic_vector(4 downto 0);\r
+   variable imm            : std_logic_vector(15 downto 0);\r
+   variable alu_function   : alu_function_type;\r
+   variable shift_function : shift_function_type;\r
+   variable mult_function  : mult_function_type;\r
+   variable a_source       : a_source_type;\r
+   variable b_source       : b_source_type;\r
+   variable c_source       : c_source_type;\r
+   variable pc_source      : pc_source_type;\r
+   variable branch_function: branch_function_type;\r
+   variable mem_source     : mem_source_type;\r
+   variable is_syscall     : std_logic;\r
+begin\r
+   alu_function := ALU_NOTHING;\r
+   shift_function := SHIFT_NOTHING;\r
+   mult_function := MULT_NOTHING;\r
+   a_source := A_FROM_REG_SOURCE;\r
+   b_source := B_FROM_REG_TARGET;\r
+   c_source := C_FROM_NULL;\r
+   pc_source := FROM_INC4;\r
+   branch_function := BRANCH_EQ;\r
+   mem_source := MEM_FETCH;\r
+   op := opcode(31 downto 26);\r
+   rs := '0' & opcode(25 downto 21);\r
+   rt := '0' & opcode(20 downto 16);\r
+   rtx := opcode(20 downto 16);\r
+   rd := '0' & opcode(15 downto 11);\r
+   func := opcode(5 downto 0);\r
+   imm := opcode(15 downto 0);\r
+   is_syscall := '0';\r
+\r
+   case op is\r
+   when "000000" =>   --SPECIAL\r
+      case func is\r
+      when "000000" =>   --SLL   r[rd]=r[rt]<<re;\r
+         a_source := A_FROM_IMM10_6;\r
+         c_source := C_FROM_SHIFT;\r
+         shift_function := SHIFT_LEFT_UNSIGNED;\r
+\r
+      when "000010" =>   --SRL   r[rd]=u[rt]>>re;\r
+         a_source := A_FROM_IMM10_6;\r
+         c_source := C_FROM_shift;\r
+         shift_function := SHIFT_RIGHT_UNSIGNED;\r
+\r
+      when "000011" =>   --SRA   r[rd]=r[rt]>>re;\r
+         a_source := A_FROM_IMM10_6;\r
+         c_source := C_FROM_SHIFT;\r
+         shift_function := SHIFT_RIGHT_SIGNED;\r
+\r
+      when "000100" =>   --SLLV  r[rd]=r[rt]<<r[rs];\r
+         c_source := C_FROM_SHIFT;\r
+         shift_function := SHIFT_LEFT_UNSIGNED;\r
+\r
+      when "000110" =>   --SRLV  r[rd]=u[rt]>>r[rs];\r
+         c_source := C_FROM_SHIFT;\r
+         shift_function := SHIFT_RIGHT_UNSIGNED;\r
+\r
+      when "000111" =>   --SRAV  r[rd]=r[rt]>>r[rs];\r
+         c_source := C_FROM_SHIFT;\r
+         shift_function := SHIFT_RIGHT_SIGNED;\r
+\r
+      when "001000" =>   --JR    s->pc_next=r[rs];\r
+         pc_source := FROM_BRANCH;\r
+         alu_function := ALU_ADD;\r
+         branch_function := BRANCH_YES;\r
+\r
+      when "001001" =>   --JALR  r[rd]=s->pc_next; s->pc_next=r[rs];\r
+         c_source := C_FROM_PC_PLUS4;\r
+         pc_source := FROM_BRANCH;\r
+         alu_function := ALU_ADD;\r
+         branch_function := BRANCH_YES;\r
+\r
+      --when "001010" =>   --MOVZ  if(!r[rt]) r[rd]=r[rs]; /*IV*/\r
+      --when "001011" =>   --MOVN  if(r[rt]) r[rd]=r[rs];  /*IV*/\r
+\r
+      when "001100" =>   --SYSCALL\r
+         is_syscall := '1';\r
+\r
+      when "001101" =>   --BREAK s->wakeup=1;\r
+         is_syscall := '1';\r
+\r
+      --when "001111" =>   --SYNC  s->wakeup=1;\r
+\r
+      when "010000" =>   --MFHI  r[rd]=s->hi;\r
+         c_source := C_FROM_MULT;\r
+         mult_function := MULT_READ_HI;\r
+\r
+      when "010001" =>   --MTHI  s->hi=r[rs];\r
+         mult_function := MULT_WRITE_HI;\r
+\r
+      when "010010" =>   --MFLO  r[rd]=s->lo;\r
+         c_source := C_FROM_MULT;\r
+         mult_function := MULT_READ_LO;\r
+\r
+      when "010011" =>   --MTLO  s->lo=r[rs];\r
+         mult_function := MULT_WRITE_LO;\r
+\r
+      when "011000" =>   --MULT  s->lo=r[rs]*r[rt]; s->hi=0;\r
+         mult_function := MULT_SIGNED_MULT;\r
+\r
+      when "011001" =>   --MULTU s->lo=r[rs]*r[rt]; s->hi=0;\r
+         mult_function := MULT_MULT;\r
+\r
+      when "011010" =>   --DIV   s->lo=r[rs]/r[rt]; s->hi=r[rs]%r[rt];\r
+         mult_function := MULT_SIGNED_DIVIDE;\r
+\r
+      when "011011" =>   --DIVU  s->lo=r[rs]/r[rt]; s->hi=r[rs]%r[rt];\r
+         mult_function := MULT_DIVIDE;\r
+\r
+      when "100000" =>   --ADD   r[rd]=r[rs]+r[rt];\r
+         c_source := C_FROM_ALU;\r
+         alu_function := ALU_ADD;\r
+\r
+      when "100001" =>   --ADDU  r[rd]=r[rs]+r[rt];\r
+         c_source := C_FROM_ALU;\r
+         alu_function := ALU_ADD;\r
+\r
+      when "100010" =>   --SUB   r[rd]=r[rs]-r[rt];\r
+         c_source := C_FROM_ALU;\r
+         alu_function := ALU_SUBTRACT;\r
+\r
+      when "100011" =>   --SUBU  r[rd]=r[rs]-r[rt];\r
+         c_source := C_FROM_ALU;\r
+         alu_function := ALU_SUBTRACT;\r
+\r
+      when "100100" =>   --AND   r[rd]=r[rs]&r[rt];\r
+         c_source := C_FROM_ALU;\r
+         alu_function := ALU_AND;\r
+\r
+      when "100101" =>   --OR    r[rd]=r[rs]|r[rt];\r
+         c_source := C_FROM_ALU;\r
+         alu_function := ALU_OR;\r
+\r
+      when "100110" =>   --XOR   r[rd]=r[rs]^r[rt];\r
+         c_source := C_FROM_ALU;\r
+         alu_function := ALU_XOR;\r
+\r
+      when "100111" =>   --NOR   r[rd]=~(r[rs]|r[rt]);\r
+         c_source := C_FROM_ALU;\r
+         alu_function := ALU_NOR;\r
+\r
+      when "101010" =>   --SLT   r[rd]=r[rs]<r[rt];\r
+         c_source := C_FROM_ALU;\r
+         alu_function := ALU_LESS_THAN_SIGNED;\r
+\r
+      when "101011" =>   --SLTU  r[rd]=u[rs]<u[rt];\r
+         c_source := C_FROM_ALU;\r
+         alu_function := ALU_LESS_THAN;\r
+\r
+      when "101101" =>   --DADDU r[rd]=r[rs]+u[rt];\r
+         c_source := C_FROM_ALU;\r
+         alu_function := ALU_ADD;\r
+\r
+      --when "110001" =>   --TGEU\r
+      --when "110010" =>   --TLT\r
+      --when "110011" =>   --TLTU\r
+      --when "110100" =>   --TEQ \r
+      --when "110110" =>   --TNE \r
+      when others =>\r
+      end case;\r
+\r
+   when "000001" =>   --REGIMM\r
+      rt := "000000";\r
+      rd := "011111";\r
+      a_source := A_FROM_PC;\r
+      b_source := B_FROM_IMMX4;\r
+      alu_function := ALU_ADD;\r
+      pc_source := FROM_BRANCH;\r
+      branch_function := BRANCH_GTZ;\r
+      --if(test) pc=pc+imm*4\r
+\r
+      case rtx is\r
+      when "10000" =>   --BLTZAL  r[31]=s->pc_next; branch=r[rs]<0;\r
+         c_source := C_FROM_PC_PLUS4;\r
+         branch_function := BRANCH_LTZ;\r
+\r
+      when "00000" =>   --BLTZ    branch=r[rs]<0;\r
+         branch_function := BRANCH_LTZ;\r
+\r
+      when "10001" =>   --BGEZAL  r[31]=s->pc_next; branch=r[rs]>=0;\r
+         c_source := C_FROM_PC_PLUS4;\r
+         branch_function := BRANCH_GEZ;\r
+\r
+      when "00001" =>   --BGEZ    branch=r[rs]>=0;\r
+         branch_function := BRANCH_GEZ;\r
+\r
+      --when "10010" =>   --BLTZALL r[31]=s->pc_next; lbranch=r[rs]<0;\r
+      --when "00010" =>   --BLTZL   lbranch=r[rs]<0;\r
+      --when "10011" =>   --BGEZALL r[31]=s->pc_next; lbranch=r[rs]>=0;\r
+      --when "00011" =>   --BGEZL   lbranch=r[rs]>=0;\r
+\r
+      when others =>\r
+      end case;\r
+\r
+   when "000011" =>   --JAL    r[31]=s->pc_next; s->pc_next=(s->pc&0xf0000000)|target;\r
+      c_source := C_FROM_PC_PLUS4;\r
+      rd := "011111";\r
+      pc_source := FROM_OPCODE25_0;\r
+\r
+   when "000010" =>   --J      s->pc_next=(s->pc&0xf0000000)|target; \r
+      pc_source := FROM_OPCODE25_0;\r
+\r
+   when "000100" =>   --BEQ    branch=r[rs]==r[rt];\r
+      a_source := A_FROM_PC;\r
+      b_source := B_FROM_IMMX4;\r
+      alu_function := ALU_ADD;\r
+      pc_source := FROM_BRANCH;\r
+      branch_function := BRANCH_EQ;\r
+\r
+   when "000101" =>   --BNE    branch=r[rs]!=r[rt];\r
+      a_source := A_FROM_PC;\r
+      b_source := B_FROM_IMMX4;\r
+      alu_function := ALU_ADD;\r
+      pc_source := FROM_BRANCH;\r
+      branch_function := BRANCH_NE;\r
+\r
+   when "000110" =>   --BLEZ   branch=r[rs]<=0;\r
+      a_source := A_FROM_PC;\r
+      b_source := b_FROM_IMMX4;\r
+      alu_function := ALU_ADD;\r
+      pc_source := FROM_BRANCH;\r
+      branch_function := BRANCH_LEZ;\r
+\r
+   when "000111" =>   --BGTZ   branch=r[rs]>0;\r
+      a_source := A_FROM_PC;\r
+      b_source := B_FROM_IMMX4;\r
+      alu_function := ALU_ADD;\r
+      pc_source := FROM_BRANCH;\r
+      branch_function := BRANCH_GTZ;\r
+\r
+   when "001000" =>   --ADDI   r[rt]=r[rs]+(short)imm;\r
+      b_source := B_FROM_SIGNED_IMM;\r
+      c_source := C_FROM_ALU;\r
+      rd := rt;\r
+      alu_function := ALU_ADD;\r
+\r
+   when "001001" =>   --ADDIU  u[rt]=u[rs]+(short)imm;\r
+      b_source := B_FROM_SIGNED_IMM;\r
+      c_source := C_FROM_ALU;\r
+      rd := rt;\r
+      alu_function := ALU_ADD;\r
+\r
+   when "001010" =>   --SLTI   r[rt]=r[rs]<(short)imm;\r
+      b_source := B_FROM_SIGNED_IMM;\r
+      c_source := C_FROM_ALU;\r
+      rd := rt;\r
+      alu_function := ALU_LESS_THAN_SIGNED;\r
+\r
+   when "001011" =>   --SLTIU  u[rt]=u[rs]<(unsigned long)(short)imm;\r
+      b_source := B_FROM_SIGNED_IMM;\r
+      c_source := C_FROM_ALU;\r
+      rd := rt;\r
+      alu_function := ALU_LESS_THAN;\r
+\r
+   when "001100" =>   --ANDI   r[rt]=r[rs]&imm;\r
+      b_source := B_FROM_IMM;\r
+      c_source := C_FROM_ALU;\r
+      rd := rt;\r
+      alu_function := ALU_AND;\r
+\r
+   when "001101" =>   --ORI    r[rt]=r[rs]|imm;\r
+      b_source := B_FROM_IMM;\r
+      c_source := C_FROM_ALU;\r
+      rd := rt;\r
+      alu_function := ALU_OR;\r
+\r
+   when "001110" =>   --XORI   r[rt]=r[rs]^imm;\r
+      b_source := B_FROM_IMM;\r
+      c_source := C_FROM_ALU;\r
+      rd := rt;\r
+      alu_function := ALU_XOR;\r
+\r
+   when "001111" =>   --LUI    r[rt]=(imm<<16);\r
+      c_source := C_FROM_IMM_SHIFT16;\r
+      rd := rt;\r
+\r
+   when "010000" =>   --COP0\r
+      alu_function := ALU_OR;\r
+      c_source := C_FROM_ALU;\r
+      if opcode(23) = '0' then  --move from CP0\r
+         rs := '1' & opcode(15 downto 11);\r
+         rt := "000000";\r
+         rd := '0' & opcode(20 downto 16);\r
+      else                      --move to CP0\r
+         rs := "000000";\r
+         rd(5) := '1';\r
+         pc_source := FROM_BRANCH;   --delay possible interrupt\r
+         branch_function := BRANCH_NO;\r
+      end if;\r
+\r
+   --when "010001" =>   --COP1\r
+   --when "010010" =>   --COP2\r
+   --when "010011" =>   --COP3\r
+   --when "010100" =>   --BEQL   lbranch=r[rs]==r[rt];\r
+   --when "010101" =>   --BNEL   lbranch=r[rs]!=r[rt];\r
+   --when "010110" =>   --BLEZL  lbranch=r[rs]<=0;\r
+   --when "010111" =>   --BGTZL  lbranch=r[rs]>0;\r
+\r
+   when "100000" =>   --LB     r[rt]=*(signed char*)ptr;\r
+      a_source := A_FROM_REG_SOURCE;\r
+      b_source := B_FROM_SIGNED_IMM;\r
+      alu_function := ALU_ADD;\r
+      rd := rt;\r
+      c_source := C_FROM_MEMORY;\r
+      mem_source := MEM_READ8S;    --address=(short)imm+r[rs];\r
+\r
+   when "100001" =>   --LH     r[rt]=*(signed short*)ptr;\r
+      a_source := A_FROM_REG_SOURCE;\r
+      b_source := B_FROM_SIGNED_IMM;\r
+      alu_function := ALU_ADD;\r
+      rd := rt;\r
+      c_source := C_FROM_MEMORY;\r
+      mem_source := MEM_READ16S;   --address=(short)imm+r[rs];\r
+\r
+   when "100010" =>   --LWL    //Not Implemented\r
+      a_source := A_FROM_REG_SOURCE;\r
+      b_source := B_FROM_SIGNED_IMM;\r
+      alu_function := ALU_ADD;\r
+      rd := rt;\r
+      c_source := C_FROM_MEMORY;\r
+      mem_source := MEM_READ32;\r
+\r
+   when "100011" =>   --LW     r[rt]=*(long*)ptr;\r
+      a_source := A_FROM_REG_SOURCE;\r
+      b_source := B_FROM_SIGNED_IMM;\r
+      alu_function := ALU_ADD;\r
+      rd := rt;\r
+      c_source := C_FROM_MEMORY;\r
+      mem_source := MEM_READ32;\r
+\r
+   when "100100" =>   --LBU    r[rt]=*(unsigned char*)ptr;\r
+      a_source := A_FROM_REG_SOURCE;\r
+      b_source := B_FROM_SIGNED_IMM;\r
+      alu_function := ALU_ADD;\r
+      rd := rt;\r
+      c_source := C_FROM_MEMORY;\r
+      mem_source := MEM_READ8;    --address=(short)imm+r[rs];\r
+\r
+   when "100101" =>   --LHU    r[rt]=*(unsigned short*)ptr;\r
+      a_source := A_FROM_REG_SOURCE;\r
+      b_source := B_FROM_SIGNED_IMM;\r
+      alu_function := ALU_ADD;\r
+      rd := rt;\r
+      c_source := C_FROM_MEMORY;\r
+      mem_source := MEM_READ16;    --address=(short)imm+r[rs];\r
+\r
+   --when "100110" =>   --LWR    //Not Implemented\r
+\r
+   when "101000" =>   --SB     *(char*)ptr=(char)r[rt];\r
+      a_source := A_FROM_REG_SOURCE;\r
+      b_source := B_FROM_SIGNED_IMM;\r
+      alu_function := ALU_ADD;\r
+      mem_source := MEM_WRITE8;   --address=(short)imm+r[rs];\r
+\r
+   when "101001" =>   --SH     *(short*)ptr=(short)r[rt];\r
+      a_source := A_FROM_REG_SOURCE;\r
+      b_source := B_FROM_SIGNED_IMM;\r
+      alu_function := ALU_ADD;\r
+      mem_source := MEM_WRITE16;\r
+\r
+   when "101010" =>   --SWL    //Not Implemented\r
+      a_source := A_FROM_REG_SOURCE;\r
+      b_source := B_FROM_SIGNED_IMM;\r
+      alu_function := ALU_ADD;\r
+      mem_source := MEM_WRITE32;  --address=(short)imm+r[rs];\r
+\r
+   when "101011" =>   --SW     *(long*)ptr=r[rt];\r
+      a_source := A_FROM_REG_SOURCE;\r
+      b_source := B_FROM_SIGNED_IMM;\r
+      alu_function := ALU_ADD;\r
+      mem_source := MEM_WRITE32;  --address=(short)imm+r[rs];\r
+\r
+   --when "101110" =>   --SWR    //Not Implemented\r
+   --when "101111" =>   --CACHE\r
+   --when "110000" =>   --LL     r[rt]=*(long*)ptr;\r
+   --when "110001" =>   --LWC1 \r
+   --when "110010" =>   --LWC2 \r
+   --when "110011" =>   --LWC3 \r
+   --when "110101" =>   --LDC1 \r
+   --when "110110" =>   --LDC2 \r
+   --when "110111" =>   --LDC3 \r
+   --when "111000" =>   --SC     *(long*)ptr=r[rt]; r[rt]=1;\r
+   --when "111001" =>   --SWC1 \r
+   --when "111010" =>   --SWC2 \r
+   --when "111011" =>   --SWC3 \r
+   --when "111101" =>   --SDC1 \r
+   --when "111110" =>   --SDC2 \r
+   --when "111111" =>   --SDC3 \r
+   when others =>\r
+   end case;\r
+\r
+   if c_source = C_FROM_NULL then\r
+      rd := "000000";\r
+   end if;\r
+\r
+   if intr_signal = '1' or is_syscall = '1' then\r
+      rs := "111111";  --interrupt vector\r
+      rt := "000000";\r
+      rd := "101110";  --save PC in EPC\r
+      alu_function := ALU_OR;\r
+      shift_function := SHIFT_NOTHING;\r
+      mult_function := MULT_NOTHING;\r
+      branch_function := BRANCH_YES;\r
+      a_source := A_FROM_REG_SOURCE;\r
+      b_source := B_FROM_REG_TARGET;\r
+      c_source := C_FROM_PC;\r
+      pc_source := FROM_LBRANCH;\r
+      mem_source := MEM_FETCH;\r
+      exception_out <= '1';\r
+   else\r
+      exception_out <= '0';\r
+   end if;\r
+\r
+   rs_index <= rs;\r
+   rt_index <= rt;\r
+   rd_index <= rd;\r
+   imm_out <= imm;\r
+   alu_func <= alu_function;\r
+   shift_func <= shift_function;\r
+   mult_func <= mult_function;\r
+   branch_func <= branch_function;\r
+   a_source_out <= a_source;\r
+   b_source_out <= b_source;\r
+   c_source_out <= c_source;\r
+   pc_source_out <= pc_source;\r
+   mem_source_out <= mem_source;\r
+\r
+end process;\r
+\r
+end; --logic\r
+\r
diff --git a/vhdl/ddr_ctrl.vhd b/vhdl/ddr_ctrl.vhd
new file mode 100644 (file)
index 0000000..34d84de
--- /dev/null
@@ -0,0 +1,354 @@
+---------------------------------------------------------------------
+-- TITLE: DDR SDRAM Interface
+-- AUTHORS: Steve Rhoads (rhoadss@yahoo.com)
+-- DATE CREATED: 7/26/07
+-- FILENAME: ddr_ctrl.vhd
+-- PROJECT: Plasma CPU core
+-- COPYRIGHT: Software placed into the public domain by the author.
+--    Software 'as is' without warranty.  Author liable for nothing.
+-- DESCRIPTION:
+--    Double Data Rate Sychronous Dynamic Random Access Memory Interface
+--
+--    For: 64 MB = MT46V32M16, 512Mb, 32Mb x 16 (default)
+--    ROW = address(25 downto 13)
+--    BANK = address(12 downto 11)
+--    COL = address(10 downto 2)
+--
+--    Changes are needed for 32 MB = MT46V16M16, 256Mb, 16Mb x 16
+--    ROW = address(24 downto 12)  -- 25 ignored
+--    BANK = address(11 downto 10)
+--    COL = address(9 downto 2)    --also change ddr_init.c
+--
+--    Changes are needed for 128 MB = MT46V64M16, 1Gb, 64Mb x 16
+--    ROW = address(26 downto 14)
+--    BANK = address(13 downto 12)
+--    COL = address(11 downto 2)   --also change ddr_init.c
+--
+--    Requires CAS latency=2; burst size=2.  
+--    Requires clk changes on rising_edge(clk_2x).
+--    Requires active, address, byte_we, data_w stable throughout transfer.
+--    DLL mode requires 77MHz.  Non-DLL mode runs at 25 MHz.
+--
+-- cycle_cnt 777777770000111122223333444455556666777777777777
+-- clk_2x    --__--__--__--__--__--__--__--__--__--__--__--__
+-- clk       ____----____----____----____----____----____----
+-- SD_CLK    ----____----____----____----____----____----____
+-- cmd       ____write+++WRITE+++____________________________
+-- SD_DQ     ~~~~~~~~~~~~~~uuuullllUUUULLLL~~~~~~~~~~~~~~~~~~
+--
+-- cycle_cnt 777777770000111122223333444455556666777777777777
+-- clk_2x    --__--__--__--__--__--__--__--__--__--__--__--__
+-- clk       ____----____----____----____----____----____----
+-- SD_CLK    ----____----____----____----____----____----____
+-- cmd       ____read++++________________________read++++____
+-- SD_DQ     ~~~~~~~~~~~~~~~~~~~~~~~~uuuullll~~~~~~~~~~~~~~~~
+-- SD_DQnDLL ~~~~~~~~~~~~~~~~~~~~~~~~~~uuuullll~~~~~~~~~~~~~~
+-- pause     ____------------------------________------------
+--
+-- Must run DdrInit() to initialize DDR chip.
+-- Read Micron DDR SDRAM MT46V32M16 data sheet for more details.
+---------------------------------------------------------------------
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+use ieee.std_logic_arith.all;
+use work.mlite_pack.all;
+
+entity ddr_ctrl is
+   port(
+      clk      : in std_logic;
+      clk_2x   : in std_logic;
+      reset_in : in std_logic;
+
+      address  : in std_logic_vector(25 downto 2);
+      byte_we  : in std_logic_vector(3 downto 0);
+      data_w   : in std_logic_vector(31 downto 0);
+      data_r   : out std_logic_vector(31 downto 0);
+      active   : in std_logic;
+      no_start : in std_logic;
+      no_stop  : in std_logic;
+      pause    : out std_logic;
+
+      SD_CK_P  : out std_logic;     --clock_positive
+      SD_CK_N  : out std_logic;     --clock_negative
+      SD_CKE   : out std_logic;     --clock_enable
+
+      SD_BA    : out std_logic_vector(1 downto 0);  --bank_address
+      SD_A     : out std_logic_vector(12 downto 0); --address(row or col)
+      SD_CS    : out std_logic;     --chip_select
+      SD_RAS   : out std_logic;     --row_address_strobe
+      SD_CAS   : out std_logic;     --column_address_strobe
+      SD_WE    : out std_logic;     --write_enable
+
+      SD_DQ    : inout std_logic_vector(15 downto 0); --data
+      SD_UDM   : out std_logic;     --upper_byte_enable
+      SD_UDQS  : inout std_logic;   --upper_data_strobe
+      SD_LDM   : out std_logic;     --low_byte_enable
+      SD_LDQS  : inout std_logic);  --low_data_strobe
+end; --entity ddr
+
+architecture logic of ddr_ctrl is
+
+   --Commands for bits RAS & CAS & WE
+   subtype command_type is std_logic_vector(2 downto 0);
+   constant COMMAND_LMR          : command_type := "000";
+   constant COMMAND_AUTO_REFRESH : command_type := "001";
+   constant COMMAND_PRECHARGE    : command_type := "010";
+   constant COMMAND_ACTIVE       : command_type := "011";
+   constant COMMAND_WRITE        : command_type := "100";
+   constant COMMAND_READ         : command_type := "101";
+   constant COMMAND_TERMINATE    : command_type := "110";
+   constant COMMAND_NOP          : command_type := "111";
+
+   subtype ddr_state_type is std_logic_vector(3 downto 0);
+   constant STATE_POWER_ON     : ddr_state_type := "0000";
+   constant STATE_IDLE         : ddr_state_type := "0001";
+   constant STATE_ROW_ACTIVATE : ddr_state_type := "0010";
+   constant STATE_ROW_ACTIVE   : ddr_state_type := "0011";
+   constant STATE_READ         : ddr_state_type := "0100";
+   constant STATE_READ2        : ddr_state_type := "0101";
+   constant STATE_READ3        : ddr_state_type := "0110";
+   constant STATE_PRECHARGE    : ddr_state_type := "0111";
+   constant STATE_PRECHARGE2   : ddr_state_type := "1000";
+
+   signal state_prev   : ddr_state_type;
+   signal refresh_cnt  : std_logic_vector(7 downto 0);
+   signal data_write2  : std_logic_vector(47 downto 0); --write pipeline
+   signal byte_we_reg2 : std_logic_vector(5 downto 0);  --write pipeline
+   signal write_active : std_logic;
+   signal write_prev   : std_logic;
+   signal cycle_count  : std_logic_vector(2 downto 0);  --half clocks since op
+   signal cycle_count2 : std_logic_vector(2 downto 0);  --delayed by quarter clock
+   signal cke_reg      : std_logic;
+   signal clk_p        : std_logic;
+   signal bank_open    : std_logic_vector(3 downto 0);
+   signal data_read    : std_logic_vector(31 downto 0);
+
+begin
+   ddr_proc: process(clk, clk_p, clk_2x, reset_in, 
+                     address, byte_we, data_w, active, no_start, no_stop,
+                     SD_DQ, SD_UDQS, SD_LDQS,
+                     state_prev, refresh_cnt,  
+                     byte_we_reg2, data_write2, 
+                     cycle_count, cycle_count2, write_prev,
+                     write_active, cke_reg, bank_open,
+                     data_read)
+   type address_array_type is array(3 downto 0) of std_logic_vector(12 downto 0);
+   variable address_row    : address_array_type;
+   variable command        : std_logic_vector(2 downto 0); --RAS & CAS & WE
+   variable bank_index     : integer;
+   variable state_current  : ddr_state_type;
+
+   begin
+   
+      command := COMMAND_NOP;
+      bank_index := conv_integer(address(12 downto 11));
+      state_current := state_prev;
+      
+      --DDR state machine to determine state_current and command
+      case state_prev is
+         when STATE_POWER_ON =>
+            if active = '1' then
+               if byte_we /= "0000" then
+                  command := address(6 downto 4); --LMR="000"
+               else
+                  state_current := STATE_IDLE;  --read transistions to STATE_IDLE
+               end if;
+            end if;
+
+         when STATE_IDLE =>
+            if refresh_cnt(7) = '1' then
+               state_current := STATE_PRECHARGE;
+               command := COMMAND_AUTO_REFRESH;
+            elsif active = '1' and no_start = '0' then
+               state_current := STATE_ROW_ACTIVATE;
+               command := COMMAND_ACTIVE;
+            end if;
+            
+         when STATE_ROW_ACTIVATE =>
+            state_current := STATE_ROW_ACTIVE;
+
+         when STATE_ROW_ACTIVE =>
+            if refresh_cnt(7) = '1' then
+               if write_prev = '0' then
+                  state_current := STATE_PRECHARGE;
+                  command := COMMAND_PRECHARGE;
+               end if;
+            elsif active = '1' and no_start = '0' then
+               if bank_open(bank_index) = '0' then
+                  state_current := STATE_ROW_ACTIVATE;
+                  command := COMMAND_ACTIVE;
+               elsif address(25 downto 13) /= address_row(bank_index) then
+                  if write_prev = '0' then
+                     state_current := STATE_PRECHARGE;
+                     command := COMMAND_PRECHARGE;
+                  end if;
+               else
+                  if byte_we /= "0000" then
+                     command := COMMAND_WRITE;
+                  elsif write_prev = '0' then
+                     state_current := STATE_READ;
+                     command := COMMAND_READ;
+                  end if;
+               end if;
+            end if;
+
+         when STATE_READ =>
+            state_current := STATE_READ2;
+
+         when STATE_READ2 =>
+            state_current := STATE_READ3;
+
+         when STATE_READ3 =>
+            if no_stop = '0' then
+               state_current := STATE_ROW_ACTIVE;
+            end if;
+
+         when STATE_PRECHARGE =>
+            state_current := STATE_PRECHARGE2;
+
+         when STATE_PRECHARGE2 =>
+            state_current := STATE_IDLE;
+
+         when others =>
+            state_current := STATE_IDLE;
+      end case; --state_prev
+      
+      --rising_edge(clk) domain registers
+      if reset_in = '1' then
+         state_prev   <= STATE_POWER_ON;
+         cke_reg      <= '0';
+         refresh_cnt  <= ZERO(7 downto 0);
+         write_prev   <= '0';
+         write_active <= '0';
+         bank_open    <= "0000";
+      elsif rising_edge(clk) then
+
+         if active = '1' then
+            cke_reg <= '1';
+         end if;
+
+         if command = COMMAND_WRITE then
+            write_prev <= '1';
+         elsif cycle_count2(2 downto 1) = "11" then
+            write_prev <= '0';
+         end if;
+
+         if command = COMMAND_WRITE then
+            write_active <= '1';
+         elsif cycle_count2 = "100" then
+            write_active <= '0';
+         end if;
+
+         if command = COMMAND_ACTIVE then
+            bank_open(bank_index) <= '1';
+            address_row(bank_index) := address(25 downto 13);
+         end if;
+         
+         if command = COMMAND_PRECHARGE then
+            bank_open <= "0000";
+         end if;
+         
+         if command = COMMAND_AUTO_REFRESH then
+            refresh_cnt <= ZERO(7 downto 0);
+         else
+            refresh_cnt <= refresh_cnt + 1;
+         end if;
+         
+         state_prev <= state_current;
+
+      end if; --rising_edge(clk)
+
+      --rising_edge(clk_2x) domain registers
+      if reset_in = '1' then
+         cycle_count <= "000";
+      elsif rising_edge(clk_2x) then
+         --Cycle_count
+         if (command = COMMAND_READ or command = COMMAND_WRITE) and clk = '1' then
+            cycle_count <= "000";
+         elsif cycle_count /= "111" then
+            cycle_count <= cycle_count + 1;
+         end if;
+         
+         clk_p <= clk;  --earlier version of not clk         
+         
+         --Read data (DLL disabled)
+         if cycle_count = "100" then
+            data_read(31 downto 16) <= SD_DQ; --data
+         elsif cycle_count = "101" then
+            data_read(15 downto 0) <= SD_DQ;
+         end if;
+      end if;
+
+      --falling_edge(clk_2x) domain registers
+      if reset_in = '1' then
+         cycle_count2 <= "000";
+         data_write2 <= ZERO(15 downto 0) & ZERO;
+         byte_we_reg2 <= "000000";
+      elsif falling_edge(clk_2x) then
+         cycle_count2 <= cycle_count;
+
+         --Write pipeline
+         if clk = '0' then
+            data_write2 <= data_write2(31 downto 16) & data_w;
+            byte_we_reg2 <= byte_we_reg2(3 downto 2) & byte_we;
+         else
+            data_write2(47 downto 16) <= data_write2(31 downto 0);
+            byte_we_reg2(5 downto 2) <= byte_we_reg2(3 downto 0);
+         end if;
+
+         --Read data (DLL enabled)
+         --if cycle_count = "100" then
+         --   data_read(31 downto 16) <= SD_DQ; --data
+         --elsif cycle_count = "101" then
+         --   data_read(15 downto 0) <= SD_DQ;
+         --end if;
+      end if;
+      
+      data_r <= data_read;
+
+      --Write data
+      if write_active = '1' then
+         SD_UDQS <= clk_p;                   --upper_data_strobe 
+         SD_LDQS <= clk_p;                   --low_data_strobe
+         SD_DQ <= data_write2(47 downto 32); --data
+         SD_UDM <= not byte_we_reg2(5);      --upper_byte_enable
+         SD_LDM <= not byte_we_reg2(4);      --low_byte_enable
+      else
+         SD_UDQS <= 'Z';               --upper_data_strobe 
+         SD_LDQS <= 'Z';               --low_data_strobe
+         SD_DQ <= "ZZZZZZZZZZZZZZZZ";  --data
+         SD_UDM <= 'Z';
+         SD_LDM <= 'Z';
+      end if;
+
+      --DDR control signals
+      SD_CK_P <= clk_p;                --clock_positive
+      SD_CK_N <= not clk_p;            --clock_negative
+      SD_CKE  <= cke_reg;              --clock_enable
+
+      SD_BA   <= address(12 downto 11);  --bank_address
+      if command = COMMAND_ACTIVE or state_current = STATE_POWER_ON then
+         SD_A <= address(25 downto 13);  --address row
+      elsif command = COMMAND_READ or command = COMMAND_WRITE then
+         SD_A <= "000" & address(10 downto 2) & "0"; --address col
+      else
+         SD_A <= "0010000000000";      --PERCHARGE all banks
+      end if;
+
+      SD_CS   <= not cke_reg;          --chip_select
+      SD_RAS  <= command(2);           --row_address_strobe
+      SD_CAS  <= command(1);           --column_address_strobe
+      SD_WE   <= command(0);           --write_enable
+
+      if active = '1' and state_current /= STATE_POWER_ON and
+         command /= COMMAND_WRITE and state_prev /= STATE_READ3 then
+         pause <= '1';
+      else
+         pause <= '0';
+      end if;
+
+   end process; --ddr_proc
+   
+end; --architecture logic
+
diff --git a/vhdl/eth_dma.vhd b/vhdl/eth_dma.vhd
new file mode 100644 (file)
index 0000000..227db86
--- /dev/null
@@ -0,0 +1,183 @@
+---------------------------------------------------------------------
+-- TITLE: Ethernet DMA
+-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
+-- DATE CREATED: 12/27/07
+-- FILENAME: eth_dma.vhd
+-- PROJECT: Plasma CPU core
+-- COPYRIGHT: Software placed into the public domain by the author.
+--    Software 'as is' without warranty.  Author liable for nothing.
+-- DESCRIPTION:
+--    Ethernet DMA (Direct Memory Access) controller.  
+--    Reads four bits and writes four bits from/to the Ethernet PHY each 
+--    2.5 MHz clock cycle.  Received data is DMAed starting at 0x13ff0000 
+--    transmit data is read from 0x13fd0000.
+--    To send a packet write bytes/4 to Ethernet send register.
+---------------------------------------------------------------------
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+use ieee.std_logic_arith.all;
+use work.mlite_pack.all;
+
+entity eth_dma is port(
+   clk         : in std_logic;                      --25 MHz
+   reset       : in std_logic;
+   enable_eth  : in std_logic;                      --enable receive DMA
+   select_eth  : in std_logic;
+   rec_isr     : out std_logic;                     --data received
+   send_isr    : out std_logic;                     --transmit done
+
+   address     : out std_logic_vector(31 downto 2); --to DDR
+   byte_we     : out std_logic_vector(3 downto 0);
+   data_write  : out std_logic_vector(31 downto 0);
+   data_read   : in std_logic_vector(31 downto 0);
+   pause_in    : in std_logic;
+
+   mem_address : in std_logic_vector(31 downto 2);  --from CPU
+   mem_byte_we : in std_logic_vector(3 downto 0);
+   data_w      : in std_logic_vector(31 downto 0);
+   pause_out   : out std_logic;
+
+   E_RX_CLK    : in std_logic;                      --2.5 MHz receive
+   E_RX_DV     : in std_logic;                      --data valid
+   E_RXD       : in std_logic_vector(3 downto 0);   --receive nibble
+   E_TX_CLK    : in std_logic;                      --2.5 MHz transmit
+   E_TX_EN     : out std_logic;                     --transmit enable
+   E_TXD       : out std_logic_vector(3 downto 0)); --transmit nibble
+end; --entity eth_dma
+
+architecture logic of eth_dma is
+   signal rec_clk    : std_logic_vector(1 downto 0);  --receive
+   signal rec_store  : std_logic_vector(31 downto 0); --to DDR
+   signal rec_data   : std_logic_vector(27 downto 0);
+   signal rec_cnt    : std_logic_vector(2 downto 0);  --nibbles
+   signal rec_words  : std_logic_vector(13 downto 0);
+   signal rec_dma    : std_logic_vector(1 downto 0);  --active & request
+   signal rec_done   : std_logic;
+
+   signal send_clk   : std_logic_vector(1 downto 0);  --transmit
+   signal send_read  : std_logic_vector(31 downto 0); --from DDR
+   signal send_data  : std_logic_vector(31 downto 0);
+   signal send_cnt   : std_logic_vector(2 downto 0);  --nibbles
+   signal send_words : std_logic_vector(8 downto 0);
+   signal send_level : std_logic_vector(8 downto 0);
+   signal send_dma   : std_logic_vector(1 downto 0);  --active & request
+   signal send_enable: std_logic;
+
+begin  --architecture
+
+   dma_proc: process(clk, reset, enable_eth, select_eth, 
+         data_read, pause_in, mem_address, mem_byte_we, data_w, 
+         E_RX_CLK, E_RX_DV, E_RXD, E_TX_CLK,
+         rec_clk, rec_store, rec_data, 
+         rec_cnt, rec_words, rec_dma, rec_done,
+         send_clk, send_read, send_data, send_cnt, send_words, 
+         send_level, send_dma, send_enable)
+   begin
+
+      if reset = '1' then
+         rec_clk <= "00";
+         rec_cnt <= "000";
+         rec_words <= ZERO(13 downto 0);
+         rec_dma <= "00";
+         rec_done <= '0';
+         send_clk <= "00";
+         send_cnt <= "000";
+         send_words <= ZERO(8 downto 0);
+         send_level <= ZERO(8 downto 0);
+         send_dma <= "00";
+         send_enable <= '0';
+      elsif rising_edge(clk) then
+
+         --Receive nibble on low->high E_RX_CLK.  Send to DDR every 32 bits.
+         rec_clk <= rec_clk(0) & E_RX_CLK;
+         if rec_clk = "01" and enable_eth = '1' then
+            if E_RX_DV = '1' or rec_cnt /= "000" then
+               if rec_cnt = "111" then
+                  rec_store <= rec_data & E_RXD;
+                  rec_dma(0) <= '1';           --request DMA
+               end if;
+               rec_data <= rec_data(23 downto 0) & E_RXD;
+               rec_cnt <= rec_cnt + 1;
+            end if;
+         end if;
+
+         --Set transmit count or clear receive interrupt
+         if select_eth = '1' then
+            if mem_byte_we /= "0000" then
+               send_cnt <= "000";
+               send_words <= ZERO(8 downto 0);
+               send_level <= data_w(8 downto 0);
+               send_dma(0) <= '1';
+            else
+               rec_done <= '0';
+            end if;
+         end if;
+
+         --Transmit nibble on low->high E_TX_CLK.  Get 32 bits from DDR.
+         send_clk <= send_clk(0) & E_TX_CLK;
+         if send_clk = "01" then
+            if send_cnt = "111" then
+               if send_words /= send_level then
+                  send_data <= send_read;
+                  send_dma(0) <= '1';
+                  send_enable <= '1';
+               else
+                  send_enable <= '0';
+               end if;
+            else
+               send_data(31 downto 4) <= send_data(27 downto 0);
+            end if;
+            send_cnt <= send_cnt + 1;
+         end if;
+
+         --Pick which type of DMA operation: bit0 = request; bit1 = active
+         if pause_in = '0' then
+            if rec_dma(1) = '1' then
+               rec_dma <= "00";               --DMA done
+               rec_words <= rec_words + 1;
+               if E_RX_DV = '0' then
+                  rec_done <= '1';
+               end if;
+            elsif send_dma(1) = '1' then
+               send_dma <= "00";
+               send_words <= send_words + 1;
+               send_read <= data_read;
+            elsif rec_dma(0) = '1' then
+               rec_dma(1) <= '1';             --start DMA
+            elsif send_dma(0) = '1' then
+               send_dma(1) <= '1';            --start DMA
+            end if;
+         end if;
+
+      end if;  --rising_edge(clk)
+
+      E_TXD <= send_data(31 downto 28);
+      E_TX_EN <= send_enable;
+      rec_isr <= rec_done;
+      if send_words = send_level then
+         send_isr <= '1';
+      else
+         send_isr <= '0';
+      end if;
+
+      if rec_dma(1) = '1' then
+         address <= "0001001111111111" & rec_words;        --0x13ff0000
+         byte_we <= "1111";
+         data_write <= rec_store;
+         pause_out <= '1';                                 --to CPU
+      elsif send_dma(1) = '1' then
+         address <= "000100111111111000000" & send_words;  --0x13fe0000
+         byte_we <= "0000";
+         data_write <= data_w;
+         pause_out <= '1';
+      else
+         address <= mem_address;  --Send request from CPU to DDR
+         byte_we <= mem_byte_we;
+         data_write <= data_w;
+         pause_out <= '0';
+      end if;
+
+   end process;
+
+end; --architecture logic
diff --git a/vhdl/makefile b/vhdl/makefile
new file mode 100644 (file)
index 0000000..0928ec9
--- /dev/null
@@ -0,0 +1,119 @@
+#Makefile for Plasma
+
+#for ModelSim
+#WORK_DIR = work
+#DEP_FILE = _primary.dat
+#COMPILE = vcom -check_synthesis
+
+#for FREE VHDL simulator http://www.symphonyeda.com 
+#WARNING: vhdle now deletes the output.txt if terminated by a ^C
+WORK_DIR = work.sym
+DEP_FILE = prim.dep
+COMPILE = vhdlp -s
+
+all: $(WORK_DIR)/tbench/$(DEP_FILE) 
+
+run: all
+       -@del output.txt
+       vhdle -t 30us tbench
+       type output.txt|more
+
+run2: all
+       -@del output.txt
+       vhdle -t 50us tbench
+       type output.txt|more
+
+run3: all
+       -@del output.txt
+       vhdle -t 100us tbench
+       type output.txt|more
+
+opcodes: all
+       make -C ..\tools opcodes
+       vhdle -t 200us tbench
+       @type output.txt|more
+
+simulate: all
+       vhdle -s -t 10us tbench -do simili.cmd -list trace.txt
+       -@..\tools\tracehex.exe
+       -@start ed trace2.txt
+
+simulate2: all
+       vhdle -s -t 4us tbench -do simili.cmd -list trace.txt
+       -@..\tools\tracehex.exe
+       -@ed trace2.txt
+
+$(WORK_DIR)/lpm_pack/$(DEP_FILE): lpm_pack.vhd
+       $(COMPILE) lpm_pack.vhd
+
+$(WORK_DIR)/lpm_model/$(DEP_FILE): lpm_model.vhd
+       $(COMPILE) -87 lpm_model.vhd
+
+$(WORK_DIR)/mlite_pack/$(DEP_FILE): mlite_pack.vhd
+       $(COMPILE) mlite_pack.vhd
+
+$(WORK_DIR)/alu/$(DEP_FILE): mlite_pack.vhd alu.vhd
+       $(COMPILE) alu.vhd
+
+$(WORK_DIR)/bus_mux/$(DEP_FILE): mlite_pack.vhd bus_mux.vhd
+       $(COMPILE) bus_mux.vhd
+
+$(WORK_DIR)/control/$(DEP_FILE): mlite_pack.vhd control.vhd
+       $(COMPILE) control.vhd
+
+$(WORK_DIR)/mem_ctrl/$(DEP_FILE): mlite_pack.vhd mem_ctrl.vhd
+       $(COMPILE) mem_ctrl.vhd
+
+$(WORK_DIR)/mult/$(DEP_FILE): mlite_pack.vhd mult.vhd
+       $(COMPILE) mult.vhd
+
+$(WORK_DIR)/pc_next/$(DEP_FILE): mlite_pack.vhd pc_next.vhd
+       $(COMPILE) pc_next.vhd
+
+$(WORK_DIR)/reg_bank/$(DEP_FILE): mlite_pack.vhd reg_bank.vhd 
+       $(COMPILE) reg_bank.vhd
+
+$(WORK_DIR)/shifter/$(DEP_FILE): mlite_pack.vhd shifter.vhd
+       $(COMPILE) shifter.vhd
+
+$(WORK_DIR)/pipeline/$(DEP_FILE): mlite_pack.vhd pipeline.vhd
+       $(COMPILE) pipeline.vhd
+
+$(WORK_DIR)/mlite_cpu/$(DEP_FILE): mlite_cpu.vhd \
+       $(WORK_DIR)/mlite_pack/$(DEP_FILE) \
+       $(WORK_DIR)/alu/$(DEP_FILE) \
+       $(WORK_DIR)/bus_mux/$(DEP_FILE) \
+       $(WORK_DIR)/control/$(DEP_FILE) \
+       $(WORK_DIR)/mem_ctrl/$(DEP_FILE) \
+       $(WORK_DIR)/mult/$(DEP_FILE) \
+       $(WORK_DIR)/pc_next/$(DEP_FILE) \
+       $(WORK_DIR)/reg_bank/$(DEP_FILE) \
+       $(WORK_DIR)/shifter/$(DEP_FILE) \
+       $(WORK_DIR)/pipeline/$(DEP_FILE)
+       $(COMPILE) mlite_cpu.vhd
+
+$(WORK_DIR)/ram/$(DEP_FILE): mlite_pack.vhd ram.vhd
+       $(COMPILE) -87 ram.vhd
+
+$(WORK_DIR)/uart/$(DEP_FILE): mlite_pack.vhd uart.vhd
+       $(COMPILE) -87 uart.vhd
+
+$(WORK_DIR)/plasma/$(DEP_FILE): mlite_pack.vhd plasma.vhd \
+       $(WORK_DIR)/mlite_cpu/$(DEP_FILE) \
+       $(WORK_DIR)/ram/$(DEP_FILE) \
+       $(WORK_DIR)/uart/$(DEP_FILE) 
+       $(COMPILE) plasma.vhd
+
+$(WORK_DIR)/plasma_if/$(DEP_FILE): mlite_pack.vhd plasma_if.vhd \
+       $(WORK_DIR)/plasma/$(DEP_FILE) 
+       $(COMPILE) plasma_if.vhd
+
+$(WORK_DIR)/tbench/$(DEP_FILE): mlite_pack.vhd tbench.vhd \
+       $(WORK_DIR)/plasma/$(DEP_FILE) \
+       $(WORK_DIR)/plasma_if/$(DEP_FILE) 
+       $(COMPILE) tbench.vhd
+
+altera: $(WORK_DIR)/lpm_pack/$(DEP_FILE) \
+       $(WORK_DIR)/lpm_model/$(DEP_FILE) 
+       echo UNUSED > UNUSED
+
diff --git a/vhdl/mem_ctrl.vhd b/vhdl/mem_ctrl.vhd
new file mode 100644 (file)
index 0000000..8188f03
--- /dev/null
@@ -0,0 +1,196 @@
+---------------------------------------------------------------------
+-- TITLE: Memory Controller
+-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
+-- DATE CREATED: 1/31/01
+-- FILENAME: mem_ctrl.vhd
+-- PROJECT: Plasma CPU core
+-- COPYRIGHT: Software placed into the public domain by the author.
+--    Software 'as is' without warranty.  Author liable for nothing.
+-- DESCRIPTION:
+--    Memory controller for the Plasma CPU.
+--    Supports Big or Little Endian mode.
+---------------------------------------------------------------------
+library ieee;
+use ieee.std_logic_1164.all;
+use work.mlite_pack.all;
+
+entity mem_ctrl is
+   port(clk          : in std_logic;
+        reset_in     : in std_logic;
+        pause_in     : in std_logic;
+        nullify_op   : in std_logic;
+        address_pc   : in std_logic_vector(31 downto 2);
+        opcode_out   : out std_logic_vector(31 downto 0);
+
+        address_in   : in std_logic_vector(31 downto 0);
+        mem_source   : in mem_source_type;
+        data_write   : in std_logic_vector(31 downto 0);
+        data_read    : out std_logic_vector(31 downto 0);
+        pause_out    : out std_logic;
+        
+        address_next : out std_logic_vector(31 downto 2);
+        byte_we_next : out std_logic_vector(3 downto 0);
+
+        address      : out std_logic_vector(31 downto 2);
+        byte_we      : out std_logic_vector(3 downto 0);
+        data_w       : out std_logic_vector(31 downto 0);
+        data_r       : in std_logic_vector(31 downto 0));
+end; --entity mem_ctrl
+
+architecture logic of mem_ctrl is
+   --"00" = big_endian; "11" = little_endian
+   constant ENDIAN_MODE   : std_logic_vector(1 downto 0) := "00";
+   signal opcode_reg      : std_logic_vector(31 downto 0);
+   signal next_opcode_reg : std_logic_vector(31 downto 0);
+   signal address_reg     : std_logic_vector(31 downto 2);
+   signal byte_we_reg     : std_logic_vector(3 downto 0);
+
+   signal mem_state_reg   : std_logic;
+   constant STATE_ADDR    : std_logic := '0';
+   constant STATE_ACCESS  : std_logic := '1';
+
+begin
+
+mem_proc: process(clk, reset_in, pause_in, nullify_op, 
+                  address_pc, address_in, mem_source, data_write, 
+                  data_r, opcode_reg, next_opcode_reg, mem_state_reg,
+                  address_reg, byte_we_reg)
+   variable address_var    : std_logic_vector(31 downto 2);
+   variable data_read_var  : std_logic_vector(31 downto 0);
+   variable data_write_var : std_logic_vector(31 downto 0);
+   variable opcode_next    : std_logic_vector(31 downto 0);
+   variable byte_we_var    : std_logic_vector(3 downto 0);
+   variable mem_state_next : std_logic;
+   variable pause_var      : std_logic;
+   variable bits           : std_logic_vector(1 downto 0);
+begin
+   byte_we_var := "0000";
+   pause_var := '0';
+   data_read_var := ZERO;
+   data_write_var := ZERO;
+   mem_state_next := mem_state_reg;
+   opcode_next := opcode_reg;
+
+   case mem_source is
+   when MEM_READ32 =>
+      data_read_var := data_r;
+
+   when MEM_READ16 | MEM_READ16S =>
+      if address_in(1) = ENDIAN_MODE(1) then
+         data_read_var(15 downto 0) := data_r(31 downto 16);
+      else
+         data_read_var(15 downto 0) := data_r(15 downto 0);
+      end if;
+      if mem_source = MEM_READ16 or data_read_var(15) = '0' then
+         data_read_var(31 downto 16) := ZERO(31 downto 16);
+      else
+         data_read_var(31 downto 16) := ONES(31 downto 16);
+      end if;
+
+   when MEM_READ8 | MEM_READ8S =>
+      bits := address_in(1 downto 0) xor ENDIAN_MODE;
+      case bits is
+      when "00" => data_read_var(7 downto 0) := data_r(31 downto 24);
+      when "01" => data_read_var(7 downto 0) := data_r(23 downto 16);
+      when "10" => data_read_var(7 downto 0) := data_r(15 downto 8);
+      when others => data_read_var(7 downto 0) := data_r(7 downto 0);
+      end case;
+      if mem_source = MEM_READ8 or data_read_var(7) = '0' then
+         data_read_var(31 downto 8) := ZERO(31 downto 8);
+      else
+         data_read_var(31 downto 8) := ONES(31 downto 8);
+      end if;
+
+   when MEM_WRITE32 =>
+      data_write_var := data_write;
+      byte_we_var := "1111";
+
+   when MEM_WRITE16 =>
+      data_write_var := data_write(15 downto 0) & data_write(15 downto 0);
+      if address_in(1) = ENDIAN_MODE(1) then
+         byte_we_var := "1100";
+      else
+         byte_we_var := "0011";
+      end if;
+
+   when MEM_WRITE8 =>
+      data_write_var := data_write(7 downto 0) & data_write(7 downto 0) &
+                  data_write(7 downto 0) & data_write(7 downto 0);
+      bits := address_in(1 downto 0) xor ENDIAN_MODE;
+      case bits is
+      when "00" =>
+         byte_we_var := "1000"; 
+      when "01" => 
+         byte_we_var := "0100"; 
+      when "10" =>
+         byte_we_var := "0010"; 
+      when others =>
+         byte_we_var := "0001"; 
+      end case;
+
+   when others =>
+   end case;
+
+   if mem_source = MEM_FETCH then --opcode fetch
+      address_var := address_pc;
+      opcode_next := data_r;
+      mem_state_next := STATE_ADDR;
+   else
+      if mem_state_reg = STATE_ADDR then
+         if pause_in = '0' then
+            address_var := address_in(31 downto 2);
+            mem_state_next := STATE_ACCESS;
+            pause_var := '1';
+         else
+            address_var := address_pc;
+            byte_we_var := "0000";
+         end if;
+      else  --STATE_ACCESS
+         if pause_in = '0' then
+            address_var := address_pc;
+            opcode_next := next_opcode_reg;
+            mem_state_next := STATE_ADDR;
+            byte_we_var := "0000";
+         else
+            address_var := address_in(31 downto 2);
+            byte_we_var := "0000";
+         end if;
+      end if;
+   end if;
+
+   if nullify_op = '1' and pause_in = '0' then
+      opcode_next := ZERO;  --NOP after beql
+   end if;
+
+   if reset_in = '1' then
+      mem_state_reg <= STATE_ADDR;
+      opcode_reg <= ZERO;
+      next_opcode_reg <= ZERO;
+      address_reg <= ZERO(31 downto 2);
+      byte_we_reg <= "0000";
+   elsif rising_edge(clk) then
+      if pause_in = '0' then
+         address_reg <= address_var;
+         byte_we_reg <= byte_we_var;
+         mem_state_reg <= mem_state_next;
+         opcode_reg <= opcode_next;
+         if mem_state_reg = STATE_ADDR then
+            next_opcode_reg <= data_r;
+         end if;
+      end if;
+   end if;
+
+   opcode_out <= opcode_reg;
+   data_read <= data_read_var;
+   pause_out <= pause_var;
+
+   address_next <= address_var;
+   byte_we_next <= byte_we_var;
+
+   address <= address_reg;
+   byte_we <= byte_we_reg;
+   data_w <= data_write_var;
+
+end process; --data_proc
+
+end; --architecture logic
diff --git a/vhdl/mlite_cpu.vhd b/vhdl/mlite_cpu.vhd
new file mode 100644 (file)
index 0000000..c512661
--- /dev/null
@@ -0,0 +1,342 @@
+---------------------------------------------------------------------
+-- TITLE: Plasma CPU core
+-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
+-- DATE CREATED: 2/15/01
+-- FILENAME: mlite_cpu.vhd
+-- PROJECT: Plasma CPU core
+-- COPYRIGHT: Software placed into the public domain by the author.
+--    Software 'as is' without warranty.  Author liable for nothing.
+-- NOTE:  MIPS(tm) and MIPS I(tm) are registered trademarks of MIPS 
+--    Technologies.  MIPS Technologies does not endorse and is not 
+--    associated with this project.
+-- DESCRIPTION:
+--    Top level VHDL document that ties the nine other entities together.
+--
+-- Executes all MIPS I(tm) opcodes but exceptions and non-aligned
+-- memory accesses.  Based on information found in:
+--    "MIPS RISC Architecture" by Gerry Kane and Joe Heinrich
+--    and "The Designer's Guide to VHDL" by Peter J. Ashenden
+--
+-- The CPU is implemented as a two or three stage pipeline.
+-- An add instruction would take the following steps (see cpu.gif):
+-- Stage #0:
+--    1.  The "pc_next" entity passes the program counter (PC) to the 
+--        "mem_ctrl" entity which fetches the opcode from memory.
+-- Stage #1:
+--    2.  The memory returns the opcode.
+-- Stage #2:
+--    3.  "Mem_ctrl" passes the opcode to the "control" entity.
+--    4.  "Control" converts the 32-bit opcode to a 60-bit VLWI opcode
+--        and sends control signals to the other entities.
+--    5.  Based on the rs_index and rt_index control signals, "reg_bank" 
+--        sends the 32-bit reg_source and reg_target to "bus_mux".
+--    6.  Based on the a_source and b_source control signals, "bus_mux"
+--        multiplexes reg_source onto a_bus and reg_target onto b_bus.
+-- Stage #3 (part of stage #2 if using two stage pipeline):
+--    7.  Based on the alu_func control signals, "alu" adds the values
+--        from a_bus and b_bus and places the result on c_bus.
+--    8.  Based on the c_source control signals, "bus_bux" multiplexes
+--        c_bus onto reg_dest.
+--    9.  Based on the rd_index control signal, "reg_bank" saves
+--        reg_dest into the correct register.
+-- Stage #3b:
+--   10.  Read or write memory if needed.
+--
+-- All signals are active high. 
+-- Here are the signals for writing a character to address 0xffff
+-- when using a two stage pipeline:
+--
+-- Program:
+-- addr     value  opcode 
+-- =============================
+--   3c: 00000000  nop
+--   40: 34040041  li $a0,0x41
+--   44: 3405ffff  li $a1,0xffff
+--   48: a0a40000  sb $a0,0($a1)
+--   4c: 00000000  nop
+--   50: 00000000  nop
+--
+--      intr_in                             mem_pause 
+--  reset_in                               byte_we     Stages
+--     ns         address     data_w     data_r        40 44 48 4c 50
+--   3600  0  0  00000040   00000000   34040041  0  0   1  
+--   3700  0  0  00000044   00000000   3405FFFF  0  0   2  1  
+--   3800  0  0  00000048   00000000   A0A40000  0  0      2  1  
+--   3900  0  0  0000004C   41414141   00000000  0  0         2  1
+--   4000  0  0  0000FFFC   41414141   XXXXXX41  1  0         3  2  
+--   4100  0  0  00000050   00000000   00000000  0  0               1
+---------------------------------------------------------------------
+library ieee;
+use work.mlite_pack.all;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+
+entity mlite_cpu is
+   generic(memory_type     : string  := "XILINX_16X"; --ALTERA_LPM, or DUAL_PORT_
+           mult_type       : string  := "DEFAULT"; --AREA_OPTIMIZED
+           shifter_type    : string  := "DEFAULT"; --AREA_OPTIMIZED
+           alu_type        : string  := "DEFAULT"; --AREA_OPTIMIZED
+           pipeline_stages : natural := 2); --2 or 3
+   port(clk          : in std_logic;
+        reset_in     : in std_logic;
+        intr_in      : in std_logic;
+
+        address_next : out std_logic_vector(31 downto 2); --for synch ram
+        byte_we_next : out std_logic_vector(3 downto 0); 
+
+        address      : out std_logic_vector(31 downto 2);
+        byte_we      : out std_logic_vector(3 downto 0);
+        data_w       : out std_logic_vector(31 downto 0);
+        data_r       : in std_logic_vector(31 downto 0);
+        mem_pause    : in std_logic);
+end; --entity mlite_cpu
+
+architecture logic of mlite_cpu is
+   --When using a two stage pipeline "sigD <= sig".
+   --When using a three stage pipeline "sigD <= sig when rising_edge(clk)",
+   --  so sigD is delayed by one clock cycle.
+   signal opcode         : std_logic_vector(31 downto 0);
+   signal rs_index       : std_logic_vector(5 downto 0);
+   signal rt_index       : std_logic_vector(5 downto 0);
+   signal rd_index       : std_logic_vector(5 downto 0);
+   signal rd_indexD      : std_logic_vector(5 downto 0);
+   signal reg_source     : std_logic_vector(31 downto 0);
+   signal reg_target     : std_logic_vector(31 downto 0);
+   signal reg_dest       : std_logic_vector(31 downto 0);
+   signal reg_destD      : std_logic_vector(31 downto 0);
+   signal a_bus          : std_logic_vector(31 downto 0);
+   signal a_busD         : std_logic_vector(31 downto 0);
+   signal b_bus          : std_logic_vector(31 downto 0);
+   signal b_busD         : std_logic_vector(31 downto 0);
+   signal c_bus          : std_logic_vector(31 downto 0);
+   signal c_alu          : std_logic_vector(31 downto 0);
+   signal c_shift        : std_logic_vector(31 downto 0);
+   signal c_mult         : std_logic_vector(31 downto 0);
+   signal c_memory       : std_logic_vector(31 downto 0);
+   signal imm            : std_logic_vector(15 downto 0);
+   signal pc_future      : std_logic_vector(31 downto 2);
+   signal pc_current     : std_logic_vector(31 downto 2);
+   signal pc_plus4       : std_logic_vector(31 downto 2);
+   signal alu_func       : alu_function_type;
+   signal alu_funcD      : alu_function_type;
+   signal shift_func     : shift_function_type;
+   signal shift_funcD    : shift_function_type;
+   signal mult_func      : mult_function_type;
+   signal mult_funcD     : mult_function_type;
+   signal branch_func    : branch_function_type;
+   signal take_branch    : std_logic;
+   signal a_source       : a_source_type;
+   signal b_source       : b_source_type;
+   signal c_source       : c_source_type;
+   signal pc_source      : pc_source_type;
+   signal mem_source     : mem_source_type;
+   signal pause_mult     : std_logic;
+   signal pause_ctrl     : std_logic;
+   signal pause_pipeline : std_logic;
+   signal pause_any      : std_logic;
+   signal pause_non_ctrl : std_logic;
+   signal pause_bank     : std_logic;
+   signal nullify_op     : std_logic;
+   signal intr_enable    : std_logic;
+   signal intr_signal    : std_logic;
+   signal exception_sig  : std_logic;
+   signal reset_reg      : std_logic_vector(3 downto 0);
+   signal reset          : std_logic;
+begin  --architecture
+
+   pause_any <= (mem_pause or pause_ctrl) or (pause_mult or pause_pipeline);
+   pause_non_ctrl <= (mem_pause or pause_mult) or pause_pipeline;
+   pause_bank <= (mem_pause or pause_ctrl or pause_mult) and not pause_pipeline;
+   nullify_op <= '1' when (pc_source = FROM_LBRANCH and take_branch = '0')
+                          or intr_signal = '1' or exception_sig = '1'
+                          else '0';
+   c_bus <= c_alu or c_shift or c_mult;
+   reset <= '1' when reset_in = '1' or reset_reg /= "1111" else '0';
+
+   --synchronize reset and interrupt pins
+   intr_proc: process(clk, reset_in, reset_reg, intr_in, intr_enable, 
+      pc_source, pc_current, pause_any)
+   begin
+      if reset_in = '1' then
+         reset_reg <= "0000";
+         intr_signal <= '0';
+      elsif rising_edge(clk) then
+         if reset_reg /= "1111" then
+            reset_reg <= reset_reg + 1;
+         end if;
+
+         --don't try to interrupt a multi-cycle instruction
+         if pause_any = '0' then
+            if intr_in = '1' and intr_enable = '1' and 
+                  pc_source = FROM_INC4 then
+               --the epc will contain pc+4
+               intr_signal <= '1';
+            else
+               intr_signal <= '0';
+            end if;
+         end if;
+
+      end if;
+   end process;
+
+   u1_pc_next: pc_next PORT MAP (
+        clk          => clk,
+        reset_in     => reset,
+        take_branch  => take_branch,
+        pause_in     => pause_any,
+        pc_new       => c_bus(31 downto 2),
+        opcode25_0   => opcode(25 downto 0),
+        pc_source    => pc_source,
+        pc_future    => pc_future,
+        pc_current   => pc_current,
+        pc_plus4     => pc_plus4);
+
+   u2_mem_ctrl: mem_ctrl 
+      PORT MAP (
+        clk          => clk,
+        reset_in     => reset,
+        pause_in     => pause_non_ctrl,
+        nullify_op   => nullify_op,
+        address_pc   => pc_future,
+        opcode_out   => opcode,
+
+        address_in   => c_bus,
+        mem_source   => mem_source,
+        data_write   => reg_target,
+        data_read    => c_memory,
+        pause_out    => pause_ctrl,
+        
+        address_next => address_next,
+        byte_we_next => byte_we_next,
+
+        address      => address,
+        byte_we      => byte_we,
+        data_w       => data_w,
+        data_r       => data_r);
+
+   u3_control: control PORT MAP (
+        opcode       => opcode,
+        intr_signal  => intr_signal,
+        rs_index     => rs_index,
+        rt_index     => rt_index,
+        rd_index     => rd_index,
+        imm_out      => imm,
+        alu_func     => alu_func,
+        shift_func   => shift_func,
+        mult_func    => mult_func,
+        branch_func  => branch_func,
+        a_source_out => a_source,
+        b_source_out => b_source,
+        c_source_out => c_source,
+        pc_source_out=> pc_source,
+        mem_source_out=> mem_source,
+        exception_out=> exception_sig);
+
+   u4_reg_bank: reg_bank 
+      generic map(memory_type => memory_type)
+      port map (
+        clk            => clk,
+        reset_in       => reset,
+        pause          => pause_bank,
+        rs_index       => rs_index,
+        rt_index       => rt_index,
+        rd_index       => rd_indexD,
+        reg_source_out => reg_source,
+        reg_target_out => reg_target,
+        reg_dest_new   => reg_destD,
+        intr_enable    => intr_enable);
+
+   u5_bus_mux: bus_mux port map (
+        imm_in       => imm,
+        reg_source   => reg_source,
+        a_mux        => a_source,
+        a_out        => a_bus,
+
+        reg_target   => reg_target,
+        b_mux        => b_source,
+        b_out        => b_bus,
+
+        c_bus        => c_bus,
+        c_memory     => c_memory,
+        c_pc         => pc_current,
+        c_pc_plus4   => pc_plus4,
+        c_mux        => c_source,
+        reg_dest_out => reg_dest,
+
+        branch_func  => branch_func,
+        take_branch  => take_branch);
+
+   u6_alu: alu 
+      generic map (alu_type => alu_type)
+      port map (
+        a_in         => a_busD,
+        b_in         => b_busD,
+        alu_function => alu_funcD,
+        c_alu        => c_alu);
+
+   u7_shifter: shifter
+      generic map (shifter_type => shifter_type)
+      port map (
+        value        => b_busD,
+        shift_amount => a_busD(4 downto 0),
+        shift_func   => shift_funcD,
+        c_shift      => c_shift);
+
+   u8_mult: mult 
+      generic map (mult_type => mult_type)
+      port map (
+        clk       => clk,
+        reset_in  => reset,
+        a         => a_busD,
+        b         => b_busD,
+        mult_func => mult_funcD,
+        c_mult    => c_mult,
+        pause_out => pause_mult);
+
+   pipeline2: if pipeline_stages <= 2 generate
+      a_busD <= a_bus;
+      b_busD <= b_bus;
+      alu_funcD <= alu_func;
+      shift_funcD <= shift_func;
+      mult_funcD <= mult_func;
+      rd_indexD <= rd_index;
+      reg_destD <= reg_dest;
+      pause_pipeline <= '0';
+   end generate; --pipeline2
+
+   pipeline3: if pipeline_stages > 2 generate
+      --When operating in three stage pipeline mode, the following signals
+      --are delayed by one clock cycle:  a_bus, b_bus, alu/shift/mult_func,
+      --c_source, and rd_index.
+   u9_pipeline: pipeline port map (
+        clk            => clk,
+        reset          => reset,
+        a_bus          => a_bus,
+        a_busD         => a_busD,
+        b_bus          => b_bus,
+        b_busD         => b_busD,
+        alu_func       => alu_func,
+        alu_funcD      => alu_funcD,
+        shift_func     => shift_func,
+        shift_funcD    => shift_funcD,
+        mult_func      => mult_func,
+        mult_funcD     => mult_funcD,
+        reg_dest       => reg_dest,
+        reg_destD      => reg_destD,
+        rd_index       => rd_index,
+        rd_indexD      => rd_indexD,
+
+        rs_index       => rs_index,
+        rt_index       => rt_index,
+        pc_source      => pc_source,
+        mem_source     => mem_source,
+        a_source       => a_source,
+        b_source       => b_source,
+        c_source       => c_source,
+        c_bus          => c_bus,
+        pause_any      => pause_any,
+        pause_pipeline => pause_pipeline);
+
+   end generate; --pipeline3
+
+end; --architecture logic
diff --git a/vhdl/mlite_pack.vhd b/vhdl/mlite_pack.vhd
new file mode 100644 (file)
index 0000000..f6e37a6
--- /dev/null
@@ -0,0 +1,563 @@
+---------------------------------------------------------------------
+-- TITLE: Plasma Misc. Package
+-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
+-- DATE CREATED: 2/15/01
+-- FILENAME: mlite_pack.vhd
+-- PROJECT: Plasma CPU core
+-- COPYRIGHT: Software placed into the public domain by the author.
+--    Software 'as is' without warranty.  Author liable for nothing.
+-- DESCRIPTION:
+--    Data types, constants, and add functions needed for the Plasma CPU.
+---------------------------------------------------------------------
+library ieee;
+use ieee.std_logic_1164.all;
+
+package mlite_pack is
+   constant ZERO          : std_logic_vector(31 downto 0) :=
+      "00000000000000000000000000000000";
+   constant ONES          : std_logic_vector(31 downto 0) :=
+      "11111111111111111111111111111111";
+   --make HIGH_Z equal to ZERO if compiler complains
+   constant HIGH_Z        : std_logic_vector(31 downto 0) :=
+      "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ";
+  
+   subtype alu_function_type is std_logic_vector(3 downto 0);
+   constant ALU_NOTHING   : alu_function_type := "0000";
+   constant ALU_ADD       : alu_function_type := "0001";
+   constant ALU_SUBTRACT  : alu_function_type := "0010";
+   constant ALU_LESS_THAN : alu_function_type := "0011";
+   constant ALU_LESS_THAN_SIGNED : alu_function_type := "0100";
+   constant ALU_OR        : alu_function_type := "0101";
+   constant ALU_AND       : alu_function_type := "0110";
+   constant ALU_XOR       : alu_function_type := "0111";
+   constant ALU_NOR       : alu_function_type := "1000";
+
+   subtype shift_function_type is std_logic_vector(1 downto 0);
+   constant SHIFT_NOTHING        : shift_function_type := "00";
+   constant SHIFT_LEFT_UNSIGNED  : shift_function_type := "01";
+   constant SHIFT_RIGHT_SIGNED   : shift_function_type := "11";
+   constant SHIFT_RIGHT_UNSIGNED : shift_function_type := "10";
+
+   subtype mult_function_type is std_logic_vector(3 downto 0);
+   constant MULT_NOTHING       : mult_function_type := "0000";
+   constant MULT_READ_LO       : mult_function_type := "0001";
+   constant MULT_READ_HI       : mult_function_type := "0010";
+   constant MULT_WRITE_LO      : mult_function_type := "0011";
+   constant MULT_WRITE_HI      : mult_function_type := "0100";
+   constant MULT_MULT          : mult_function_type := "0101";
+   constant MULT_SIGNED_MULT   : mult_function_type := "0110";
+   constant MULT_DIVIDE        : mult_function_type := "0111";
+   constant MULT_SIGNED_DIVIDE : mult_function_type := "1000";
+
+   subtype a_source_type is std_logic_vector(1 downto 0);
+   constant A_FROM_REG_SOURCE : a_source_type := "00";
+   constant A_FROM_IMM10_6    : a_source_type := "01";
+   constant A_FROM_PC         : a_source_type := "10";
+
+   subtype b_source_type is std_logic_vector(1 downto 0);
+   constant B_FROM_REG_TARGET : b_source_type := "00";
+   constant B_FROM_IMM        : b_source_type := "01";
+   constant B_FROM_SIGNED_IMM : b_source_type := "10";
+   constant B_FROM_IMMX4      : b_source_type := "11";
+
+   subtype c_source_type is std_logic_vector(2 downto 0);
+   constant C_FROM_NULL       : c_source_type := "000";
+   constant C_FROM_ALU        : c_source_type := "001";
+   constant C_FROM_SHIFT      : c_source_type := "001"; --same as alu
+   constant C_FROM_MULT       : c_source_type := "001"; --same as alu
+   constant C_FROM_MEMORY     : c_source_type := "010";
+   constant C_FROM_PC         : c_source_type := "011";
+   constant C_FROM_PC_PLUS4   : c_source_type := "100";
+   constant C_FROM_IMM_SHIFT16: c_source_type := "101";
+   constant C_FROM_REG_SOURCEN: c_source_type := "110";
+
+   subtype pc_source_type is std_logic_vector(1 downto 0);
+   constant FROM_INC4       : pc_source_type := "00";
+   constant FROM_OPCODE25_0 : pc_source_type := "01";
+   constant FROM_BRANCH     : pc_source_type := "10";
+   constant FROM_LBRANCH    : pc_source_type := "11";
+
+   subtype branch_function_type is std_logic_vector(2 downto 0);
+   constant BRANCH_LTZ : branch_function_type := "000";
+   constant BRANCH_LEZ : branch_function_type := "001";
+   constant BRANCH_EQ  : branch_function_type := "010";
+   constant BRANCH_NE  : branch_function_type := "011";
+   constant BRANCH_GEZ : branch_function_type := "100";
+   constant BRANCH_GTZ : branch_function_type := "101";
+   constant BRANCH_YES : branch_function_type := "110";
+   constant BRANCH_NO  : branch_function_type := "111";
+
+   -- mode(32=1,16=2,8=3), signed, write
+   subtype mem_source_type is std_logic_vector(3 downto 0);
+   constant MEM_FETCH   : mem_source_type := "0000";
+   constant MEM_READ32  : mem_source_type := "0100";
+   constant MEM_WRITE32 : mem_source_type := "0101";
+   constant MEM_READ16  : mem_source_type := "1000";
+   constant MEM_READ16S : mem_source_type := "1010";
+   constant MEM_WRITE16 : mem_source_type := "1001";
+   constant MEM_READ8   : mem_source_type := "1100";
+   constant MEM_READ8S  : mem_source_type := "1110";
+   constant MEM_WRITE8  : mem_source_type := "1101";
+
+   function bv_adder(a     : in std_logic_vector;
+                     b     : in std_logic_vector;
+                     do_add: in std_logic) return std_logic_vector;
+   function bv_negate(a : in std_logic_vector) return std_logic_vector;
+   function bv_increment(a : in std_logic_vector(31 downto 2)
+                         ) return std_logic_vector;
+   function bv_inc(a : in std_logic_vector
+                  ) return std_logic_vector;
+
+   -- For Altera
+   COMPONENT lpm_ram_dp
+      generic (
+         LPM_WIDTH : natural;    -- MUST be greater than 0
+         LPM_WIDTHAD : natural;    -- MUST be greater than 0
+         LPM_NUMWORDS : natural := 0;
+         LPM_INDATA : string := "REGISTERED";
+         LPM_OUTDATA : string := "REGISTERED";
+         LPM_RDADDRESS_CONTROL : string := "REGISTERED";
+         LPM_WRADDRESS_CONTROL : string := "REGISTERED";
+         LPM_FILE : string := "UNUSED";
+         LPM_TYPE : string := "LPM_RAM_DP";
+         USE_EAB  : string := "OFF";
+         INTENDED_DEVICE_FAMILY  : string := "UNUSED";
+         RDEN_USED  : string := "TRUE";
+         LPM_HINT : string := "UNUSED");
+      port (
+         RDCLOCK   : in std_logic := '0';
+         RDCLKEN   : in std_logic := '1';
+         RDADDRESS : in std_logic_vector(LPM_WIDTHAD-1 downto 0);
+         RDEN      : in std_logic := '1';
+         DATA      : in std_logic_vector(LPM_WIDTH-1 downto 0);
+         WRADDRESS : in std_logic_vector(LPM_WIDTHAD-1 downto 0);
+         WREN      : in std_logic;
+         WRCLOCK   : in std_logic := '0';
+         WRCLKEN   : in std_logic := '1';
+         Q         : out std_logic_vector(LPM_WIDTH-1 downto 0));
+   END COMPONENT;
+
+   -- For Altera
+   component LPM_RAM_DQ
+      generic (
+         LPM_WIDTH    : natural;    -- MUST be greater than 0
+         LPM_WIDTHAD  : natural;    -- MUST be greater than 0
+         LPM_NUMWORDS : natural := 0;
+         LPM_INDATA   : string := "REGISTERED";
+         LPM_ADDRESS_CONTROL: string := "REGISTERED";
+         LPM_OUTDATA  : string := "REGISTERED";
+         LPM_FILE     : string := "UNUSED";
+         LPM_TYPE     : string := "LPM_RAM_DQ";
+         USE_EAB      : string := "OFF";
+         INTENDED_DEVICE_FAMILY  : string := "UNUSED";
+         LPM_HINT     : string := "UNUSED");
+               port (
+         DATA     : in std_logic_vector(LPM_WIDTH-1 downto 0);
+         ADDRESS  : in std_logic_vector(LPM_WIDTHAD-1 downto 0);
+         INCLOCK  : in std_logic := '0';
+         OUTCLOCK : in std_logic := '0';
+         WE       : in std_logic;
+         Q        : out std_logic_vector(LPM_WIDTH-1 downto 0));
+   end component;
+
+   -- For Xilinx
+   component RAM16X1D 
+      -- synthesis translate_off 
+      generic (INIT : bit_vector := X"16"); 
+      -- synthesis translate_on 
+      port (DPO   : out STD_ULOGIC; 
+            SPO   : out STD_ULOGIC; 
+            A0    : in STD_ULOGIC; 
+            A1    : in STD_ULOGIC; 
+            A2    : in STD_ULOGIC; 
+            A3    : in STD_ULOGIC; 
+            D     : in STD_ULOGIC; 
+            DPRA0 : in STD_ULOGIC; 
+            DPRA1 : in STD_ULOGIC; 
+            DPRA2 : in STD_ULOGIC; 
+            DPRA3 : in STD_ULOGIC; 
+            WCLK  : in STD_ULOGIC; 
+            WE    : in STD_ULOGIC); 
+   end component;\r
+       \r
+   -- For Xilinx Virtex-5
+   component RAM32X1D 
+      -- synthesis translate_off 
+      generic (INIT : bit_vector := X"32"); 
+      -- synthesis translate_on 
+      port (DPO   : out STD_ULOGIC; 
+            SPO   : out STD_ULOGIC; 
+            A0    : in STD_ULOGIC; 
+            A1    : in STD_ULOGIC; 
+            A2    : in STD_ULOGIC; 
+            A3    : in STD_ULOGIC; 
+            A4    : in STD_ULOGIC; 
+            D     : in STD_ULOGIC; 
+            DPRA0 : in STD_ULOGIC; 
+            DPRA1 : in STD_ULOGIC; 
+            DPRA2 : in STD_ULOGIC; 
+            DPRA3 : in STD_ULOGIC; 
+            DPRA4 : in STD_ULOGIC; 
+            WCLK  : in STD_ULOGIC; 
+            WE    : in STD_ULOGIC); 
+   end component; 
+       
+   component pc_next
+      port(clk         : in std_logic;
+           reset_in    : in std_logic;
+           pc_new      : in std_logic_vector(31 downto 2);
+           take_branch : in std_logic;
+           pause_in    : in std_logic;
+           opcode25_0  : in std_logic_vector(25 downto 0);
+           pc_source   : in pc_source_type;
+           pc_future   : out std_logic_vector(31 downto 2);
+           pc_current  : out std_logic_vector(31 downto 2);
+           pc_plus4    : out std_logic_vector(31 downto 2));
+   end component;
+
+   component mem_ctrl
+      port(clk          : in std_logic;
+           reset_in     : in std_logic;
+           pause_in     : in std_logic;
+           nullify_op   : in std_logic;
+           address_pc   : in std_logic_vector(31 downto 2);
+           opcode_out   : out std_logic_vector(31 downto 0);
+
+           address_in   : in std_logic_vector(31 downto 0);
+           mem_source   : in mem_source_type;
+           data_write   : in std_logic_vector(31 downto 0);
+           data_read    : out std_logic_vector(31 downto 0);
+           pause_out    : out std_logic;
+
+           address_next : out std_logic_vector(31 downto 2);
+           byte_we_next : out std_logic_vector(3 downto 0);
+
+           address      : out std_logic_vector(31 downto 2);
+           byte_we      : out std_logic_vector(3 downto 0);
+           data_w       : out std_logic_vector(31 downto 0);
+           data_r       : in std_logic_vector(31 downto 0));
+   end component;
+
+   component control 
+      port(opcode       : in  std_logic_vector(31 downto 0);
+           intr_signal  : in  std_logic;
+           rs_index     : out std_logic_vector(5 downto 0);
+           rt_index     : out std_logic_vector(5 downto 0);
+           rd_index     : out std_logic_vector(5 downto 0);
+           imm_out      : out std_logic_vector(15 downto 0);
+           alu_func     : out alu_function_type;
+           shift_func   : out shift_function_type;
+           mult_func    : out mult_function_type;
+           branch_func  : out branch_function_type;
+           a_source_out : out a_source_type;
+           b_source_out : out b_source_type;
+           c_source_out : out c_source_type;
+           pc_source_out: out pc_source_type;
+           mem_source_out:out mem_source_type;
+           exception_out: out std_logic);
+   end component;
+
+   component reg_bank
+      generic(memory_type : string := "XILINX_16X");
+      port(clk            : in  std_logic;
+           reset_in       : in  std_logic;
+           pause          : in  std_logic;
+           rs_index       : in  std_logic_vector(5 downto 0);
+           rt_index       : in  std_logic_vector(5 downto 0);
+           rd_index       : in  std_logic_vector(5 downto 0);
+           reg_source_out : out std_logic_vector(31 downto 0);
+           reg_target_out : out std_logic_vector(31 downto 0);
+           reg_dest_new   : in  std_logic_vector(31 downto 0);
+           intr_enable    : out std_logic);
+   end component;
+
+   component bus_mux 
+      port(imm_in       : in  std_logic_vector(15 downto 0);
+           reg_source   : in  std_logic_vector(31 downto 0);
+           a_mux        : in  a_source_type;
+           a_out        : out std_logic_vector(31 downto 0);
+
+           reg_target   : in  std_logic_vector(31 downto 0);
+           b_mux        : in  b_source_type;
+           b_out        : out std_logic_vector(31 downto 0);
+
+           c_bus        : in  std_logic_vector(31 downto 0);
+           c_memory     : in  std_logic_vector(31 downto 0);
+           c_pc         : in  std_logic_vector(31 downto 2);
+           c_pc_plus4   : in  std_logic_vector(31 downto 2);
+           c_mux        : in  c_source_type;
+           reg_dest_out : out std_logic_vector(31 downto 0);
+
+           branch_func  : in  branch_function_type;
+           take_branch  : out std_logic);
+   end component;
+
+   component alu
+      generic(alu_type  : string := "DEFAULT");
+      port(a_in         : in  std_logic_vector(31 downto 0);
+           b_in         : in  std_logic_vector(31 downto 0);
+           alu_function : in  alu_function_type;
+           c_alu        : out std_logic_vector(31 downto 0));
+   end component;
+
+   component shifter
+      generic(shifter_type : string := "DEFAULT" );
+      port(value        : in  std_logic_vector(31 downto 0);
+           shift_amount : in  std_logic_vector(4 downto 0);
+           shift_func   : in  shift_function_type;
+           c_shift      : out std_logic_vector(31 downto 0));
+   end component;
+
+   component mult
+      generic(mult_type  : string := "DEFAULT"); 
+      port(clk       : in  std_logic;
+           reset_in  : in  std_logic;
+           a, b      : in  std_logic_vector(31 downto 0);
+           mult_func : in  mult_function_type;
+           c_mult    : out std_logic_vector(31 downto 0);
+           pause_out : out std_logic); 
+   end component;
+
+   component pipeline
+      port(clk            : in  std_logic;
+           reset          : in  std_logic;
+           a_bus          : in  std_logic_vector(31 downto 0);
+           a_busD         : out std_logic_vector(31 downto 0);
+           b_bus          : in  std_logic_vector(31 downto 0);
+           b_busD         : out std_logic_vector(31 downto 0);
+           alu_func       : in  alu_function_type;
+           alu_funcD      : out alu_function_type;
+           shift_func     : in  shift_function_type;
+           shift_funcD    : out shift_function_type;
+           mult_func      : in  mult_function_type;
+           mult_funcD     : out mult_function_type;
+           reg_dest       : in  std_logic_vector(31 downto 0);
+           reg_destD      : out std_logic_vector(31 downto 0);
+           rd_index       : in  std_logic_vector(5 downto 0);
+           rd_indexD      : out std_logic_vector(5 downto 0);
+
+           rs_index       : in  std_logic_vector(5 downto 0);
+           rt_index       : in  std_logic_vector(5 downto 0);
+           pc_source      : in  pc_source_type;
+           mem_source     : in  mem_source_type;
+           a_source       : in  a_source_type;
+           b_source       : in  b_source_type;
+           c_source       : in  c_source_type;
+           c_bus          : in  std_logic_vector(31 downto 0);
+           pause_any      : in  std_logic;
+           pause_pipeline : out std_logic);
+   end component;
+
+   component mlite_cpu
+      generic(memory_type     : string := "XILINX_16X"; --ALTERA_LPM, or DUAL_PORT_
+              mult_type       : string := "DEFAULT";
+              shifter_type    : string := "DEFAULT";
+              alu_type        : string := "DEFAULT";
+              pipeline_stages : natural := 2); --2 or 3
+      port(clk         : in std_logic;
+           reset_in    : in std_logic;
+           intr_in     : in std_logic;
+
+           address_next : out std_logic_vector(31 downto 2); --for synch ram
+           byte_we_next : out std_logic_vector(3 downto 0); 
+
+           address      : out std_logic_vector(31 downto 2);
+           byte_we      : out std_logic_vector(3 downto 0);
+           data_w       : out std_logic_vector(31 downto 0);
+           data_r       : in std_logic_vector(31 downto 0);
+           mem_pause    : in std_logic);
+   end component;
+
+   component cache
+      generic(memory_type : string := "DEFAULT");
+      port(clk            : in std_logic;
+           reset          : in std_logic;
+           address_next   : in std_logic_vector(31 downto 2);
+           byte_we_next   : in std_logic_vector(3 downto 0);
+           cpu_address    : in std_logic_vector(31 downto 2);
+           mem_busy       : in std_logic;
+
+           cache_access   : out std_logic;   --access 4KB cache
+           cache_checking : out std_logic;   --checking if cache hit
+           cache_miss     : out std_logic);  --cache miss
+   end component; --cache
+
+   component ram
+      generic(memory_type : string := "DEFAULT");
+      port(clk               : in std_logic;
+           enable            : in std_logic;
+           write_byte_enable : in std_logic_vector(3 downto 0);
+           address           : in std_logic_vector(31 downto 2);
+           data_write        : in std_logic_vector(31 downto 0);
+           data_read         : out std_logic_vector(31 downto 0));
+   end component; --ram
+   
+   component uart
+      generic(log_file : string := "UNUSED");
+      port(clk          : in std_logic;
+           reset        : in std_logic;
+           enable_read  : in std_logic;
+           enable_write : in std_logic;
+           data_in      : in std_logic_vector(7 downto 0);
+           data_out     : out std_logic_vector(7 downto 0);
+           uart_read    : in std_logic;
+           uart_write   : out std_logic;
+           busy_write   : out std_logic;
+           data_avail   : out std_logic);
+   end component; --uart
+
+   component eth_dma 
+      port(clk         : in std_logic;                      --25 MHz
+           reset       : in std_logic;
+           enable_eth  : in std_logic;
+           select_eth  : in std_logic;
+           rec_isr     : out std_logic;
+           send_isr    : out std_logic;
+
+           address     : out std_logic_vector(31 downto 2); --to DDR
+           byte_we     : out std_logic_vector(3 downto 0);
+           data_write  : out std_logic_vector(31 downto 0);
+           data_read   : in std_logic_vector(31 downto 0);
+           pause_in    : in std_logic;
+
+           mem_address : in std_logic_vector(31 downto 2);  --from CPU
+           mem_byte_we : in std_logic_vector(3 downto 0);
+           data_w      : in std_logic_vector(31 downto 0);
+           pause_out   : out std_logic;
+
+           E_RX_CLK    : in std_logic;                      --2.5 MHz receive
+           E_RX_DV     : in std_logic;                      --data valid
+           E_RXD       : in std_logic_vector(3 downto 0);   --receive nibble
+           E_TX_CLK    : in std_logic;                      --2.5 MHz transmit
+           E_TX_EN     : out std_logic;                     --transmit enable
+           E_TXD       : out std_logic_vector(3 downto 0)); --transmit nibble
+   end component; --eth_dma
+
+   component plasma
+      generic(memory_type : string := "XILINX_X16"; --"DUAL_PORT_" "ALTERA_LPM";
+              log_file    : string := "UNUSED";
+              ethernet    : std_logic := '0';
+              use_cache   : std_logic := '0');
+      port(clk          : in std_logic;
+           reset        : in std_logic;
+           uart_write   : out std_logic;
+           uart_read    : in std_logic;
+   
+           address      : out std_logic_vector(31 downto 2);
+           byte_we      : out std_logic_vector(3 downto 0); 
+           data_write   : out std_logic_vector(31 downto 0);
+           data_read    : in std_logic_vector(31 downto 0);
+           mem_pause_in : in std_logic;
+           no_ddr_start : out std_logic;
+           no_ddr_stop  : out std_logic;
+        
+           gpio0_out    : out std_logic_vector(31 downto 0);
+           gpioA_in     : in std_logic_vector(31 downto 0));
+   end component; --plasma
+
+   component ddr_ctrl
+      port(clk      : in std_logic;
+           clk_2x   : in std_logic;
+           reset_in : in std_logic;
+
+           address  : in std_logic_vector(25 downto 2);
+           byte_we  : in std_logic_vector(3 downto 0);
+           data_w   : in std_logic_vector(31 downto 0);
+           data_r   : out std_logic_vector(31 downto 0);
+           active   : in std_logic;
+           no_start : in std_logic;
+           no_stop  : in std_logic;
+           pause    : out std_logic;
+
+           SD_CK_P  : out std_logic;     --clock_positive
+           SD_CK_N  : out std_logic;     --clock_negative
+           SD_CKE   : out std_logic;     --clock_enable
+
+           SD_BA    : out std_logic_vector(1 downto 0);  --bank_address
+           SD_A     : out std_logic_vector(12 downto 0); --address(row or col)
+           SD_CS    : out std_logic;     --chip_select
+           SD_RAS   : out std_logic;     --row_address_strobe
+           SD_CAS   : out std_logic;     --column_address_strobe
+           SD_WE    : out std_logic;     --write_enable
+
+           SD_DQ    : inout std_logic_vector(15 downto 0); --data
+           SD_UDM   : out std_logic;     --upper_byte_enable
+           SD_UDQS  : inout std_logic;   --upper_data_strobe
+           SD_LDM   : out std_logic;     --low_byte_enable
+           SD_LDQS  : inout std_logic);  --low_data_strobe
+   end component; --ddr
+   
+end; --package mlite_pack
+
+
+package body mlite_pack is
+
+function bv_adder(a     : in std_logic_vector;
+                  b     : in std_logic_vector;
+                  do_add: in std_logic) return std_logic_vector is
+   variable carry_in : std_logic;
+   variable bb       : std_logic_vector(a'length-1 downto 0);
+   variable result   : std_logic_vector(a'length downto 0);
+begin
+   if do_add = '1' then
+      bb := b;
+      carry_in := '0';
+   else
+      bb := not b;
+      carry_in := '1';
+   end if;
+   for index in 0 to a'length-1 loop
+      result(index) := a(index) xor bb(index) xor carry_in;
+      carry_in := (carry_in and (a(index) or bb(index))) or
+                  (a(index) and bb(index));
+   end loop;
+   result(a'length) := carry_in xnor do_add;
+   return result;
+end; --function
+
+
+function bv_negate(a : in std_logic_vector) return std_logic_vector is
+   variable carry_in : std_logic;
+   variable not_a    : std_logic_vector(a'length-1 downto 0);
+   variable result   : std_logic_vector(a'length-1 downto 0);
+begin
+   not_a := not a;
+   carry_in := '1';
+   for index in a'reverse_range loop
+      result(index) := not_a(index) xor carry_in;
+      carry_in := carry_in and not_a(index);
+   end loop;
+   return result;
+end; --function
+
+
+function bv_increment(a : in std_logic_vector(31 downto 2)
+                     ) return std_logic_vector is
+   variable carry_in : std_logic;
+   variable result   : std_logic_vector(31 downto 2);
+begin
+   carry_in := '1';
+   for index in 2 to 31 loop
+      result(index) := a(index) xor carry_in;
+      carry_in := a(index) and carry_in;
+   end loop;
+   return result;
+end; --function
+
+
+function bv_inc(a : in std_logic_vector
+                ) return std_logic_vector is
+   variable carry_in : std_logic;
+   variable result   : std_logic_vector(a'length-1 downto 0);
+begin
+   carry_in := '1';
+   for index in 0 to a'length-1 loop
+      result(index) := a(index) xor carry_in;
+      carry_in := a(index) and carry_in;
+   end loop;
+   return result;
+end; --function
+
+end; --package body
+
+
diff --git a/vhdl/mult.vhd b/vhdl/mult.vhd
new file mode 100644 (file)
index 0000000..643814e
--- /dev/null
@@ -0,0 +1,207 @@
+---------------------------------------------------------------------
+-- TITLE: Multiplication and Division Unit
+-- AUTHORS: Steve Rhoads (rhoadss@yahoo.com)
+-- DATE CREATED: 1/31/01
+-- FILENAME: mult.vhd
+-- PROJECT: Plasma CPU core
+-- COPYRIGHT: Software placed into the public domain by the author.
+--    Software 'as is' without warranty.  Author liable for nothing.
+-- DESCRIPTION:
+--    Implements the multiplication and division unit in 32 clocks.
+--
+--    To reduce space, compile your code using the flag "-mno-mul" which 
+--    will use software base routines in math.c if USE_SW_MULT is defined.
+--    Then remove references to the entity mult in mlite_cpu.vhd.
+--
+-- MULTIPLICATION
+-- long64 answer = 0;
+-- for(i = 0; i < 32; ++i)
+-- {
+--    answer = (answer >> 1) + (((b&1)?a:0) << 31);
+--    b = b >> 1;
+-- }
+--
+-- DIVISION
+-- long upper=a, lower=0;
+-- a = b << 31;
+-- for(i = 0; i < 32; ++i)
+-- {
+--    lower = lower << 1;
+--    if(upper >= a && a && b < 2)
+--    {
+--       upper = upper - a;
+--       lower |= 1;
+--    }
+--    a = ((b&2) << 30) | (a >> 1);
+--    b = b >> 1;
+-- }
+---------------------------------------------------------------------
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+use IEEE.std_logic_arith.all;
+use work.mlite_pack.all;
+
+entity mult is
+   generic(mult_type  : string := "DEFAULT");
+   port(clk       : in std_logic;
+        reset_in  : in std_logic;
+        a, b      : in std_logic_vector(31 downto 0);
+        mult_func : in mult_function_type;
+        c_mult    : out std_logic_vector(31 downto 0);
+        pause_out : out std_logic);
+end; --entity mult
+
+architecture logic of mult is
+
+   constant MODE_MULT : std_logic := '1';
+   constant MODE_DIV  : std_logic := '0';
+
+   signal mode_reg    : std_logic;
+   signal negate_reg  : std_logic;
+   signal sign_reg    : std_logic;
+   signal sign2_reg   : std_logic;
+   signal count_reg   : std_logic_vector(5 downto 0);
+   signal aa_reg      : std_logic_vector(31 downto 0);
+   signal bb_reg      : std_logic_vector(31 downto 0);
+   signal upper_reg   : std_logic_vector(31 downto 0);
+   signal lower_reg   : std_logic_vector(31 downto 0);
+
+   signal a_neg       : std_logic_vector(31 downto 0);
+   signal b_neg       : std_logic_vector(31 downto 0);
+   signal sum         : std_logic_vector(32 downto 0);
+   
+begin
+   -- Result
+   c_mult <= lower_reg when mult_func = MULT_READ_LO and negate_reg = '0' else 
+             bv_negate(lower_reg) when mult_func = MULT_READ_LO 
+                and negate_reg = '1' else
+             upper_reg when mult_func = MULT_READ_HI else 
+             ZERO;
+   pause_out <= '1' when (count_reg /= "000000") and 
+             (mult_func = MULT_READ_LO or mult_func = MULT_READ_HI) else '0';
+
+   -- ABS and remainder signals
+   a_neg <= bv_negate(a);
+   b_neg <= bv_negate(b);
+   sum <= bv_adder(upper_reg, aa_reg, mode_reg);
+    
+   --multiplication/division unit
+   mult_proc: process(clk, reset_in, a, b, mult_func,
+      a_neg, b_neg, sum, sign_reg, mode_reg, negate_reg, 
+      count_reg, aa_reg, bb_reg, upper_reg, lower_reg)
+      variable count : std_logic_vector(2 downto 0);
+   begin
+      count := "001";
+      if reset_in = '1' then
+         mode_reg <= '0';
+         negate_reg <= '0';
+         sign_reg <= '0';
+         sign2_reg <= '0';
+         count_reg <= "000000";
+         aa_reg <= ZERO;
+         bb_reg <= ZERO;
+         upper_reg <= ZERO;
+         lower_reg <= ZERO;
+      elsif rising_edge(clk) then
+         case mult_func is
+            when MULT_WRITE_LO =>
+               lower_reg <= a;
+               negate_reg <= '0';
+            when MULT_WRITE_HI =>
+               upper_reg <= a;
+               negate_reg <= '0';
+            when MULT_MULT =>
+               mode_reg <= MODE_MULT;
+               aa_reg <= a;
+               bb_reg <= b;
+               upper_reg <= ZERO;
+               count_reg <= "100000";
+               negate_reg <= '0';
+               sign_reg <= '0';
+               sign2_reg <= '0';
+            when MULT_SIGNED_MULT =>
+               mode_reg <= MODE_MULT;
+               if b(31) = '0' then
+                  aa_reg <= a;
+                  bb_reg <= b;
+               else
+                  aa_reg <= a_neg;
+                  bb_reg <= b_neg;
+               end if;
+               sign_reg <= a(31) xor b(31);
+               sign2_reg <= '0';
+               upper_reg <= ZERO;
+               count_reg <= "100000";
+               negate_reg <= '0';
+            when MULT_DIVIDE =>
+               mode_reg <= MODE_DIV;
+               aa_reg <= b(0) & ZERO(30 downto 0);
+               bb_reg <= b;
+               upper_reg <= a;
+               count_reg <= "100000";
+               negate_reg <= '0';
+            when MULT_SIGNED_DIVIDE =>
+               mode_reg <= MODE_DIV;
+               if b(31) = '0' then
+                  aa_reg(31) <= b(0);
+                  bb_reg <= b;
+               else
+                  aa_reg(31) <= b_neg(0);
+                  bb_reg <= b_neg;
+               end if;
+               if a(31) = '0' then
+                  upper_reg <= a;
+               else
+                  upper_reg <= a_neg;
+               end if;
+               aa_reg(30 downto 0) <= ZERO(30 downto 0);
+               count_reg <= "100000";
+               negate_reg <= a(31) xor b(31);
+            when others =>
+
+               if count_reg /= "000000" then
+                  if mode_reg = MODE_MULT then
+                     -- Multiplication
+                     if bb_reg(0) = '1' then
+                        upper_reg <= (sign_reg xor sum(32)) & sum(31 downto 1);
+                        lower_reg <= sum(0) & lower_reg(31 downto 1);
+                        sign2_reg <= sign2_reg or sign_reg;
+                        sign_reg <= '0';
+                        bb_reg <= '0' & bb_reg(31 downto 1);
+                     -- The following six lines are optional for speedup
+                     --elsif bb_reg(3 downto 0) = "0000" and sign2_reg = '0' and 
+                     --      count_reg(5 downto 2) /= "0000" then
+                     --   upper_reg <= "0000" & upper_reg(31 downto 4);
+                     --   lower_reg <=  upper_reg(3 downto 0) & lower_reg(31 downto 4);
+                     --   count := "100";
+                     --   bb_reg <= "0000" & bb_reg(31 downto 4);
+                     else
+                        upper_reg <= sign2_reg & upper_reg(31 downto 1);
+                        lower_reg <= upper_reg(0) & lower_reg(31 downto 1);
+                        bb_reg <= '0' & bb_reg(31 downto 1);
+                     end if;
+                  else   
+                     -- Division
+                     if sum(32) = '0' and aa_reg /= ZERO and 
+                           bb_reg(31 downto 1) = ZERO(31 downto 1) then
+                        upper_reg <= sum(31 downto 0);
+                        lower_reg(0) <= '1';
+                     else
+                        lower_reg(0) <= '0';
+                     end if;
+                     aa_reg <= bb_reg(1) & aa_reg(31 downto 1);
+                     lower_reg(31 downto 1) <= lower_reg(30 downto 0);
+                     bb_reg <= '0' & bb_reg(31 downto 1);
+                  end if;
+                  count_reg <= count_reg - count;
+               end if; --count
+
+         end case;
+         
+      end if;
+
+   end process;
+    
+end; --architecture logic
diff --git a/vhdl/pc_next.vhd b/vhdl/pc_next.vhd
new file mode 100644 (file)
index 0000000..3c0d9b0
--- /dev/null
@@ -0,0 +1,71 @@
+---------------------------------------------------------------------
+-- TITLE: Program Counter Next
+-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
+-- DATE CREATED: 2/8/01
+-- FILENAME: pc_next.vhd
+-- PROJECT: Plasma CPU core
+-- COPYRIGHT: Software placed into the public domain by the author.
+--    Software 'as is' without warranty.  Author liable for nothing.
+-- DESCRIPTION:
+--    Implements the Program Counter logic.
+---------------------------------------------------------------------
+library ieee;
+use ieee.std_logic_1164.all;
+use work.mlite_pack.all;
+
+entity pc_next is
+   port(clk         : in std_logic;
+        reset_in    : in std_logic;
+        pc_new      : in std_logic_vector(31 downto 2);
+        take_branch : in std_logic;
+        pause_in    : in std_logic;
+        opcode25_0  : in std_logic_vector(25 downto 0);
+        pc_source   : in pc_source_type;
+        pc_future   : out std_logic_vector(31 downto 2);
+        pc_current  : out std_logic_vector(31 downto 2);
+        pc_plus4    : out std_logic_vector(31 downto 2));
+end; --pc_next
+
+architecture logic of pc_next is
+   signal pc_reg : std_logic_vector(31 downto 2); 
+begin
+
+pc_select: process(clk, reset_in, pc_new, take_branch, pause_in, 
+                 opcode25_0, pc_source, pc_reg)
+   variable pc_inc      : std_logic_vector(31 downto 2);
+   variable pc_next : std_logic_vector(31 downto 2);
+begin
+   pc_inc := bv_increment(pc_reg);  --pc_reg+1
+
+   case pc_source is
+   when FROM_INC4 =>
+      pc_next := pc_inc;
+   when FROM_OPCODE25_0 =>
+      pc_next := pc_reg(31 downto 28) & opcode25_0;
+   when FROM_BRANCH | FROM_LBRANCH =>
+      if take_branch = '1' then
+         pc_next := pc_new;
+      else
+         pc_next := pc_inc;
+      end if;
+   when others =>
+      pc_next := pc_inc;
+   end case;
+
+   if pause_in = '1' then
+      pc_next := pc_reg;
+   end if;
+
+   if reset_in = '1' then
+      pc_reg <= ZERO(31 downto 2);
+      pc_next := pc_reg;
+   elsif rising_edge(clk) then
+      pc_reg <= pc_next;
+   end if;
+
+   pc_future <= pc_next;
+   pc_current <= pc_reg;
+   pc_plus4 <= pc_inc;
+end process;
+
+end; --logic
diff --git a/vhdl/pipeline.vhd b/vhdl/pipeline.vhd
new file mode 100644 (file)
index 0000000..09dfcee
--- /dev/null
@@ -0,0 +1,139 @@
+---------------------------------------------------------------------
+-- TITLE: Pipeline
+-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
+-- DATE CREATED: 6/24/02
+-- FILENAME: pipeline.vhd
+-- PROJECT: Plasma CPU core
+-- COPYRIGHT: Software placed into the public domain by the author.
+--    Software 'as is' without warranty.  Author liable for nothing.
+-- DESCRIPTION:
+--    Controls the three stage pipeline by delaying the signals:
+--      a_bus, b_bus, alu/shift/mult_func, c_source, and rs_index.
+---------------------------------------------------------------------
+library ieee;
+use ieee.std_logic_1164.all;
+use work.mlite_pack.all;
+
+--Note: sigD <= sig after rising_edge(clk)
+entity pipeline is
+   port(clk            : in  std_logic;
+        reset          : in  std_logic;
+        a_bus          : in  std_logic_vector(31 downto 0);
+        a_busD         : out std_logic_vector(31 downto 0);
+        b_bus          : in  std_logic_vector(31 downto 0);
+        b_busD         : out std_logic_vector(31 downto 0);
+        alu_func       : in  alu_function_type;
+        alu_funcD      : out alu_function_type;
+        shift_func     : in  shift_function_type;
+        shift_funcD    : out shift_function_type;
+        mult_func      : in  mult_function_type;
+        mult_funcD     : out mult_function_type;
+        reg_dest       : in  std_logic_vector(31 downto 0);
+        reg_destD      : out std_logic_vector(31 downto 0);
+        rd_index       : in  std_logic_vector(5 downto 0);
+        rd_indexD      : out std_logic_vector(5 downto 0);
+
+        rs_index       : in  std_logic_vector(5 downto 0);
+        rt_index       : in  std_logic_vector(5 downto 0);
+        pc_source      : in  pc_source_type;
+        mem_source     : in  mem_source_type;
+        a_source       : in  a_source_type;
+        b_source       : in  b_source_type;
+        c_source       : in  c_source_type;
+        c_bus          : in  std_logic_vector(31 downto 0);
+        pause_any      : in  std_logic;
+        pause_pipeline : out std_logic);
+end; --entity pipeline
+
+architecture logic of pipeline is
+   signal rd_index_reg     : std_logic_vector(5 downto 0);
+   signal reg_dest_reg     : std_logic_vector(31 downto 0);
+   signal reg_dest_delay   : std_logic_vector(31 downto 0);
+   signal c_source_reg     : c_source_type;
+   signal pause_enable_reg : std_logic;
+begin
+
+--When operating in three stage pipeline mode, the following signals
+--are delayed by one clock cycle:  a_bus, b_bus, alu/shift/mult_func,
+--c_source, and rd_index.
+pipeline3: process(clk, reset, a_bus, b_bus, alu_func, shift_func, mult_func,
+      rd_index, rd_index_reg, pause_any, pause_enable_reg, 
+      rs_index, rt_index,
+      pc_source, mem_source, a_source, b_source, c_source, c_source_reg, 
+      reg_dest, reg_dest_reg, reg_dest_delay, c_bus)
+   variable pause_mult_clock : std_logic;
+   variable freeze_pipeline  : std_logic;
+begin
+   if (pc_source /= FROM_INC4 and pc_source /= FROM_OPCODE25_0) or
+         mem_source /= MEM_FETCH or
+         (mult_func = MULT_READ_LO or mult_func = MULT_READ_HI) then
+      pause_mult_clock := '1';
+   else
+      pause_mult_clock := '0';
+   end if;
+
+   freeze_pipeline := not (pause_mult_clock and pause_enable_reg) and pause_any;
+   pause_pipeline <= pause_mult_clock and pause_enable_reg;
+   rd_indexD <= rd_index_reg;
+
+   -- The value written back into the register bank, signal reg_dest is tricky.
+   -- If reg_dest comes from the ALU via the signal c_bus, it is already delayed 
+   -- into stage #3, because a_busD and b_busD are delayed.  If reg_dest comes from 
+   -- c_memory, pc_current, or pc_plus4 then reg_dest hasn't yet been delayed into 
+   -- stage #3.
+   -- Instead of delaying c_memory, pc_current, and pc_plus4, these signals
+   -- are multiplexed into reg_dest which is then delayed.  The decision to use
+   -- the already delayed c_bus or the delayed value of reg_dest (reg_dest_reg) is 
+   -- based on a delayed value of c_source (c_source_reg).
+   
+   if c_source_reg = C_FROM_ALU then
+      reg_dest_delay <= c_bus;        --delayed by 1 clock cycle via a_busD & b_busD
+   else
+      reg_dest_delay <= reg_dest_reg; --need to delay 1 clock cycle from reg_dest
+   end if;
+   reg_destD <= reg_dest_delay;
+
+   if reset = '1' then
+      a_busD <= ZERO;
+      b_busD <= ZERO;
+      alu_funcD <= ALU_NOTHING;
+      shift_funcD <= SHIFT_NOTHING;
+      mult_funcD <= MULT_NOTHING;
+      reg_dest_reg <= ZERO;
+      c_source_reg <= "000";
+      rd_index_reg <= "000000";
+      pause_enable_reg <= '0';
+   elsif rising_edge(clk) then
+      if freeze_pipeline = '0' then
+         if (rs_index = "000000" or rs_index /= rd_index_reg) or 
+            (a_source /= A_FROM_REG_SOURCE or pause_enable_reg = '0') then
+            a_busD <= a_bus;
+         else
+            a_busD <= reg_dest_delay;  --rs from previous operation (bypass stage)
+         end if;
+
+         if (rt_index = "000000" or rt_index /= rd_index_reg) or
+               (b_source /= B_FROM_REG_TARGET or pause_enable_reg = '0') then
+            b_busD <= b_bus;
+         else
+            b_busD <= reg_dest_delay;  --rt from previous operation
+         end if;
+
+         alu_funcD <= alu_func;
+         shift_funcD <= shift_func;
+         mult_funcD <= mult_func;
+         reg_dest_reg <= reg_dest;
+         c_source_reg <= c_source;
+         rd_index_reg <= rd_index;
+      end if;
+
+      if pause_enable_reg = '0' and pause_any = '0' then
+         pause_enable_reg <= '1';   --enable pause_pipeline
+      elsif pause_mult_clock = '1' then
+         pause_enable_reg <= '0';   --disable pause_pipeline
+      end if;
+   end if;
+
+end process; --pipeline3
+
+end; --logic
diff --git a/vhdl/plasma.vhd b/vhdl/plasma.vhd
new file mode 100644 (file)
index 0000000..130576b
--- /dev/null
@@ -0,0 +1,320 @@
+---------------------------------------------------------------------
+-- TITLE: Plasma (CPU core with memory)
+-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
+-- DATE CREATED: 6/4/02
+-- FILENAME: plasma.vhd
+-- PROJECT: Plasma CPU core
+-- COPYRIGHT: Software placed into the public domain by the author.
+--    Software 'as is' without warranty.  Author liable for nothing.
+-- DESCRIPTION:
+--    This entity combines the CPU core with memory and a UART.
+--
+-- Memory Map:
+--   0x00000000 - 0x0000ffff   Internal RAM (8KB)
+--   0x10000000 - 0x100fffff   External RAM (1MB)
+--   Access all Misc registers with 32-bit accesses
+--   0x20000000  Uart Write (will pause CPU if busy)
+--   0x20000000  Uart Read
+--   0x20000010  IRQ Mask
+--   0x20000020  IRQ Status
+--   0x20000030  GPIO0 Out Set bits
+--   0x20000040  GPIO0 Out Clear bits
+--   0x20000050  GPIOA In
+--   0x20000060  Counter
+--   0x20000070  Ethernet transmit count
+--   IRQ bits:
+--      7   GPIO31
+--      6  ^GPIO31
+--      5   EthernetSendDone
+--      4   EthernetReceive
+--      3   Counter(18)
+--      2  ^Counter(18)
+--      1  ^UartWriteBusy
+--      0   UartDataAvailable
+---------------------------------------------------------------------
+library ieee;
+use ieee.std_logic_1164.all;
+use work.mlite_pack.all;
+
+entity plasma is
+   generic(memory_type : string := "XILINX_16X"; --"DUAL_PORT_" "ALTERA_LPM";
+           log_file    : string := "UNUSED";
+           ethernet    : std_logic := '0';
+           use_cache   : std_logic := '0');
+   port(clk          : in std_logic;
+        reset        : in std_logic;
+
+        uart_write   : out std_logic;
+        uart_read    : in std_logic;
+
+        address      : out std_logic_vector(31 downto 2);
+        byte_we      : out std_logic_vector(3 downto 0); 
+        data_write   : out std_logic_vector(31 downto 0);
+        data_read    : in std_logic_vector(31 downto 0);
+        mem_pause_in : in std_logic;
+        no_ddr_start : out std_logic;
+        no_ddr_stop  : out std_logic;
+        
+        gpio0_out    : out std_logic_vector(31 downto 0);
+        gpioA_in     : in std_logic_vector(31 downto 0));
+end; --entity plasma
+
+architecture logic of plasma is
+   signal address_next      : std_logic_vector(31 downto 2);
+   signal byte_we_next      : std_logic_vector(3 downto 0);
+   signal cpu_address       : std_logic_vector(31 downto 0);
+   signal cpu_byte_we       : std_logic_vector(3 downto 0);
+   signal cpu_data_w        : std_logic_vector(31 downto 0);
+   signal cpu_data_r        : std_logic_vector(31 downto 0);
+   signal cpu_pause         : std_logic;
+
+   signal data_read_uart    : std_logic_vector(7 downto 0);
+   signal write_enable      : std_logic;
+   signal eth_pause_in      : std_logic;
+   signal eth_pause         : std_logic;
+   signal mem_busy          : std_logic;
+
+   signal enable_misc       : std_logic;
+   signal enable_uart       : std_logic;
+   signal enable_uart_read  : std_logic;
+   signal enable_uart_write : std_logic;
+   signal enable_eth        : std_logic;
+
+   signal gpio0_reg         : std_logic_vector(31 downto 0);
+   signal uart_write_busy   : std_logic;
+   signal uart_data_avail   : std_logic;
+   signal irq_mask_reg      : std_logic_vector(7 downto 0);
+   signal irq_status        : std_logic_vector(7 downto 0);
+   signal irq               : std_logic;
+   signal irq_eth_rec       : std_logic;
+   signal irq_eth_send      : std_logic;
+   signal counter_reg       : std_logic_vector(31 downto 0);
+
+   signal ram_enable        : std_logic;
+   signal ram_byte_we       : std_logic_vector(3 downto 0);
+   signal ram_address       : std_logic_vector(31 downto 2);
+   signal ram_data_w        : std_logic_vector(31 downto 0);
+   signal ram_data_r        : std_logic_vector(31 downto 0);
+
+   signal cache_access      : std_logic;
+   signal cache_checking    : std_logic;
+   signal cache_miss        : std_logic;
+   signal cache_hit         : std_logic;
+
+begin  --architecture
+   write_enable <= '1' when cpu_byte_we /= "0000" else '0';
+   mem_busy <= eth_pause or mem_pause_in;
+   cache_hit <= cache_checking and not cache_miss;
+   cpu_pause <= (uart_write_busy and enable_uart and write_enable) or  --UART busy
+      cache_miss or                                                    --Cache wait
+      (cpu_address(28) and not cache_hit and mem_busy);                --DDR or flash
+   irq_status <= gpioA_in(31) & not gpioA_in(31) &
+                 irq_eth_send & irq_eth_rec & 
+                 counter_reg(18) & not counter_reg(18) &
+                 not uart_write_busy & uart_data_avail;
+   irq <= '1' when (irq_status and irq_mask_reg) /= ZERO(7 downto 0) else '0';
+   gpio0_out(31 downto 29) <= gpio0_reg(31 downto 29);
+   gpio0_out(23 downto 0) <= gpio0_reg(23 downto 0);
+
+   enable_misc <= '1' when cpu_address(30 downto 28) = "010" else '0';
+   enable_uart <= '1' when enable_misc = '1' and cpu_address(7 downto 4) = "0000" else '0';
+   enable_uart_read <= enable_uart and not write_enable;
+   enable_uart_write <= enable_uart and write_enable;
+   enable_eth <= '1' when enable_misc = '1' and cpu_address(7 downto 4) = "0111" else '0';
+   cpu_address(1 downto 0) <= "00";
+
+   u1_cpu: mlite_cpu 
+      generic map (memory_type => memory_type)
+      PORT MAP (
+         clk          => clk,
+         reset_in     => reset,
+         intr_in      => irq,
+         address_next => address_next,             --before rising_edge(clk)
+         byte_we_next => byte_we_next,
+
+         address      => cpu_address(31 downto 2), --after rising_edge(clk)
+         byte_we      => cpu_byte_we,
+         data_w       => cpu_data_w,
+         data_r       => cpu_data_r,
+         mem_pause    => cpu_pause);
+
+   opt_cache: if use_cache = '0' generate
+      cache_access <= '0';
+      cache_checking <= '0';
+      cache_miss <= '0';
+   end generate;
+   
+   opt_cache2: if use_cache = '1' generate
+   --Control 4KB unified cache that uses the upper 4KB of the 8KB
+   --internal RAM.  Only lowest 2MB of DDR is cached.
+   u_cache: cache 
+      generic map (memory_type => memory_type)
+      PORT MAP (
+         clk            => clk,
+         reset          => reset,
+         address_next   => address_next,
+         byte_we_next   => byte_we_next,
+         cpu_address    => cpu_address(31 downto 2),
+         mem_busy       => mem_busy,
+
+         cache_access   => cache_access,    --access 4KB cache
+         cache_checking => cache_checking,  --checking if cache hit
+         cache_miss     => cache_miss);     --cache miss
+   end generate; --opt_cache2
+
+   no_ddr_start <= not eth_pause and cache_checking;
+   no_ddr_stop <= not eth_pause and cache_miss;
+   eth_pause_in <= mem_pause_in or (not eth_pause and cache_miss and not cache_checking);
+
+   misc_proc: process(clk, reset, cpu_address, enable_misc,
+      ram_data_r, data_read, data_read_uart, cpu_pause,
+      irq_mask_reg, irq_status, gpio0_reg, write_enable,
+      cache_checking,
+      gpioA_in, counter_reg, cpu_data_w)
+   begin
+      case cpu_address(30 downto 28) is
+      when "000" =>         --internal RAM
+         cpu_data_r <= ram_data_r;
+      when "001" =>         --external RAM
+         if cache_checking = '1' then
+            cpu_data_r <= ram_data_r; --cache
+         else
+            cpu_data_r <= data_read; --DDR
+         end if;
+      when "010" =>         --misc
+         case cpu_address(6 downto 4) is
+         when "000" =>      --uart
+            cpu_data_r <= ZERO(31 downto 8) & data_read_uart;
+         when "001" =>      --irq_mask
+            cpu_data_r <= ZERO(31 downto 8) & irq_mask_reg;
+         when "010" =>      --irq_status
+            cpu_data_r <= ZERO(31 downto 8) & irq_status;
+         when "011" =>      --gpio0
+            cpu_data_r <= gpio0_reg;
+         when "101" =>      --gpioA
+            cpu_data_r <= gpioA_in;
+         when "110" =>      --counter
+            cpu_data_r <= counter_reg;        
+         when others =>
+            cpu_data_r <= gpioA_in;
+         end case;
+      when "011" =>         --flash
+         cpu_data_r <= data_read;
+      when others =>
+         cpu_data_r <= ZERO;
+      end case;
+
+      if reset = '1' then
+         irq_mask_reg <= ZERO(7 downto 0);
+         gpio0_reg <= ZERO;
+         counter_reg <= ZERO;
+      elsif rising_edge(clk) then
+         if cpu_pause = '0' then
+            if enable_misc = '1' and write_enable = '1' then
+               if cpu_address(6 downto 4) = "001" then
+                  irq_mask_reg <= cpu_data_w(7 downto 0);
+               elsif cpu_address(6 downto 4) = "011" then
+                  gpio0_reg <= gpio0_reg or cpu_data_w;
+               elsif cpu_address(6 downto 4) = "100" then
+                  gpio0_reg <= gpio0_reg and not cpu_data_w;
+               end if;
+            end if;
+         end if;
+         counter_reg <= bv_inc(counter_reg);
+      end if;
+   end process;
+
+   ram_proc: process(cache_access, cache_miss,
+                     address_next, cpu_address,
+                     byte_we_next, cpu_data_w, data_read)
+   begin
+      if cache_access = '1' then    --Check if cache hit or write through
+         ram_enable <= '1';
+         ram_byte_we <= byte_we_next;
+         ram_address(31 downto 2) <= ZERO(31 downto 16) & 
+            "0001" & address_next(11 downto 2);
+         ram_data_w <= cpu_data_w;
+      elsif cache_miss = '1' then  --Update cache after cache miss
+         ram_enable <= '1';
+         ram_byte_we <= "1111";
+         ram_address(31 downto 2) <= ZERO(31 downto 16) & 
+            "0001" & cpu_address(11 downto 2);
+         ram_data_w <= data_read;
+      else                         --Normal non-cache access\r
+         if address_next(30 downto 28) = "000" then\r
+            ram_enable <= '1';\r
+         else\r
+            ram_enable <= '0';\r
+         end if;
+         ram_byte_we <= byte_we_next;
+         ram_address(31 downto 2) <= address_next(31 downto 2);
+         ram_data_w <= cpu_data_w;
+      end if;
+   end process;
+
+   u2_ram: ram 
+      generic map (memory_type => memory_type)
+      port map (
+         clk               => clk,
+         enable            => ram_enable,
+         write_byte_enable => ram_byte_we,
+         address           => ram_address,
+         data_write        => ram_data_w,
+         data_read         => ram_data_r);
+
+   u3_uart: uart
+      generic map (log_file => log_file)
+      port map(
+         clk          => clk,
+         reset        => reset,
+         enable_read  => enable_uart_read,
+         enable_write => enable_uart_write,
+         data_in      => cpu_data_w(7 downto 0),
+         data_out     => data_read_uart,
+         uart_read    => uart_read,
+         uart_write   => uart_write,
+         busy_write   => uart_write_busy,
+         data_avail   => uart_data_avail);
+
+   dma_gen: if ethernet = '0' generate
+      address <= cpu_address(31 downto 2);
+      byte_we <= cpu_byte_we;
+      data_write <= cpu_data_w;
+      eth_pause <= '0';
+      gpio0_out(28 downto 24) <= ZERO(28 downto 24);
+      irq_eth_rec <= '0';
+      irq_eth_send <= '0';
+   end generate;
+
+   dma_gen2: if ethernet = '1' generate
+   u4_eth: eth_dma 
+      port map(
+         clk         => clk,
+         reset       => reset,
+         enable_eth  => gpio0_reg(24),
+         select_eth  => enable_eth,
+         rec_isr     => irq_eth_rec,
+         send_isr    => irq_eth_send,
+
+         address     => address,      --to DDR
+         byte_we     => byte_we,
+         data_write  => data_write,
+         data_read   => data_read,
+         pause_in    => eth_pause_in,
+
+         mem_address => cpu_address(31 downto 2), --from CPU
+         mem_byte_we => cpu_byte_we,
+         data_w      => cpu_data_w,
+         pause_out   => eth_pause,
+
+         E_RX_CLK    => gpioA_in(20),
+         E_RX_DV     => gpioA_in(19),
+         E_RXD       => gpioA_in(18 downto 15),
+         E_TX_CLK    => gpioA_in(14),
+         E_TX_EN     => gpio0_out(28),
+         E_TXD       => gpio0_out(27 downto 24));
+   end generate;
+
+end; --architecture logic
+
diff --git a/vhdl/plasma_3e.vhd b/vhdl/plasma_3e.vhd
new file mode 100644 (file)
index 0000000..8879fda
--- /dev/null
@@ -0,0 +1,289 @@
+---------------------------------------------------------------------
+-- TITLE: Plamsa Interface (clock divider and interface to FPGA board)
+-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
+-- DATE CREATED: 9/15/07
+-- FILENAME: plasma_3e.vhd
+-- PROJECT: Plasma CPU core
+-- COPYRIGHT: Software placed into the public domain by the author.
+--    Software 'as is' without warranty.  Author liable for nothing.
+-- DESCRIPTION:
+--    This entity divides the clock by two and interfaces to the 
+--    Xilinx Spartan-3E XC3S200FT256-4 FPGA with DDR.
+---------------------------------------------------------------------
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+use ieee.std_logic_arith.all;
+--use work.mlite_pack.all;
+
+entity plasma_3e is
+   port(CLK_50MHZ  : in std_logic;
+        RS232_DCE_RXD : in std_logic;
+        RS232_DCE_TXD : out std_logic;
+
+        SD_CK_P    : out std_logic;     --DDR SDRAM clock_positive
+        SD_CK_N    : out std_logic;     --clock_negative
+        SD_CKE     : out std_logic;     --clock_enable
+
+        SD_BA      : out std_logic_vector(1 downto 0);  --bank_address
+        SD_A       : out std_logic_vector(12 downto 0); --address(row or col)
+        SD_CS      : out std_logic;     --chip_select
+        SD_RAS     : out std_logic;     --row_address_strobe
+        SD_CAS     : out std_logic;     --column_address_strobe
+        SD_WE      : out std_logic;     --write_enable
+
+        SD_DQ      : inout std_logic_vector(15 downto 0); --data
+        SD_UDM     : out std_logic;     --upper_byte_enable
+        SD_UDQS    : inout std_logic;   --upper_data_strobe
+        SD_LDM     : out std_logic;     --low_byte_enable
+        SD_LDQS    : inout std_logic;   --low_data_strobe
+
+        E_MDC      : out std_logic;     --Ethernet PHY
+        E_MDIO     : inout std_logic;   --management data in/out
+        E_RX_CLK   : in std_logic;      --receive clock
+        E_RX_DV    : in std_logic;      --data valid
+        E_RXD      : in std_logic_vector(3 downto 0);
+        E_TX_CLK   : in std_logic;      --transmit clock
+        E_TX_EN    : out std_logic;     --data valid
+        E_TXD      : out std_logic_vector(3 downto 0);
+
+        SF_CE0     : out std_logic;     --NOR flash
+        SF_OE      : out std_logic;
+        SF_WE      : out std_logic;
+        SF_BYTE    : out std_logic;
+        SF_STS     : in std_logic;      --status
+        SF_A       : out std_logic_vector(24 downto 0);
+        SF_D       : inout std_logic_vector(15 downto 1);
+        SPI_MISO   : inout std_logic;
+
+        VGA_VSYNC  : out std_logic;     --VGA port
+        VGA_HSYNC  : out std_logic;
+        VGA_RED    : out std_logic;
+        VGA_GREEN  : out std_logic;
+        VGA_BLUE   : out std_logic;
+
+        PS2_CLK    : in std_logic;      --Keyboard
+        PS2_DATA   : in std_logic;
+
+        LED        : out std_logic_vector(7 downto 0);
+        ROT_CENTER : in std_logic;
+        ROT_A      : in std_logic;
+        ROT_B      : in std_logic;
+        BTN_EAST   : in std_logic;
+        BTN_NORTH  : in std_logic;
+        BTN_SOUTH  : in std_logic;
+        BTN_WEST   : in std_logic;
+        SW         : in std_logic_vector(3 downto 0));
+end; --entity plasma_if
+
+
+architecture logic of plasma_3e is
+
+   component plasma
+      generic(memory_type : string := "XILINX_16X"; --"DUAL_PORT_" "ALTERA_LPM";
+              log_file    : string := "UNUSED";
+              ethernet    : std_logic := '0';
+              use_cache   : std_logic := '0');
+      port(clk          : in std_logic;
+           reset        : in std_logic;
+           uart_write   : out std_logic;
+           uart_read    : in std_logic;
+   
+           address      : out std_logic_vector(31 downto 2);
+           byte_we      : out std_logic_vector(3 downto 0); 
+           data_write   : out std_logic_vector(31 downto 0);
+           data_read    : in std_logic_vector(31 downto 0);
+           mem_pause_in : in std_logic;
+           no_ddr_start : out std_logic;
+           no_ddr_stop  : out std_logic;
+        
+           gpio0_out    : out std_logic_vector(31 downto 0);
+           gpioA_in     : in std_logic_vector(31 downto 0));
+   end component; --plasma
+
+   component ddr_ctrl
+      port(clk      : in std_logic;
+           clk_2x   : in std_logic;
+           reset_in : in std_logic;
+
+           address  : in std_logic_vector(25 downto 2);
+           byte_we  : in std_logic_vector(3 downto 0);
+           data_w   : in std_logic_vector(31 downto 0);
+           data_r   : out std_logic_vector(31 downto 0);
+           active   : in std_logic;
+           no_start : in std_logic;
+           no_stop  : in std_logic;
+           pause    : out std_logic;
+
+           SD_CK_P  : out std_logic;     --clock_positive
+           SD_CK_N  : out std_logic;     --clock_negative
+           SD_CKE   : out std_logic;     --clock_enable
+
+           SD_BA    : out std_logic_vector(1 downto 0);  --bank_address
+           SD_A     : out std_logic_vector(12 downto 0); --address(row or col)
+           SD_CS    : out std_logic;     --chip_select
+           SD_RAS   : out std_logic;     --row_address_strobe
+           SD_CAS   : out std_logic;     --column_address_strobe
+           SD_WE    : out std_logic;     --write_enable
+
+           SD_DQ    : inout std_logic_vector(15 downto 0); --data
+           SD_UDM   : out std_logic;     --upper_byte_enable
+           SD_UDQS  : inout std_logic;   --upper_data_strobe
+           SD_LDM   : out std_logic;     --low_byte_enable
+           SD_LDQS  : inout std_logic);  --low_data_strobe
+   end component; --ddr
+
+   signal clk_reg      : std_logic;
+   signal address      : std_logic_vector(31 downto 2);
+   signal data_write   : std_logic_vector(31 downto 0);
+   signal data_read    : std_logic_vector(31 downto 0);
+   signal data_r_ddr   : std_logic_vector(31 downto 0);
+   signal byte_we      : std_logic_vector(3 downto 0);
+   signal write_enable : std_logic;
+   signal pause_ddr    : std_logic;
+   signal pause        : std_logic;
+   signal no_ddr_start : std_logic;
+   signal no_ddr_stop  : std_logic;
+   signal ddr_active   : std_logic;
+   signal flash_active : std_logic;
+   signal flash_cnt    : std_logic_vector(1 downto 0);
+   signal flash_we     : std_logic;
+   signal reset        : std_logic;
+   signal gpio0_out    : std_logic_vector(31 downto 0);
+   signal gpio0_in     : std_logic_vector(31 downto 0);
+   
+begin  --architecture
+   --Divide 50 MHz clock by two
+   clk_div: process(reset, CLK_50MHZ, clk_reg)
+   begin
+      if reset = '1' then
+         clk_reg <= '0';
+      elsif rising_edge(CLK_50MHZ) then
+         clk_reg <= not clk_reg;
+      end if;
+   end process; --clk_div
+
+   reset <= ROT_CENTER;
+   E_TX_EN   <= gpio0_out(28);  --Ethernet
+   E_TXD     <= gpio0_out(27 downto 24);
+   E_MDC     <= gpio0_out(23);
+   E_MDIO    <= gpio0_out(21) when gpio0_out(22) = '1' else 'Z';
+   VGA_VSYNC <= gpio0_out(20);
+   VGA_HSYNC <= gpio0_out(19);
+   VGA_RED   <= gpio0_out(18);
+   VGA_GREEN <= gpio0_out(17);
+   VGA_BLUE  <= gpio0_out(16);
+   LED <= gpio0_out(7 downto 0);
+   gpio0_in(31 downto 21) <= (others => '0');
+   gpio0_in(20 downto 13) <= E_RX_CLK & E_RX_DV & E_RXD & E_TX_CLK & E_MDIO;
+   gpio0_in(12 downto 10) <= SF_STS & PS2_CLK & PS2_DATA;
+   gpio0_in(9 downto 0) <= ROT_A & ROT_B & BTN_EAST & BTN_NORTH & 
+                           BTN_SOUTH & BTN_WEST & SW;
+   ddr_active <= '1' when address(31 downto 28) = "0001" else '0';
+   flash_active <= '1' when address(31 downto 28) = "0011" else '0';
+   write_enable <= '1' when byte_we /= "0000" else '0';
+
+   u1_plama: plasma 
+      generic map (memory_type => "XILINX_16X",
+                   log_file    => "UNUSED",
+                   ethernet    => '1',
+                   use_cache   => '1')
+      --generic map (memory_type => "DUAL_PORT_",
+      --             log_file    => "output2.txt",
+      --             ethernet    => '1')
+      PORT MAP (
+         clk          => clk_reg,
+         reset        => reset,
+         uart_write   => RS232_DCE_TXD,
+         uart_read    => RS232_DCE_RXD,
+         address      => address,
+         byte_we      => byte_we,
+         data_write   => data_write,
+         data_read    => data_read,
+         mem_pause_in => pause,
+         no_ddr_start => no_ddr_start,
+         no_ddr_stop  => no_ddr_stop,
+
+         gpio0_out    => gpio0_out,
+         gpioA_in     => gpio0_in);
+         
+   u2_ddr: ddr_ctrl
+      port map (
+         clk      => clk_reg,
+         clk_2x   => CLK_50MHZ,
+         reset_in => reset,
+
+         address  => address(25 downto 2),
+         byte_we  => byte_we,
+         data_w   => data_write,
+         data_r   => data_r_ddr,
+         active   => ddr_active,
+         no_start => no_ddr_start,
+         no_stop  => no_ddr_stop,
+         pause    => pause_ddr,
+
+         SD_CK_P  => SD_CK_P,    --clock_positive
+         SD_CK_N  => SD_CK_N,    --clock_negative
+         SD_CKE   => SD_CKE,     --clock_enable
+   
+         SD_BA    => SD_BA,      --bank_address
+         SD_A     => SD_A,       --address(row or col)
+         SD_CS    => SD_CS,      --chip_select
+         SD_RAS   => SD_RAS,     --row_address_strobe
+         SD_CAS   => SD_CAS,     --column_address_strobe
+         SD_WE    => SD_WE,      --write_enable
+
+         SD_DQ    => SD_DQ,      --data
+         SD_UDM   => SD_UDM,     --upper_byte_enable
+         SD_UDQS  => SD_UDQS,    --upper_data_strobe
+         SD_LDM   => SD_LDM,     --low_byte_enable
+         SD_LDQS  => SD_LDQS);   --low_data_strobe
+
+   --Flash control (only lower 16-bit data lines connected)
+   flash_ctrl: process(reset, clk_reg, flash_active, write_enable, 
+                       flash_cnt, pause_ddr)
+   begin
+      if reset = '1' then
+         flash_cnt <= "00";
+         flash_we <= '1';
+      elsif rising_edge(clk_reg) then
+         if flash_active = '0' then
+            flash_cnt <= "00";
+            flash_we <= '1';
+         else
+            if write_enable = '1' and flash_cnt(1) = '0' then
+               flash_we <= '0';
+            else
+               flash_we <= '1';
+            end if;
+            if flash_cnt /= "11" then
+               flash_cnt <= flash_cnt + 1;
+            end if;
+         end if;
+      end if;  --rising_edge(clk_reg)
+      if pause_ddr = '1' or (flash_active = '1' and flash_cnt /= "11") then
+         pause <= '1';
+      else
+         pause <= '0';
+      end if;
+   end process; --flash_ctrl
+
+   SF_CE0  <= not flash_active;
+   SF_OE   <= write_enable or not flash_active;
+   SF_WE   <= flash_we;
+   SF_BYTE <= '1';  --16-bit access
+   SF_A    <= address(25 downto 2) & '0' when flash_active = '1' else
+              "0000000000000000000000000";
+   SF_D    <= data_write(15 downto 1) when 
+              flash_active = '1' and write_enable = '1'
+              else "ZZZZZZZZZZZZZZZ";
+   SPI_MISO <= data_write(0) when 
+              flash_active = '1' and write_enable = '1'
+              else 'Z';
+   data_read(31 downto 16) <= data_r_ddr(31 downto 16);
+   data_read(15 downto 0) <= data_r_ddr(15 downto 0) when flash_active = '0' 
+                             else SF_D & SPI_MISO;
+         
+end; --architecture logic
+
diff --git a/vhdl/plasma_S3E.npl b/vhdl/plasma_S3E.npl
new file mode 100644 (file)
index 0000000..579c2b3
--- /dev/null
@@ -0,0 +1,38 @@
+JDF G
+// Created by Project Navigator ver 1.0
+PROJECT jop
+DESIGN jop
+DEVFAM spartan3e
+DEVFAMTIME 0
+DEVICE xc3s500e
+DEVICETIME 0
+DEVPKG fg320
+DEVPKGTIME 0
+DEVSPEED -4
+DEVTOPLEVELMODULETYPE HDL
+TOPLEVELMODULETYPETIME 0
+DEVSYNTHESISTOOL XST (VHDL/Verilog)
+SYNTHESISTOOLTIME 0
+DEVSIMULATOR Modelsim
+SIMULATORTIME 0
+DEVGENERATEDSIMULATIONMODEL VHDL
+GENERATEDSIMULATIONMODELTIME 0
+SOURCE mlite_pack.vhd
+SOURCE plasma_3e.vhd
+SOURCE ddr_ctrl.vhd
+SOURCE plasma.vhd
+SOURCE ram_image.vhd
+SOURCE uart.vhd
+SOURCE eth_dma.vhd
+SOURCE mlite_cpu.vhd
+SOURCE alu.vhd
+SOURCE bus_mux.vhd
+SOURCE control.vhd
+SOURCE mem_ctrl.vhd
+SOURCE mult.vhd
+SOURCE pipeline.vhd
+SOURCE pc_next.vhd
+SOURCE reg_bank.vhd
+SOURCE shifter.vhd
+SOURCE cache.vhd
+DEPASSOC spartan3e spartan3e.ucf
diff --git a/vhdl/plasma_if.ucf b/vhdl/plasma_if.ucf
new file mode 100644 (file)
index 0000000..51b354f
--- /dev/null
@@ -0,0 +1,111 @@
+NET "clk_in" TNM_NET = "clk_in";
+TIMESPEC "TS_clk_in" = PERIOD "clk_in" 20 ns HIGH 50 %;
+#NET "clk_reg1" TNM_NET = "clk_reg1";
+#TIMESPEC "TS_clk_reg1" = PERIOD "clk_reg1" 40 ns HIGH 50 %;
+NET "clk_reg1" TNM_NET = "clk_reg1";
+TIMESPEC "TS_clk_reg1" = PERIOD "clk_reg1" 39.9 ns HIGH 50 %;
+#PACE: Start of Constraints generated by PACE
+#PACE: Start of PACE I/O Pin Assignments
+NET "clk_in" LOC = "T9";
+NET "gpio0_out<0>" LOC = "K12";
+NET "gpio0_out<10>" LOC = "N15";
+NET "gpio0_out<11>" LOC = "P15";
+NET "gpio0_out<12>" LOC = "R16";
+NET "gpio0_out<13>" LOC = "F13";
+NET "gpio0_out<14>" LOC = "N16";
+NET "gpio0_out<15>" LOC = "P16";
+NET "gpio0_out<16>" LOC = "E13";
+NET "gpio0_out<17>" LOC = "F14";
+NET "gpio0_out<18>" LOC = "G14";
+NET "gpio0_out<19>" LOC = "D14";
+NET "gpio0_out<1>" LOC = "P14";
+NET "gpio0_out<24>" LOC = "R12";
+NET "gpio0_out<25>" LOC = "T12";
+NET "gpio0_out<26>" LOC = "R11";
+NET "gpio0_out<27>" LOC = "R9";
+NET "gpio0_out<28>" LOC = "T10";
+NET "gpio0_out<2>" LOC = "L12";
+NET "gpio0_out<3>" LOC = "N14";
+NET "gpio0_out<4>" LOC = "P13";
+NET "gpio0_out<5>" LOC = "N12";
+NET "gpio0_out<6>" LOC = "P12";
+NET "gpio0_out<7>" LOC = "P11";
+NET "gpio0_out<8>" LOC = "E14";
+NET "gpio0_out<9>" LOC = "G13";
+NET "gpioA_in<0>" LOC = "F12";
+NET "gpioA_in<10>" LOC = "L13";
+NET "gpioA_in<1>" LOC = "G12";
+NET "gpioA_in<2>" LOC = "H14";
+NET "gpioA_in<30>" LOC = "M15";
+NET "gpioA_in<31>" LOC = "M16";
+NET "gpioA_in<3>" LOC = "H13";
+NET "gpioA_in<4>" LOC = "J14";
+NET "gpioA_in<5>" LOC = "J13";
+NET "gpioA_in<6>" LOC = "K14";
+NET "gpioA_in<7>" LOC = "K13";
+NET "gpioA_in<8>" LOC = "M13";
+NET "gpioA_in<9>" LOC = "M14";
+NET "ram_address<10>" LOC = "E3";
+NET "ram_address<11>" LOC = "E4";
+NET "ram_address<12>" LOC = "G5";
+NET "ram_address<13>" LOC = "H3";
+NET "ram_address<14>" LOC = "H4";
+NET "ram_address<15>" LOC = "J4";
+NET "ram_address<16>" LOC = "J3";
+NET "ram_address<17>" LOC = "K3";
+NET "ram_address<18>" LOC = "K5";
+NET "ram_address<19>" LOC = "L3";
+NET "ram_address<2>" LOC = "L5";
+NET "ram_address<3>" LOC = "N3";
+NET "ram_address<4>" LOC = "M4";
+NET "ram_address<5>" LOC = "M3";
+NET "ram_address<6>" LOC = "L4";
+NET "ram_address<7>" LOC = "G4";
+NET "ram_address<8>" LOC = "F3";
+NET "ram_address<9>" LOC = "F4";
+NET "ram_ce1_n" LOC = "P7";
+NET "ram_ce2_n" LOC = "N5";
+NET "ram_data<0>" LOC = "P2";
+NET "ram_data<10>" LOC = "G1";
+NET "ram_data<11>" LOC = "F5";
+NET "ram_data<12>" LOC = "C3";
+NET "ram_data<13>" LOC = "K2";
+NET "ram_data<14>" LOC = "M1";
+NET "ram_data<15>" LOC = "N1";
+NET "ram_data<16>" LOC = "N7";
+NET "ram_data<17>" LOC = "T8";
+NET "ram_data<18>" LOC = "R6";
+NET "ram_data<19>" LOC = "T5";
+NET "ram_data<1>" LOC = "N2";
+NET "ram_data<20>" LOC = "R5";
+NET "ram_data<21>" LOC = "C2";
+NET "ram_data<22>" LOC = "C1";
+NET "ram_data<23>" LOC = "B1";
+NET "ram_data<24>" LOC = "D3";
+NET "ram_data<25>" LOC = "P8";
+NET "ram_data<26>" LOC = "F2";
+NET "ram_data<27>" LOC = "H1";
+NET "ram_data<28>" LOC = "J2";
+NET "ram_data<29>" LOC = "L2";
+NET "ram_data<2>" LOC = "M2";
+NET "ram_data<30>" LOC = "P1";
+NET "ram_data<31>" LOC = "R1";
+NET "ram_data<3>" LOC = "K1";
+NET "ram_data<4>" LOC = "J1";
+NET "ram_data<5>" LOC = "G2";
+NET "ram_data<6>" LOC = "E1";
+NET "ram_data<7>" LOC = "D1";
+NET "ram_data<8>" LOC = "D2";
+NET "ram_data<9>" LOC = "E2";
+NET "ram_lb1_n" LOC = "P6";
+NET "ram_lb2_n" LOC = "P5";
+NET "ram_oe_n" LOC = "K4";
+NET "ram_ub1_n" LOC = "T4";
+NET "ram_ub2_n" LOC = "R4";
+NET "ram_we_n" LOC = "G3";
+NET "reset" LOC = "L14";
+NET "uart_read" LOC = "T13";
+NET "uart_write" LOC = "R13";
+#PACE: Start of PACE Area Constraints
+#PACE: Start of PACE Prohibit Constraints
+#PACE: End of Constraints generated by PACE
diff --git a/vhdl/plasma_if.vhd b/vhdl/plasma_if.vhd
new file mode 100644 (file)
index 0000000..e36530e
--- /dev/null
@@ -0,0 +1,152 @@
+---------------------------------------------------------------------
+-- TITLE: Plamsa Interface (clock divider and interface to FPGA board)
+-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
+-- DATE CREATED: 6/6/02
+-- FILENAME: plasma_if.vhd
+-- PROJECT: Plasma CPU core
+-- COPYRIGHT: Software placed into the public domain by the author.
+--    Software 'as is' without warranty.  Author liable for nothing.
+-- DESCRIPTION:
+--    This entity divides the clock by two and interfaces to the 
+--    Altera EP20K200EFC484-2X FPGA board.
+--    Xilinx Spartan-3 XC3S200FT256-4 FPGA.
+---------------------------------------------------------------------
+library ieee;
+use ieee.std_logic_1164.all;
+--use work.mlite_pack.all;
+
+entity plasma_if is
+   port(clk_in      : in std_logic;
+        reset       : in std_logic;
+        uart_read   : in std_logic;
+        uart_write  : out std_logic;
+
+        ram_address : out std_logic_vector(31 downto 2);
+        ram_data    : inout std_logic_vector(31 downto 0);
+        ram_ce1_n   : out std_logic;
+        ram_ub1_n   : out std_logic;
+        ram_lb1_n   : out std_logic;
+        ram_ce2_n   : out std_logic;
+        ram_ub2_n   : out std_logic;
+        ram_lb2_n   : out std_logic;
+        ram_we_n    : out std_logic;
+        ram_oe_n    : out std_logic;
+         
+        gpio0_out   : out std_logic_vector(31 downto 0);
+        gpioA_in    : in std_logic_vector(31 downto 0));
+end; --entity plasma_if
+
+
+architecture logic of plasma_if is
+
+   component plasma
+      generic(memory_type : string := "XILINX_16X"; --"DUAL_PORT_" "ALTERA_LPM";
+              log_file    : string := "UNUSED");
+      port(clk               : in std_logic;
+           reset             : in std_logic;
+           uart_write        : out std_logic;
+           uart_read         : in std_logic;
+   
+           address           : out std_logic_vector(31 downto 2);
+           byte_we           : out std_logic_vector(3 downto 0); 
+           data_write        : out std_logic_vector(31 downto 0);
+           data_read         : in std_logic_vector(31 downto 0);
+           mem_pause_in      : in std_logic;
+        
+           gpio0_out         : out std_logic_vector(31 downto 0);
+           gpioA_in          : in std_logic_vector(31 downto 0));
+   end component; --plasma
+
+   signal clk_reg      : std_logic;
+   signal we_n_next    : std_logic;
+   signal we_n_reg     : std_logic;
+   signal mem_address  : std_logic_vector(31 downto 2);
+   signal data_write   : std_logic_vector(31 downto 0);
+   signal data_reg     : std_logic_vector(31 downto 0);
+   signal byte_we      : std_logic_vector(3 downto 0);
+   signal mem_pause_in : std_logic;
+
+begin  --architecture
+   --Divide 50 MHz clock by two
+   clk_div: process(reset, clk_in, clk_reg, we_n_next)
+   begin
+      if reset = '1' then
+         clk_reg <= '0';
+      elsif rising_edge(clk_in) then
+         clk_reg <= not clk_reg;
+      end if;
+
+      if reset = '1' then
+         we_n_reg <= '1';
+         data_reg <= (others => '0');
+      elsif falling_edge(clk_in) then
+         we_n_reg <= we_n_next or not clk_reg;
+         data_reg <= ram_data;
+      end if;
+   end process; --clk_div
+
+   mem_pause_in <= '0';
+   ram_address <= mem_address(31 downto 2);
+   ram_we_n <= we_n_reg;
+
+   --For Xilinx Spartan-3 Starter Kit
+   ram_control:   
+   process(clk_reg, mem_address, byte_we, data_write)
+   begin
+      if mem_address(30 downto 28) = "001" then  --RAM
+         ram_ce1_n <= '0';
+         ram_ce2_n <= '0';
+         if byte_we = "0000" then      --read
+            ram_data  <= (others => 'Z');
+            ram_ub1_n <= '0';
+            ram_lb1_n <= '0';
+            ram_ub2_n <= '0';
+            ram_lb2_n <= '0';
+            we_n_next <= '1';
+            ram_oe_n  <= '0';
+         else                                    --write
+            if clk_reg = '1' then
+               ram_data <= (others => 'Z');
+            else
+               ram_data <= data_write;
+            end if;
+            ram_ub1_n <= not byte_we(3);
+            ram_lb1_n <= not byte_we(2);
+            ram_ub2_n <= not byte_we(1);
+            ram_lb2_n <= not byte_we(0);
+            we_n_next <= '0';
+            ram_oe_n  <= '1';
+         end if;
+      else
+         ram_data <= (others => 'Z');
+         ram_ce1_n <= '1';
+         ram_ub1_n <= '1';
+         ram_lb1_n <= '1';
+         ram_ce2_n <= '1';
+         ram_ub2_n <= '1';
+         ram_lb2_n <= '1';
+         we_n_next <= '1';
+         ram_oe_n  <= '1';
+      end if;
+   end process; --ram_control
+
+   u1_plama: plasma 
+      generic map (memory_type => "XILINX_16X",
+                   log_file    => "UNUSED")
+      PORT MAP (
+         clk               => clk_reg,
+         reset             => reset,
+         uart_write        => uart_write,
+         uart_read         => uart_read,
+         address           => mem_address,
+         byte_we           => byte_we,
+         data_write        => data_write,
+         data_read         => data_reg,
+         mem_pause_in      => mem_pause_in,
+         
+         gpio0_out         => gpio0_out,
+         gpioA_in          => gpioA_in);
+         
+end; --architecture logic
+
diff --git a/vhdl/ram.vhd b/vhdl/ram.vhd
new file mode 100644 (file)
index 0000000..9c0f511
--- /dev/null
@@ -0,0 +1,176 @@
+---------------------------------------------------------------------
+-- TITLE: Random Access Memory
+-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
+-- DATE CREATED: 4/21/01
+-- FILENAME: ram.vhd
+-- PROJECT: Plasma CPU core
+-- COPYRIGHT: Software placed into the public domain by the author.
+--    Software 'as is' without warranty.  Author liable for nothing.
+-- DESCRIPTION:
+--    Implements the RAM, reads the executable from either "code.txt",
+--    or for Altera "code[0-3].hex".
+--    Modified from "The Designer's Guide to VHDL" by Peter J. Ashenden
+---------------------------------------------------------------------
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_misc.all;
+use ieee.std_logic_arith.all;
+use ieee.std_logic_unsigned.all;
+use ieee.std_logic_textio.all;
+use std.textio.all;
+use work.mlite_pack.all;
+
+entity ram is
+   generic(memory_type : string := "DEFAULT");
+   port(clk               : in std_logic;
+        enable            : in std_logic;
+        write_byte_enable : in std_logic_vector(3 downto 0);
+        address           : in std_logic_vector(31 downto 2);
+        data_write        : in std_logic_vector(31 downto 0);
+        data_read         : out std_logic_vector(31 downto 0));
+end; --entity ram
+
+architecture logic of ram is
+   constant ADDRESS_WIDTH   : natural := 13;
+begin
+
+   generic_ram:
+   if memory_type /= "ALTERA_LPM" generate 
+   begin
+   --Simulate a synchronous RAM
+   ram_proc: process(clk, enable, write_byte_enable, 
+         address, data_write) --mem_write, mem_sel
+      variable mem_size : natural := 2 ** ADDRESS_WIDTH;
+      variable data : std_logic_vector(31 downto 0); 
+      subtype word is std_logic_vector(data_write'length-1 downto 0);
+      type storage_array is
+         array(natural range 0 to mem_size/4 - 1) of word;
+      variable storage : storage_array;
+      variable index : natural := 0;
+      file load_file : text open read_mode is "code.txt";
+      variable hex_file_line : line;
+   begin
+
+      --Load in the ram executable image
+      if index = 0 then
+         while not endfile(load_file) loop
+--The following two lines had to be commented out for synthesis
+            readline(load_file, hex_file_line);
+            hread(hex_file_line, data);
+            storage(index) := data;
+            index := index + 1;
+         end loop;
+      end if;
+
+      if rising_edge(clk) then
+         index := conv_integer(address(ADDRESS_WIDTH-1 downto 2));
+         data := storage(index);
+
+         if enable = '1' then
+            if write_byte_enable(0) = '1' then
+               data(7 downto 0) := data_write(7 downto 0);
+            end if;
+            if write_byte_enable(1) = '1' then
+               data(15 downto 8) := data_write(15 downto 8);
+            end if;
+            if write_byte_enable(2) = '1' then
+               data(23 downto 16) := data_write(23 downto 16);
+            end if;
+            if write_byte_enable(3) = '1' then
+               data(31 downto 24) := data_write(31 downto 24);
+            end if;
+         end if;
+      
+         if write_byte_enable /= "0000" then
+            storage(index) := data;
+         end if;
+      end if;
+
+      data_read <= data;
+   end process;
+   end generate; --generic_ram
+
+
+   altera_ram:
+   if memory_type = "ALTERA_LPM" generate
+      signal byte_we : std_logic_vector(3 downto 0);
+   begin
+      byte_we <= write_byte_enable when enable = '1' else "0000";
+      lpm_ram_io_component0 : lpm_ram_dq
+         GENERIC MAP (
+            intended_device_family => "UNUSED",
+            lpm_width => 8,
+            lpm_widthad => ADDRESS_WIDTH-2,
+            lpm_indata => "REGISTERED",
+            lpm_address_control => "REGISTERED",
+            lpm_outdata => "UNREGISTERED",
+            lpm_file => "code0.hex",
+            use_eab => "ON",
+            lpm_type => "LPM_RAM_DQ")
+         PORT MAP (
+            data    => data_write(31 downto 24),
+            address => address(ADDRESS_WIDTH-1 downto 2),
+            inclock => clk,
+            we      => byte_we(3),
+            q       => data_read(31 downto 24));
+
+      lpm_ram_io_component1 : lpm_ram_dq
+         GENERIC MAP (
+            intended_device_family => "UNUSED",
+            lpm_width => 8,
+            lpm_widthad => ADDRESS_WIDTH-2,
+            lpm_indata => "REGISTERED",
+            lpm_address_control => "REGISTERED",
+            lpm_outdata => "UNREGISTERED",
+            lpm_file => "code1.hex",
+            use_eab => "ON",
+            lpm_type => "LPM_RAM_DQ")
+         PORT MAP (
+            data    => data_write(23 downto 16),
+            address => address(ADDRESS_WIDTH-1 downto 2),
+            inclock => clk,
+            we      => byte_we(2),
+            q       => data_read(23 downto 16));
+
+      lpm_ram_io_component2 : lpm_ram_dq
+         GENERIC MAP (
+            intended_device_family => "UNUSED",
+            lpm_width => 8,
+            lpm_widthad => ADDRESS_WIDTH-2,
+            lpm_indata => "REGISTERED",
+            lpm_address_control => "REGISTERED",
+            lpm_outdata => "UNREGISTERED",
+            lpm_file => "code2.hex",
+            use_eab => "ON",
+            lpm_type => "LPM_RAM_DQ")
+         PORT MAP (
+            data    => data_write(15 downto 8),
+            address => address(ADDRESS_WIDTH-1 downto 2),
+            inclock => clk,
+            we      => byte_we(1),
+            q       => data_read(15 downto 8));
+
+      lpm_ram_io_component3 : lpm_ram_dq
+         GENERIC MAP (
+            intended_device_family => "UNUSED",
+            lpm_width => 8,
+            lpm_widthad => ADDRESS_WIDTH-2,
+            lpm_indata => "REGISTERED",
+            lpm_address_control => "REGISTERED",
+            lpm_outdata => "UNREGISTERED",
+            lpm_file => "code3.hex",
+            use_eab => "ON",
+            lpm_type => "LPM_RAM_DQ")
+         PORT MAP (
+            data    => data_write(7 downto 0),
+            address => address(ADDRESS_WIDTH-1 downto 2),
+            inclock => clk,
+            we      => byte_we(0),
+            q       => data_read(7 downto 0));
+
+   end generate; --altera_ram
+
+
+   --For XILINX see ram_xilinx.vhd
+
+end; --architecture logic
diff --git a/vhdl/ram_xilinx.vhd b/vhdl/ram_xilinx.vhd
new file mode 100644 (file)
index 0000000..a1f2a03
--- /dev/null
@@ -0,0 +1,2641 @@
+---------------------------------------------------------------------\r
+-- TITLE: Random Access Memory for Xilinx\r
+-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)\r
+-- DATE CREATED: 11/06/05\r
+-- FILENAME: ram_xilinx.vhd\r
+-- PROJECT: Plasma CPU core\r
+-- COPYRIGHT: Software placed into the public domain by the author.\r
+--    Software 'as is' without warranty.  Author liable for nothing.\r
+-- DESCRIPTION:\r
+--    Implements Plasma internal RAM as RAMB for Spartan 3x \r
+--    \r
+--    Compile the MIPS C and assembly code into "test.axf".\r
+--    Run convert.exe to change "test.axf" to "code.txt" which\r
+--    will contain the hex values of the opcodes.\r
+--    Next run "ram_image ram_xilinx.vhd code.txt ram_image.vhd",\r
+--    to create the "ram_image.vhd" file that will have the opcodes\r
+--    correctly placed inside the INIT_00 => strings.\r
+--    Then include ram_image.vhd in the simulation/synthesis.\r
+--\r
+--    Warning:  Addresses 0x1000 - 0x1FFF are reserved for the cache\r
+--    if the DDR cache is enabled.\r
+---------------------------------------------------------------------\r
+-- UPDATED: 09/07/10 Olivier Rinaudo (orinaudo@gmail.com)\r
+-- new behaviour: 8KB expandable to 64KB of internal RAM\r
+--\r
+-- MEMORY MAP\r
+--    0000..1FFF : 8KB   8KB  block0 (upper 4KB used as DDR cache)\r
+--    2000..3FFF : 8KB  16KB  block1 \r
+--    4000..5FFF : 8KB  24KB  block2\r
+--    6000..7FFF : 8KB  32KB  block3\r
+--    8000..9FFF : 8KB  40KB  block4\r
+--    A000..BFFF : 8KB  48KB  block5\r
+--    C000..DFFF : 8KB  56KB  block6\r
+--    E000..FFFF : 8KB  64KB  block7\r
+---------------------------------------------------------------------\r
+library ieee;\r
+use ieee.std_logic_1164.all;\r
+use ieee.std_logic_unsigned.all;\r
+use work.mlite_pack.all;\r
+\r
+library UNISIM;\r
+use UNISIM.vcomponents.all;\r
+\r
+entity ram is\r
+   generic(memory_type : string := "DEFAULT";\r
+           --Number of 8KB blocks of internal RAM, up to 64KB (1 to 8)\r
+           block_count : integer := 1); \r
+   port(clk               : in std_logic;\r
+        enable            : in std_logic;\r
+        write_byte_enable : in std_logic_vector(3 downto 0);\r
+        address           : in std_logic_vector(31 downto 2);\r
+        data_write        : in std_logic_vector(31 downto 0);\r
+        data_read         : out std_logic_vector(31 downto 0));\r
+end; --entity ram\r
+\r
+architecture logic of ram is\r
+   --type\r
+   type mem32_vector IS ARRAY (NATURAL RANGE<>) OF std_logic_vector(31 downto 0);\r
+\r
+   --Which 8KB block\r
+   alias block_sel: std_logic_vector(2 downto 0) is address(15 downto 13);\r
+\r
+   --Address within a 8KB block (without lower two bits)\r
+   alias block_addr : std_logic_vector(10 downto 0) is address(12 downto 2);\r
+\r
+   --Block enable with 1 bit per memory block\r
+   signal block_enable: std_logic_vector(7 downto 0);\r
+\r
+   --Block Data Out\r
+   signal block_do: mem32_vector(7 downto 0);\r
+\r
+   --Remember which block was selected\r
+   signal block_sel_buf: std_logic_vector(2 downto 0);\r
+\r
+begin\r
+   block_enable<= "00000001" when (enable='1') and (block_sel="000") else \r
+                  "00000010" when (enable='1') and (block_sel="001") else \r
+                  "00000100" when (enable='1') and (block_sel="010") else \r
+                  "00001000" when (enable='1') and (block_sel="011") else \r
+                  "00010000" when (enable='1') and (block_sel="100") else \r
+                  "00100000" when (enable='1') and (block_sel="101") else \r
+                  "01000000" when (enable='1') and (block_sel="110") else \r
+                  "10000000" when (enable='1') and (block_sel="111") else\r
+                  "00000000";\r
+  \r
+   proc_blocksel: process (clk, block_sel) is\r
+   begin\r
+      if rising_edge(clk) then \r
+         block_sel_buf <= block_sel;\r
+      end if;\r
+   end process;\r
+\r
+   proc_do: process (block_do, block_sel_buf) is\r
+   begin\r
+      data_read <= block_do(conv_integer(block_sel_buf));\r
+   end process;\r
+       \r
+       -- BLOCKS generation\r
+   block0: if (block_count > 0) generate\r
+       begin\r
+\r
+    ram_byte3 : RAMB16_S9\r
+   generic map (\r
+INIT_00 => X"000000000000000000000000000000000000000000000000000000000c080400",\r
+INIT_01 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_02 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_03 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_04 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_05 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_06 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_07 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_08 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_09 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_11 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_12 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_13 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_14 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_15 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_16 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_17 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_18 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000"\r
+)\r
+    port map (\r
+      DO   => block_do(0)(31 downto 24), \r
+      DOP  => open, \r
+      ADDR => block_addr,\r
+      CLK  => clk, \r
+      DI   => data_write(31 downto 24),\r
+      DIP  => ZERO(0 downto 0),\r
+      EN   => block_enable(0),\r
+      SSR  => ZERO(0),\r
+      WE   => write_byte_enable(3));\r
+\r
+    ram_byte2 : RAMB16_S9\r
+   generic map (\r
+INIT_00 => X"000000000000000000000000000000000000000000000000000000000d090501",\r
+INIT_01 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_02 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_03 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_04 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_05 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_06 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_07 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_08 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_09 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_11 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_12 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_13 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_14 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_15 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_16 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_17 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_18 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000"\r
+)\r
+    port map (\r
+      DO   => block_do(0)(23 downto 16),\r
+      DOP  => open, \r
+      ADDR => block_addr,\r
+      CLK  => clk, \r
+      DI   => data_write(23 downto 16),\r
+      DIP  => ZERO(0 downto 0),\r
+      EN   => block_enable(0),\r
+      SSR  => ZERO(0),\r
+      WE   => write_byte_enable(2));\r
+       \r
+    ram_byte1 : RAMB16_S9\r
+   generic map (\r
+INIT_00 => X"000000000000000000000000000000000000000000000000000000000e0a0602",\r
+INIT_01 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_02 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_03 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_04 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_05 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_06 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_07 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_08 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_09 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_11 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_12 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_13 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_14 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_15 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_16 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_17 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_18 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000"\r
+)\r
+    port map (\r
+      DO   => block_do(0)(15 downto 8),\r
+      DOP  => open, \r
+      ADDR => block_addr,\r
+      CLK  => clk, \r
+      DI   => data_write(15 downto 8),\r
+      DIP  => ZERO(0 downto 0),\r
+      EN   => block_enable(0),\r
+      SSR  => ZERO(0),\r
+      WE   => write_byte_enable(1));\r
+\r
+    ram_byte0 : RAMB16_S9\r
+   generic map (\r
+INIT_00 => X"000000000000000000000000000000000000000000000000000000000f0b0703",\r
+INIT_01 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_02 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_03 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_04 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_05 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_06 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_07 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_08 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_09 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_11 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_12 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_13 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_14 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_15 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_16 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_17 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_18 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000"\r
+)\r
+    port map (\r
+      DO   => block_do(0)(7 downto 0),\r
+      DOP  => open, \r
+      ADDR => block_addr,\r
+      CLK  => clk, \r
+      DI   => data_write(7 downto 0),\r
+      DIP  => ZERO(0 downto 0),\r
+      EN   => block_enable(0),\r
+      SSR  => ZERO(0),\r
+      WE   => write_byte_enable(0));\r
+   end generate; --block0\r
+       \r
+\r
+   block1: if (block_count > 1) generate\r
+       begin\r
+\r
+    ram_byte3 : RAMB16_S9\r
+   generic map (\r
+INIT_00 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_01 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_02 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_03 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_04 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_05 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_06 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_07 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_08 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_09 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_11 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_12 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_13 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_14 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_15 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_16 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_17 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_18 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000"\r
+)\r
+    port map (\r
+      DO   => block_do(1)(31 downto 24), \r
+      DOP  => open, \r
+      ADDR => block_addr,\r
+      CLK  => clk, \r
+      DI   => data_write(31 downto 24),\r
+      DIP  => ZERO(0 downto 0),\r
+      EN   => block_enable(1),\r
+      SSR  => ZERO(0),\r
+      WE   => write_byte_enable(3));\r
+\r
+    ram_byte2 : RAMB16_S9\r
+   generic map (\r
+INIT_00 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_01 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_02 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_03 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_04 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_05 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_06 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_07 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_08 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_09 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_11 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_12 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_13 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_14 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_15 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_16 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_17 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_18 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000"\r
+)\r
+    port map (\r
+      DO   => block_do(1)(23 downto 16),\r
+      DOP  => open, \r
+      ADDR => block_addr,\r
+      CLK  => clk, \r
+      DI   => data_write(23 downto 16),\r
+      DIP  => ZERO(0 downto 0),\r
+      EN   => block_enable(1),\r
+      SSR  => ZERO(0),\r
+      WE   => write_byte_enable(2));\r
+       \r
+    ram_byte1 : RAMB16_S9\r
+   generic map (\r
+INIT_00 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_01 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_02 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_03 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_04 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_05 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_06 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_07 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_08 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_09 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_11 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_12 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_13 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_14 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_15 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_16 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_17 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_18 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000"\r
+)\r
+    port map (\r
+      DO   => block_do(1)(15 downto 8),\r
+      DOP  => open, \r
+      ADDR => block_addr,\r
+      CLK  => clk, \r
+      DI   => data_write(15 downto 8),\r
+      DIP  => ZERO(0 downto 0),\r
+      EN   => block_enable(1),\r
+      SSR  => ZERO(0),\r
+      WE   => write_byte_enable(1));\r
+\r
+    ram_byte0 : RAMB16_S9\r
+   generic map (\r
+INIT_00 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_01 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_02 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_03 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_04 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_05 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_06 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_07 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_08 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_09 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_11 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_12 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_13 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_14 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_15 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_16 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_17 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_18 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000"\r
+)\r
+    port map (\r
+      DO   => block_do(1)(7 downto 0),\r
+      DOP  => open, \r
+      ADDR => block_addr,\r
+      CLK  => clk, \r
+      DI   => data_write(7 downto 0),\r
+      DIP  => ZERO(0 downto 0),\r
+      EN   => block_enable(1),\r
+      SSR  => ZERO(0),\r
+      WE   => write_byte_enable(0));\r
+               \r
+   end generate; --block1\r
+       \r
+\r
+   block2: if (block_count > 2) generate\r
+       begin\r
+\r
+    ram_byte3 : RAMB16_S9\r
+   generic map (\r
+INIT_00 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_01 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_02 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_03 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_04 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_05 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_06 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_07 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_08 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_09 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_11 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_12 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_13 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_14 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_15 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_16 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_17 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_18 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000"\r
+)\r
+    port map (\r
+      DO   => block_do(2)(31 downto 24), \r
+      DOP  => open, \r
+      ADDR => block_addr,\r
+      CLK  => clk, \r
+      DI   => data_write(31 downto 24),\r
+      DIP  => ZERO(0 downto 0),\r
+      EN   => block_enable(2),\r
+      SSR  => ZERO(0),\r
+      WE   => write_byte_enable(3));\r
+\r
+    ram_byte2 : RAMB16_S9\r
+   generic map (\r
+INIT_00 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_01 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_02 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_03 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_04 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_05 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_06 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_07 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_08 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_09 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_11 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_12 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_13 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_14 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_15 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_16 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_17 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_18 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000"\r
+)\r
+    port map (\r
+      DO   => block_do(2)(23 downto 16),\r
+      DOP  => open, \r
+      ADDR => block_addr,\r
+      CLK  => clk, \r
+      DI   => data_write(23 downto 16),\r
+      DIP  => ZERO(0 downto 0),\r
+      EN   => block_enable(2),\r
+      SSR  => ZERO(0),\r
+      WE   => write_byte_enable(2));\r
+       \r
+    ram_byte1 : RAMB16_S9\r
+   generic map (\r
+INIT_00 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_01 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_02 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_03 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_04 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_05 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_06 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_07 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_08 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_09 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_11 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_12 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_13 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_14 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_15 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_16 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_17 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_18 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000"\r
+)\r
+    port map (\r
+      DO   => block_do(2)(15 downto 8),\r
+      DOP  => open, \r
+      ADDR => block_addr,\r
+      CLK  => clk, \r
+      DI   => data_write(15 downto 8),\r
+      DIP  => ZERO(0 downto 0),\r
+      EN   => block_enable(2),\r
+      SSR  => ZERO(0),\r
+      WE   => write_byte_enable(1));\r
+\r
+    ram_byte0 : RAMB16_S9\r
+   generic map (\r
+INIT_00 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_01 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_02 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_03 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_04 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_05 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_06 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_07 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_08 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_09 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_11 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_12 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_13 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_14 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_15 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_16 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_17 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_18 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000"\r
+)\r
+    port map (\r
+      DO   => block_do(2)(7 downto 0),\r
+      DOP  => open, \r
+      ADDR => block_addr,\r
+      CLK  => clk, \r
+      DI   => data_write(7 downto 0),\r
+      DIP  => ZERO(0 downto 0),\r
+      EN   => block_enable(2),\r
+      SSR  => ZERO(0),\r
+      WE   => write_byte_enable(0));\r
+               \r
+   end generate; --block2\r
+\r
+\r
+   block3: if (block_count > 3) generate\r
+       begin\r
+\r
+    ram_byte3 : RAMB16_S9\r
+   generic map (\r
+INIT_00 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_01 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_02 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_03 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_04 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_05 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_06 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_07 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_08 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_09 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_11 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_12 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_13 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_14 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_15 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_16 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_17 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_18 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000"\r
+)\r
+    port map (\r
+      DO   => block_do(3)(31 downto 24), \r
+      DOP  => open, \r
+      ADDR => block_addr,\r
+      CLK  => clk, \r
+      DI   => data_write(31 downto 24),\r
+      DIP  => ZERO(0 downto 0),\r
+      EN   => block_enable(3),\r
+      SSR  => ZERO(0),\r
+      WE   => write_byte_enable(3));\r
+\r
+    ram_byte2 : RAMB16_S9\r
+   generic map (\r
+INIT_00 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_01 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_02 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_03 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_04 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_05 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_06 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_07 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_08 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_09 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_11 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_12 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_13 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_14 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_15 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_16 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_17 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_18 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000"\r
+)\r
+    port map (\r
+      DO   => block_do(3)(23 downto 16),\r
+      DOP  => open, \r
+      ADDR => block_addr,\r
+      CLK  => clk, \r
+      DI   => data_write(23 downto 16),\r
+      DIP  => ZERO(0 downto 0),\r
+      EN   => block_enable(3),\r
+      SSR  => ZERO(0),\r
+      WE   => write_byte_enable(2));\r
+       \r
+    ram_byte1 : RAMB16_S9\r
+   generic map (\r
+INIT_00 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_01 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_02 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_03 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_04 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_05 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_06 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_07 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_08 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_09 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_11 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_12 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_13 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_14 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_15 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_16 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_17 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_18 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000"\r
+)\r
+    port map (\r
+      DO   => block_do(3)(15 downto 8),\r
+      DOP  => open, \r
+      ADDR => block_addr,\r
+      CLK  => clk, \r
+      DI   => data_write(15 downto 8),\r
+      DIP  => ZERO(0 downto 0),\r
+      EN   => block_enable(3),\r
+      SSR  => ZERO(0),\r
+      WE   => write_byte_enable(1));\r
+\r
+    ram_byte0 : RAMB16_S9\r
+   generic map (\r
+INIT_00 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_01 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_02 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_03 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_04 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_05 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_06 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_07 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_08 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_09 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_11 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_12 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_13 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_14 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_15 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_16 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_17 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_18 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000"\r
+)\r
+    port map (\r
+      DO   => block_do(3)(7 downto 0),\r
+      DOP  => open, \r
+      ADDR => block_addr,\r
+      CLK  => clk, \r
+      DI   => data_write(7 downto 0),\r
+      DIP  => ZERO(0 downto 0),\r
+      EN   => block_enable(3),\r
+      SSR  => ZERO(0),\r
+      WE   => write_byte_enable(0));\r
+               \r
+   end generate; --block3\r
+\r
+\r
+   block4: if (block_count > 4) generate\r
+       begin\r
+\r
+    ram_byte3 : RAMB16_S9\r
+   generic map (\r
+INIT_00 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_01 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_02 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_03 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_04 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_05 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_06 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_07 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_08 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_09 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_11 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_12 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_13 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_14 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_15 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_16 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_17 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_18 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000"\r
+)\r
+    port map (\r
+      DO   => block_do(4)(31 downto 24), \r
+      DOP  => open, \r
+      ADDR => block_addr,\r
+      CLK  => clk, \r
+      DI   => data_write(31 downto 24),\r
+      DIP  => ZERO(0 downto 0),\r
+      EN   => block_enable(4),\r
+      SSR  => ZERO(0),\r
+      WE   => write_byte_enable(3));\r
+\r
+    ram_byte2 : RAMB16_S9\r
+   generic map (\r
+INIT_00 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_01 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_02 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_03 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_04 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_05 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_06 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_07 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_08 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_09 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_11 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_12 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_13 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_14 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_15 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_16 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_17 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_18 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000"\r
+)\r
+    port map (\r
+      DO   => block_do(4)(23 downto 16),\r
+      DOP  => open, \r
+      ADDR => block_addr,\r
+      CLK  => clk, \r
+      DI   => data_write(23 downto 16),\r
+      DIP  => ZERO(0 downto 0),\r
+      EN   => block_enable(4),\r
+      SSR  => ZERO(0),\r
+      WE   => write_byte_enable(2));\r
+       \r
+    ram_byte1 : RAMB16_S9\r
+   generic map (\r
+INIT_00 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_01 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_02 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_03 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_04 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_05 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_06 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_07 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_08 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_09 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_11 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_12 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_13 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_14 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_15 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_16 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_17 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_18 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000"\r
+)\r
+    port map (\r
+      DO   => block_do(4)(15 downto 8),\r
+      DOP  => open, \r
+      ADDR => block_addr,\r
+      CLK  => clk, \r
+      DI   => data_write(15 downto 8),\r
+      DIP  => ZERO(0 downto 0),\r
+      EN   => block_enable(4),\r
+      SSR  => ZERO(0),\r
+      WE   => write_byte_enable(1));\r
+\r
+    ram_byte0 : RAMB16_S9\r
+   generic map (\r
+INIT_00 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_01 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_02 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_03 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_04 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_05 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_06 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_07 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_08 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_09 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_11 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_12 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_13 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_14 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_15 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_16 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_17 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_18 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000"\r
+)\r
+    port map (\r
+      DO   => block_do(4)(7 downto 0),\r
+      DOP  => open, \r
+      ADDR => block_addr,\r
+      CLK  => clk, \r
+      DI   => data_write(7 downto 0),\r
+      DIP  => ZERO(0 downto 0),\r
+      EN   => block_enable(4),\r
+      SSR  => ZERO(0),\r
+      WE   => write_byte_enable(0));\r
+               \r
+   end generate; --block4\r
+\r
+\r
+   block5: if (block_count > 5) generate\r
+       begin\r
+\r
+    ram_byte3 : RAMB16_S9\r
+   generic map (\r
+INIT_00 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_01 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_02 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_03 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_04 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_05 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_06 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_07 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_08 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_09 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_11 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_12 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_13 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_14 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_15 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_16 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_17 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_18 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000"\r
+)\r
+    port map (\r
+      DO   => block_do(5)(31 downto 24), \r
+      DOP  => open, \r
+      ADDR => block_addr,\r
+      CLK  => clk, \r
+      DI   => data_write(31 downto 24),\r
+      DIP  => ZERO(0 downto 0),\r
+      EN   => block_enable(5),\r
+      SSR  => ZERO(0),\r
+      WE   => write_byte_enable(3));\r
+\r
+    ram_byte2 : RAMB16_S9\r
+   generic map (\r
+INIT_00 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_01 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_02 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_03 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_04 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_05 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_06 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_07 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_08 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_09 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_11 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_12 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_13 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_14 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_15 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_16 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_17 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_18 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000"\r
+)\r
+    port map (\r
+      DO   => block_do(5)(23 downto 16),\r
+      DOP  => open, \r
+      ADDR => block_addr,\r
+      CLK  => clk, \r
+      DI   => data_write(23 downto 16),\r
+      DIP  => ZERO(0 downto 0),\r
+      EN   => block_enable(5),\r
+      SSR  => ZERO(0),\r
+      WE   => write_byte_enable(2));\r
+       \r
+    ram_byte1 : RAMB16_S9\r
+   generic map (\r
+INIT_00 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_01 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_02 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_03 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_04 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_05 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_06 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_07 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_08 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_09 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_11 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_12 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_13 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_14 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_15 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_16 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_17 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_18 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000"\r
+)\r
+    port map (\r
+      DO   => block_do(5)(15 downto 8),\r
+      DOP  => open, \r
+      ADDR => block_addr,\r
+      CLK  => clk, \r
+      DI   => data_write(15 downto 8),\r
+      DIP  => ZERO(0 downto 0),\r
+      EN   => block_enable(5),\r
+      SSR  => ZERO(0),\r
+      WE   => write_byte_enable(1));\r
+\r
+    ram_byte0 : RAMB16_S9\r
+   generic map (\r
+INIT_00 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_01 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_02 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_03 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_04 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_05 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_06 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_07 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_08 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_09 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_11 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_12 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_13 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_14 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_15 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_16 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_17 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_18 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000"\r
+)\r
+    port map (\r
+      DO   => block_do(5)(7 downto 0),\r
+      DOP  => open, \r
+      ADDR => block_addr,\r
+      CLK  => clk, \r
+      DI   => data_write(7 downto 0),\r
+      DIP  => ZERO(0 downto 0),\r
+      EN   => block_enable(5),\r
+      SSR  => ZERO(0),\r
+      WE   => write_byte_enable(0));\r
+               \r
+   end generate; --block5\r
+\r
+\r
+   block6: if (block_count > 6) generate\r
+       begin\r
+\r
+    ram_byte3 : RAMB16_S9\r
+   generic map (\r
+INIT_00 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_01 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_02 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_03 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_04 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_05 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_06 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_07 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_08 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_09 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_11 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_12 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_13 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_14 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_15 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_16 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_17 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_18 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000"\r
+)\r
+    port map (\r
+      DO   => block_do(6)(31 downto 24), \r
+      DOP  => open, \r
+      ADDR => block_addr,\r
+      CLK  => clk, \r
+      DI   => data_write(31 downto 24),\r
+      DIP  => ZERO(0 downto 0),\r
+      EN   => block_enable(6),\r
+      SSR  => ZERO(0),\r
+      WE   => write_byte_enable(3));\r
+\r
+    ram_byte2 : RAMB16_S9\r
+   generic map (\r
+INIT_00 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_01 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_02 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_03 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_04 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_05 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_06 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_07 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_08 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_09 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_11 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_12 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_13 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_14 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_15 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_16 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_17 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_18 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000"\r
+)\r
+    port map (\r
+      DO   => block_do(6)(23 downto 16),\r
+      DOP  => open, \r
+      ADDR => block_addr,\r
+      CLK  => clk, \r
+      DI   => data_write(23 downto 16),\r
+      DIP  => ZERO(0 downto 0),\r
+      EN   => block_enable(6),\r
+      SSR  => ZERO(0),\r
+      WE   => write_byte_enable(2));\r
+       \r
+    ram_byte1 : RAMB16_S9\r
+   generic map (\r
+INIT_00 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_01 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_02 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_03 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_04 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_05 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_06 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_07 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_08 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_09 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_11 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_12 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_13 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_14 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_15 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_16 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_17 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_18 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000"\r
+)\r
+    port map (\r
+      DO   => block_do(6)(15 downto 8),\r
+      DOP  => open, \r
+      ADDR => block_addr,\r
+      CLK  => clk, \r
+      DI   => data_write(15 downto 8),\r
+      DIP  => ZERO(0 downto 0),\r
+      EN   => block_enable(6),\r
+      SSR  => ZERO(0),\r
+      WE   => write_byte_enable(1));\r
+\r
+    ram_byte0 : RAMB16_S9\r
+   generic map (\r
+INIT_00 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_01 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_02 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_03 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_04 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_05 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_06 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_07 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_08 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_09 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_11 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_12 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_13 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_14 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_15 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_16 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_17 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_18 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000"\r
+)\r
+    port map (\r
+      DO   => block_do(6)(7 downto 0),\r
+      DOP  => open, \r
+      ADDR => block_addr,\r
+      CLK  => clk, \r
+      DI   => data_write(7 downto 0),\r
+      DIP  => ZERO(0 downto 0),\r
+      EN   => block_enable(6),\r
+      SSR  => ZERO(0),\r
+      WE   => write_byte_enable(0));\r
+               \r
+   end generate; --block6\r
+\r
+\r
+   block7: if (block_count > 7) generate\r
+       begin\r
+\r
+    ram_byte3 : RAMB16_S9\r
+   generic map (\r
+INIT_00 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_01 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_02 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_03 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_04 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_05 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_06 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_07 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_08 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_09 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_11 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_12 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_13 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_14 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_15 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_16 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_17 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_18 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000"\r
+)\r
+    port map (\r
+      DO   => block_do(7)(31 downto 24), \r
+      DOP  => open, \r
+      ADDR => block_addr,\r
+      CLK  => clk, \r
+      DI   => data_write(31 downto 24),\r
+      DIP  => ZERO(0 downto 0),\r
+      EN   => block_enable(7),\r
+      SSR  => ZERO(0),\r
+      WE   => write_byte_enable(3));\r
+\r
+    ram_byte2 : RAMB16_S9\r
+   generic map (\r
+INIT_00 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_01 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_02 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_03 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_04 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_05 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_06 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_07 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_08 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_09 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_11 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_12 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_13 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_14 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_15 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_16 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_17 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_18 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000"\r
+)\r
+    port map (\r
+      DO   => block_do(7)(23 downto 16),\r
+      DOP  => open, \r
+      ADDR => block_addr,\r
+      CLK  => clk, \r
+      DI   => data_write(23 downto 16),\r
+      DIP  => ZERO(0 downto 0),\r
+      EN   => block_enable(7),\r
+      SSR  => ZERO(0),\r
+      WE   => write_byte_enable(2));\r
+       \r
+    ram_byte1 : RAMB16_S9\r
+   generic map (\r
+INIT_00 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_01 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_02 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_03 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_04 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_05 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_06 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_07 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_08 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_09 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_11 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_12 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_13 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_14 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_15 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_16 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_17 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_18 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000"\r
+)\r
+    port map (\r
+      DO   => block_do(7)(15 downto 8),\r
+      DOP  => open, \r
+      ADDR => block_addr,\r
+      CLK  => clk, \r
+      DI   => data_write(15 downto 8),\r
+      DIP  => ZERO(0 downto 0),\r
+      EN   => block_enable(7),\r
+      SSR  => ZERO(0),\r
+      WE   => write_byte_enable(1));\r
+\r
+    ram_byte0 : RAMB16_S9\r
+   generic map (\r
+INIT_00 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_01 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_02 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_03 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_04 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_05 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_06 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_07 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_08 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_09 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_11 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_12 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_13 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_14 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_15 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_16 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_17 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_18 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",\r
+INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000"\r
+)\r
+    port map (\r
+      DO   => block_do(7)(7 downto 0),\r
+      DOP  => open, \r
+      ADDR => block_addr,\r
+      CLK  => clk, \r
+      DI   => data_write(7 downto 0),\r
+      DIP  => ZERO(0 downto 0),\r
+      EN   => block_enable(7),\r
+      SSR  => ZERO(0),\r
+      WE   => write_byte_enable(0));\r
+               \r
+   end generate; --block7\r
+\r
+end; --architecture logic\r
diff --git a/vhdl/reg_bank.vhd b/vhdl/reg_bank.vhd
new file mode 100644 (file)
index 0000000..91a2ef5
--- /dev/null
@@ -0,0 +1,375 @@
+---------------------------------------------------------------------\r
+-- TITLE: Register Bank\r
+-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)\r
+-- DATE CREATED: 2/2/01\r
+-- FILENAME: reg_bank.vhd\r
+-- PROJECT: Plasma CPU core\r
+-- COPYRIGHT: Software placed into the public domain by the author.\r
+--    Software 'as is' without warranty.  Author liable for nothing.\r
+-- DESCRIPTION:\r
+--    Implements a register bank with 32 registers that are 32-bits wide.\r
+--    There are two read-ports and one write port.\r
+---------------------------------------------------------------------\r
+library ieee;\r
+use ieee.std_logic_1164.all;\r
+use ieee.std_logic_unsigned.all;\r
+use work.mlite_pack.all;\r
+--library UNISIM;               --May need to uncomment for ModelSim\r
+--use UNISIM.vcomponents.all;   --May need to uncomment for ModelSim\r
+\r
+entity reg_bank is\r
+   generic(memory_type : string := "XILINX_16X");\r
+   port(clk            : in  std_logic;\r
+        reset_in       : in  std_logic;\r
+        pause          : in  std_logic;\r
+        rs_index       : in  std_logic_vector(5 downto 0);\r
+        rt_index       : in  std_logic_vector(5 downto 0);\r
+        rd_index       : in  std_logic_vector(5 downto 0);\r
+        reg_source_out : out std_logic_vector(31 downto 0);\r
+        reg_target_out : out std_logic_vector(31 downto 0);\r
+        reg_dest_new   : in  std_logic_vector(31 downto 0);\r
+        intr_enable    : out std_logic);\r
+end; --entity reg_bank\r
+\r
+\r
+--------------------------------------------------------------------\r
+-- The ram_block architecture attempts to use TWO dual-port memories.\r
+-- Different FPGAs and ASICs need different implementations.\r
+-- Choose one of the RAM implementations below.\r
+-- I need feedback on this section!\r
+--------------------------------------------------------------------\r
+architecture ram_block of reg_bank is\r
+   signal intr_enable_reg : std_logic;\r
+   type ram_type is array(31 downto 0) of std_logic_vector(31 downto 0);\r
+   \r
+   --controls access to dual-port memories\r
+   signal addr_read1, addr_read2 : std_logic_vector(4 downto 0);\r
+   signal addr_write             : std_logic_vector(4 downto 0);\r
+   signal data_out1, data_out2   : std_logic_vector(31 downto 0);\r
+   signal write_enable           : std_logic;\r
+\r
+begin\r
+  \r
+reg_proc: process(clk, rs_index, rt_index, rd_index, reg_dest_new, \r
+      intr_enable_reg, data_out1, data_out2, reset_in, pause)\r
+begin\r
+   --setup for first dual-port memory\r
+   if rs_index = "101110" then  --reg_epc CP0 14\r
+      addr_read1 <= "00000";\r
+   else\r
+      addr_read1 <= rs_index(4 downto 0);\r
+   end if;\r
+   case rs_index is\r
+   when "000000" => reg_source_out <= ZERO;\r
+   when "101100" => reg_source_out <= ZERO(31 downto 1) & intr_enable_reg;\r
+                    --interrupt vector address = 0x3c\r
+   when "111111" => reg_source_out <= ZERO(31 downto 8) & "00111100";\r
+   when others   => reg_source_out <= data_out1;\r
+   end case;\r
+\r
+   --setup for second dual-port memory\r
+   addr_read2 <= rt_index(4 downto 0);\r
+   case rt_index is\r
+   when "000000" => reg_target_out <= ZERO;\r
+   when others   => reg_target_out <= data_out2;\r
+   end case;\r
+\r
+   --setup write port for both dual-port memories\r
+   if rd_index /= "000000" and rd_index /= "101100" and pause = '0' then\r
+      write_enable <= '1';\r
+   else\r
+      write_enable <= '0';\r
+   end if;\r
+   if rd_index = "101110" then  --reg_epc CP0 14\r
+      addr_write <= "00000";\r
+   else\r
+      addr_write <= rd_index(4 downto 0);\r
+   end if;\r
+\r
+   if reset_in = '1' then\r
+      intr_enable_reg <= '0';\r
+   elsif rising_edge(clk) then\r
+      if rd_index = "101110" then     --reg_epc CP0 14\r
+         intr_enable_reg <= '0';      --disable interrupts\r
+      elsif rd_index = "101100" then\r
+         intr_enable_reg <= reg_dest_new(0);\r
+      end if;\r
+   end if;\r
+\r
+   intr_enable <= intr_enable_reg;\r
+end process;\r
+\r
+\r
+--------------------------------------------------------------\r
+---- Pick only ONE of the dual-port RAM implementations below!\r
+--------------------------------------------------------------\r
+\r
+   -- Option #1\r
+   -- One tri-port RAM, two read-ports, one write-port\r
+   -- 32 registers 32-bits wide\r
+   tri_port_mem:\r
+   if memory_type = "TRI_PORT_X" generate\r
+      ram_proc: process(clk, addr_read1, addr_read2, \r
+            addr_write, reg_dest_new, write_enable)\r
+      variable tri_port_ram : ram_type := (others => ZERO);\r
+      begin\r
+         data_out1 <= tri_port_ram(conv_integer(addr_read1));\r
+         data_out2 <= tri_port_ram(conv_integer(addr_read2));\r
+         if rising_edge(clk) then\r
+            if write_enable = '1' then\r
+               tri_port_ram(conv_integer(addr_write)) := reg_dest_new;\r
+            end if;\r
+         end if;\r
+      end process;\r
+   end generate; --tri_port_mem\r
+\r
+\r
+   -- Option #2\r
+   -- Two dual-port RAMs, each with one read-port and one write-port\r
+   dual_port_mem:\r
+   if memory_type = "DUAL_PORT_" generate\r
+      ram_proc2: process(clk, addr_read1, addr_read2, \r
+            addr_write, reg_dest_new, write_enable)\r
+      variable dual_port_ram1 : ram_type := (others => ZERO);\r
+      variable dual_port_ram2 : ram_type := (others => ZERO);\r
+      begin\r
+         data_out1 <= dual_port_ram1(conv_integer(addr_read1));\r
+         data_out2 <= dual_port_ram2(conv_integer(addr_read2));\r
+         if rising_edge(clk) then\r
+            if write_enable = '1' then\r
+               dual_port_ram1(conv_integer(addr_write)) := reg_dest_new;\r
+               dual_port_ram2(conv_integer(addr_write)) := reg_dest_new;\r
+            end if;\r
+         end if;\r
+      end process;\r
+   end generate; --dual_port_mem\r
+\r
+\r
+   -- Option #3\r
+   -- RAM16X1D: 16 x 1 positive edge write, asynchronous read dual-port \r
+   -- distributed RAM for all Xilinx FPGAs\r
+   -- From library UNISIM; use UNISIM.vcomponents.all;\r
+   xilinx_16x1d:\r
+   if memory_type = "XILINX_16X" generate\r
+      signal data_out1A, data_out1B : std_logic_vector(31 downto 0);\r
+      signal data_out2A, data_out2B : std_logic_vector(31 downto 0);\r
+      signal weA, weB               : std_logic;\r
+      signal no_connect             : std_logic_vector(127 downto 0);\r
+   begin\r
+      weA <= write_enable and not addr_write(4);  --lower 16 registers\r
+      weB <= write_enable and addr_write(4);      --upper 16 registers\r
+      \r
+      reg_loop: for i in 0 to 31 generate\r
+      begin\r
+         --Read port 1 lower 16 registers\r
+         reg_bit1a : RAM16X1D\r
+         port map (\r
+            WCLK  => clk,              -- Port A write clock input\r
+            WE    => weA,              -- Port A write enable input\r
+            A0    => addr_write(0),    -- Port A address[0] input bit\r
+            A1    => addr_write(1),    -- Port A address[1] input bit\r
+            A2    => addr_write(2),    -- Port A address[2] input bit\r
+            A3    => addr_write(3),    -- Port A address[3] input bit\r
+            D     => reg_dest_new(i),  -- Port A 1-bit data input\r
+            DPRA0 => addr_read1(0),    -- Port B address[0] input bit\r
+            DPRA1 => addr_read1(1),    -- Port B address[1] input bit\r
+            DPRA2 => addr_read1(2),    -- Port B address[2] input bit\r
+            DPRA3 => addr_read1(3),    -- Port B address[3] input bit\r
+            DPO   => data_out1A(i),    -- Port B 1-bit data output\r
+            SPO   => no_connect(i)     -- Port A 1-bit data output\r
+         );\r
+         --Read port 1 upper 16 registers\r
+         reg_bit1b : RAM16X1D\r
+         port map (\r
+            WCLK  => clk,              -- Port A write clock input\r
+            WE    => weB,              -- Port A write enable input\r
+            A0    => addr_write(0),    -- Port A address[0] input bit\r
+            A1    => addr_write(1),    -- Port A address[1] input bit\r
+            A2    => addr_write(2),    -- Port A address[2] input bit\r
+            A3    => addr_write(3),    -- Port A address[3] input bit\r
+            D     => reg_dest_new(i),  -- Port A 1-bit data input\r
+            DPRA0 => addr_read1(0),    -- Port B address[0] input bit\r
+            DPRA1 => addr_read1(1),    -- Port B address[1] input bit\r
+            DPRA2 => addr_read1(2),    -- Port B address[2] input bit\r
+            DPRA3 => addr_read1(3),    -- Port B address[3] input bit\r
+            DPO   => data_out1B(i),    -- Port B 1-bit data output\r
+            SPO   => no_connect(32+i)  -- Port A 1-bit data output\r
+         );\r
+         --Read port 2 lower 16 registers\r
+         reg_bit2a : RAM16X1D\r
+         port map (\r
+            WCLK  => clk,              -- Port A write clock input\r
+            WE    => weA,              -- Port A write enable input\r
+            A0    => addr_write(0),    -- Port A address[0] input bit\r
+            A1    => addr_write(1),    -- Port A address[1] input bit\r
+            A2    => addr_write(2),    -- Port A address[2] input bit\r
+            A3    => addr_write(3),    -- Port A address[3] input bit\r
+            D     => reg_dest_new(i),  -- Port A 1-bit data input\r
+            DPRA0 => addr_read2(0),    -- Port B address[0] input bit\r
+            DPRA1 => addr_read2(1),    -- Port B address[1] input bit\r
+            DPRA2 => addr_read2(2),    -- Port B address[2] input bit\r
+            DPRA3 => addr_read2(3),    -- Port B address[3] input bit\r
+            DPO   => data_out2A(i),    -- Port B 1-bit data output\r
+            SPO   => no_connect(64+i)  -- Port A 1-bit data output\r
+         );\r
+         --Read port 2 upper 16 registers\r
+         reg_bit2b : RAM16X1D\r
+         port map (\r
+            WCLK  => clk,              -- Port A write clock input\r
+            WE    => weB,              -- Port A write enable input\r
+            A0    => addr_write(0),    -- Port A address[0] input bit\r
+            A1    => addr_write(1),    -- Port A address[1] input bit\r
+            A2    => addr_write(2),    -- Port A address[2] input bit\r
+            A3    => addr_write(3),    -- Port A address[3] input bit\r
+            D     => reg_dest_new(i),  -- Port A 1-bit data input\r
+            DPRA0 => addr_read2(0),    -- Port B address[0] input bit\r
+            DPRA1 => addr_read2(1),    -- Port B address[1] input bit\r
+            DPRA2 => addr_read2(2),    -- Port B address[2] input bit\r
+            DPRA3 => addr_read2(3),    -- Port B address[3] input bit\r
+            DPO   => data_out2B(i),    -- Port B 1-bit data output\r
+            SPO   => no_connect(96+i)  -- Port A 1-bit data output\r
+         );\r
+      end generate; --reg_loop\r
+\r
+      data_out1 <= data_out1A when addr_read1(4)='0' else data_out1B;\r
+      data_out2 <= data_out2A when addr_read2(4)='0' else data_out2B;\r
+   end generate; --xilinx_16x1d\r
+\r
+\r
+   -- Option #4\r
+   -- RAM32X1D: 32 x 1 positive edge write, asynchronous read dual-port \r
+   -- distributed RAM for 5-LUT Xilinx FPGAs such as Virtex-5\r
+   -- From library UNISIM; use UNISIM.vcomponents.all;\r
+   xilinx_32x1d:\r
+   if memory_type = "XILINX_32X" generate\r
+      signal no_connect             : std_logic_vector(63 downto 0);\r
+   begin\r
+      reg_loop: for i in 0 to 31 generate\r
+      begin\r
+         --Read port 1\r
+         reg_bit1 : RAM32X1D\r
+         port map (\r
+            WCLK  => clk,              -- Port A write clock input\r
+            WE    => write_enable,     -- Port A write enable input\r
+            A0    => addr_write(0),    -- Port A address[0] input bit\r
+            A1    => addr_write(1),    -- Port A address[1] input bit\r
+            A2    => addr_write(2),    -- Port A address[2] input bit\r
+            A3    => addr_write(3),    -- Port A address[3] input bit\r
+            A4    => addr_write(4),    -- Port A address[4] input bit\r
+            D     => reg_dest_new(i),  -- Port A 1-bit data input\r
+            DPRA0 => addr_read1(0),    -- Port B address[0] input bit\r
+            DPRA1 => addr_read1(1),    -- Port B address[1] input bit\r
+            DPRA2 => addr_read1(2),    -- Port B address[2] input bit\r
+            DPRA3 => addr_read1(3),    -- Port B address[3] input bit\r
+            DPRA4 => addr_read1(4),    -- Port B address[4] input bit\r
+            DPO   => data_out1(i),     -- Port B 1-bit data output\r
+            SPO   => no_connect(i)     -- Port A 1-bit data output\r
+         );\r
+         --Read port 2\r
+         reg_bit2 : RAM32X1D\r
+         port map (\r
+            WCLK  => clk,              -- Port A write clock input\r
+            WE    => write_enable,     -- Port A write enable input\r
+            A0    => addr_write(0),    -- Port A address[0] input bit\r
+            A1    => addr_write(1),    -- Port A address[1] input bit\r
+            A2    => addr_write(2),    -- Port A address[2] input bit\r
+            A3    => addr_write(3),    -- Port A address[3] input bit\r
+            A4    => addr_write(4),    -- Port A address[4] input bit\r
+            D     => reg_dest_new(i),  -- Port A 1-bit data input\r
+            DPRA0 => addr_read2(0),    -- Port B address[0] input bit\r
+            DPRA1 => addr_read2(1),    -- Port B address[1] input bit\r
+            DPRA2 => addr_read2(2),    -- Port B address[2] input bit\r
+            DPRA3 => addr_read2(3),    -- Port B address[3] input bit\r
+            DPRA4 => addr_read2(4),    -- Port B address[4] input bit\r
+            DPO   => data_out2(i),     -- Port B 1-bit data output\r
+            SPO   => no_connect(32+i)  -- Port A 1-bit data output\r
+         );\r
+      end generate; --reg_loop\r
+   end generate; --xilinx_32x1d\r
+\r
+\r
+   -- Option #5\r
+   -- Altera LPM_RAM_DP\r
+   altera_mem:\r
+   if memory_type = "ALTERA_LPM" generate\r
+      signal clk_delayed : std_logic;\r
+      signal addr_reg    : std_logic_vector(4 downto 0);\r
+      signal data_reg    : std_logic_vector(31 downto 0);\r
+      signal q1          : std_logic_vector(31 downto 0);\r
+      signal q2          : std_logic_vector(31 downto 0);\r
+   begin\r
+      -- Altera dual port RAMs must have the addresses registered (sampled\r
+      -- at the rising edge).  This is very unfortunate.\r
+      -- Therefore, the dual port RAM read clock must delayed so that\r
+      -- the read address signal can be sent from the mem_ctrl block.\r
+      -- This solution also delays the how fast the registers are read so the \r
+      -- maximum clock speed is cut in half (12.5 MHz instead of 25 MHz).\r
+\r
+      clk_delayed <= not clk;  --Could be delayed by 1/4 clock cycle instead\r
+      dpram_bypass: process(clk, addr_write, reg_dest_new, write_enable)\r
+      begin\r
+         if rising_edge(clk) and write_enable = '1' then\r
+            addr_reg <= addr_write;\r
+            data_reg <= reg_dest_new;\r
+         end if;\r
+      end process; --dpram_bypass\r
+\r
+      -- Bypass dpram if reading what was just written (Altera limitation)\r
+      data_out1 <= q1 when addr_read1 /= addr_reg else data_reg;\r
+      data_out2 <= q2 when addr_read2 /= addr_reg else data_reg;\r
+      \r
+      lpm_ram_dp_component1 : lpm_ram_dp\r
+      generic map (\r
+         LPM_WIDTH => 32,\r
+         LPM_WIDTHAD => 5,\r
+         --LPM_NUMWORDS => 0,\r
+         LPM_INDATA => "REGISTERED",\r
+         LPM_OUTDATA => "UNREGISTERED",\r
+         LPM_RDADDRESS_CONTROL => "REGISTERED",\r
+         LPM_WRADDRESS_CONTROL => "REGISTERED",\r
+         LPM_FILE => "UNUSED",\r
+         LPM_TYPE => "LPM_RAM_DP",\r
+         USE_EAB  => "ON",\r
+         INTENDED_DEVICE_FAMILY => "UNUSED",\r
+         RDEN_USED => "FALSE",\r
+         LPM_HINT => "UNUSED")\r
+      port map (\r
+         RDCLOCK   => clk_delayed,\r
+         RDCLKEN   => '1',\r
+         RDADDRESS => addr_read1,\r
+         RDEN      => '1',\r
+         DATA      => reg_dest_new,\r
+         WRADDRESS => addr_write,\r
+         WREN      => write_enable,\r
+         WRCLOCK   => clk,\r
+         WRCLKEN   => '1',\r
+         Q         => q1);\r
+      lpm_ram_dp_component2 : lpm_ram_dp\r
+      generic map (\r
+         LPM_WIDTH => 32,\r
+         LPM_WIDTHAD => 5,\r
+         --LPM_NUMWORDS => 0,\r
+         LPM_INDATA => "REGISTERED",\r
+         LPM_OUTDATA => "UNREGISTERED",\r
+         LPM_RDADDRESS_CONTROL => "REGISTERED",\r
+         LPM_WRADDRESS_CONTROL => "REGISTERED",\r
+         LPM_FILE => "UNUSED",\r
+         LPM_TYPE => "LPM_RAM_DP",\r
+         USE_EAB  => "ON",\r
+         INTENDED_DEVICE_FAMILY => "UNUSED",\r
+         RDEN_USED => "FALSE",\r
+         LPM_HINT => "UNUSED")\r
+      port map (\r
+         RDCLOCK   => clk_delayed,\r
+         RDCLKEN   => '1',\r
+         RDADDRESS => addr_read2,\r
+         RDEN      => '1',\r
+         DATA      => reg_dest_new,\r
+         WRADDRESS => addr_write,\r
+         WREN      => write_enable,\r
+         WRCLOCK   => clk,\r
+         WRCLKEN   => '1',\r
+         Q         => q2);\r
+   end generate; --altera_mem\r
+\r
+end; --architecture ram_block\r
diff --git a/vhdl/shifter.vhd b/vhdl/shifter.vhd
new file mode 100644 (file)
index 0000000..f4a574b
--- /dev/null
@@ -0,0 +1,65 @@
+---------------------------------------------------------------------
+-- TITLE: Shifter Unit
+-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
+--         Matthias Gruenewald
+-- DATE CREATED: 2/2/01
+-- FILENAME: shifter.vhd
+-- PROJECT: Plasma CPU core
+-- COPYRIGHT: Software placed into the public domain by the author.
+--    Software 'as is' without warranty.  Author liable for nothing.
+-- DESCRIPTION:
+--    Implements the 32-bit shifter unit.
+---------------------------------------------------------------------
+library ieee;
+use ieee.std_logic_1164.all;
+use work.mlite_pack.all;
+
+entity shifter is
+   generic(shifter_type : string := "DEFAULT");
+   port(value        : in  std_logic_vector(31 downto 0);
+        shift_amount : in  std_logic_vector(4 downto 0);
+        shift_func   : in  shift_function_type;
+        c_shift      : out std_logic_vector(31 downto 0));
+end; --entity shifter
+
+architecture logic of shifter is
+--   type shift_function_type is (
+--      shift_nothing, shift_left_unsigned, 
+--      shift_right_signed, shift_right_unsigned);
+
+signal shift1L, shift2L, shift4L, shift8L, shift16L : std_logic_vector(31 downto 0);
+signal shift1R, shift2R, shift4R, shift8R, shift16R : std_logic_vector(31 downto 0);
+signal fills : std_logic_vector(31 downto 16);
+
+begin
+   fills <= "1111111111111111" when shift_func = SHIFT_RIGHT_SIGNED 
+                                   and value(31) = '1' 
+                                                                                else "0000000000000000";
+   shift1L  <= value(30 downto 0) & '0' when shift_amount(0) = '1' else value;
+   shift2L  <= shift1L(29 downto 0) & "00" when shift_amount(1) = '1' else shift1L;
+   shift4L  <= shift2L(27 downto 0) & "0000" when shift_amount(2) = '1' else shift2L;
+   shift8L  <= shift4L(23 downto 0) & "00000000" when shift_amount(3) = '1' else shift4L;
+   shift16L <= shift8L(15 downto 0) & ZERO(15 downto 0) when shift_amount(4) = '1' else shift8L;
+
+   shift1R  <= fills(31) & value(31 downto 1) when shift_amount(0) = '1' else value;
+   shift2R  <= fills(31 downto 30) & shift1R(31 downto 2) when shift_amount(1) = '1' else shift1R;
+   shift4R  <= fills(31 downto 28) & shift2R(31 downto 4) when shift_amount(2) = '1' else shift2R;
+   shift8R  <= fills(31 downto 24) & shift4R(31 downto 8)  when shift_amount(3) = '1' else shift4R;
+   shift16R <= fills(31 downto 16) & shift8R(31 downto 16) when shift_amount(4) = '1' else shift8R;
+
+GENERIC_SHIFTER: if shifter_type = "DEFAULT" generate
+   c_shift <= shift16L when shift_func = SHIFT_LEFT_UNSIGNED else 
+              shift16R when shift_func = SHIFT_RIGHT_UNSIGNED or 
+                                               shift_func = SHIFT_RIGHT_SIGNED else
+              ZERO;
+end generate;
+                 
+AREA_OPTIMIZED_SHIFTER: if shifter_type /= "DEFAULT" generate
+   c_shift <= shift16L when shift_func = SHIFT_LEFT_UNSIGNED else (others => 'Z');
+   c_shift <= shift16R when shift_func = SHIFT_RIGHT_UNSIGNED or 
+                            shift_func = SHIFT_RIGHT_SIGNED else (others => 'Z');
+   c_shift <= ZERO     when shift_func = SHIFT_NOTHING else (others => 'Z');
+end generate;
+
+end; --architecture logic
+
diff --git a/vhdl/simili.cmd b/vhdl/simili.cmd
new file mode 100755 (executable)
index 0000000..bf46409
--- /dev/null
@@ -0,0 +1,8 @@
+add list /u1/*
+#add list /u1/u1_cpu/*
+#add list /u1/u1_cpu/u8_mult/*
+#add list /u1/u1_cpu/pc /u1/u1_cpu/opcode /u1/*
+#add list /u1/u1_cpu/u3_control/*
+#add list /u1/u1_cpu/u8_mult/*
+SetListStyle nodelta collapse
+SetListInterval 0us 1ms
diff --git a/vhdl/spartan3e.ucf b/vhdl/spartan3e.ucf
new file mode 100644 (file)
index 0000000..04c0b2d
--- /dev/null
@@ -0,0 +1,279 @@
+#####################################################
+### SPARTAN-3E STARTER KIT BOARD CONSTRAINTS FILE
+#####################################################
+# ==== Analog-to-Digital Converter (ADC) ====
+# some connections shared with SPI Flash, DAC, ADC, and AMP
+#NET "AD_CONV" LOC = "P11" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 6 ;
+# ==== Programmable Gain Amplifier (AMP) ====
+# some connections shared with SPI Flash, DAC, ADC, and AMP
+#NET "AMP_CS" LOC = "N7" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 6 ;
+#NET "AMP_DOUT" LOC = "E18" | IOSTANDARD = LVCMOS33 ;
+#NET "AMP_SHDN" LOC = "P7" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 6 ;
+# ==== Pushbuttons (BTN) ====
+NET "BTN_EAST" LOC = "H13" | IOSTANDARD = LVTTL | PULLDOWN ;
+NET "BTN_NORTH" LOC = "V4" | IOSTANDARD = LVTTL | PULLDOWN ;
+NET "BTN_SOUTH" LOC = "K17" | IOSTANDARD = LVTTL | PULLDOWN ;
+NET "BTN_WEST" LOC = "D18" | IOSTANDARD = LVTTL | PULLDOWN ;
+# ==== Clock inputs (CLK) ====
+NET "CLK_50MHZ" LOC = "C9" | IOSTANDARD = LVCMOS33 ;
+# Define clock period for 50 MHz oscillator (40%/60% duty-cycle)
+NET "CLK_50MHZ" PERIOD = 20 ns HIGH 40 %;
+#NET "CLK_AUX" LOC = "B8" | IOSTANDARD = LVCMOS33 ;
+#NET "CLK_SMA" LOC = "A10" | IOSTANDARD = LVCMOS33 ;
+# ==== Digital-to-Analog Converter (DAC) ====
+# some connections shared with SPI Flash, DAC, ADC, and AMP
+#NET "DAC_CLR" LOC = "P8" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ;
+#NET "DAC_CS" LOC = "N8" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ;
+# ==== 1-Wire Secure EEPROM (DS)
+#NET "DS_WIRE" LOC = "U4" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 ;
+# ==== Ethernet PHY (E) ====
+#NET "E_COL" LOC = "U6" | IOSTANDARD = LVCMOS33 ;
+#NET "E_CRS" LOC = "U13" | IOSTANDARD = LVCMOS33 ;
+NET "E_MDC" LOC = "P9" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ;
+NET "E_MDIO" LOC = "U5" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ;
+NET "E_RX_CLK" LOC = "V3" | IOSTANDARD = LVCMOS33 ;
+NET "E_RX_DV" LOC = "V2" | IOSTANDARD = LVCMOS33 ;
+NET "E_RXD<0>" LOC = "V8" | IOSTANDARD = LVCMOS33 ;
+NET "E_RXD<1>" LOC = "T11" | IOSTANDARD = LVCMOS33 ;
+NET "E_RXD<2>" LOC = "U11" | IOSTANDARD = LVCMOS33 ;
+NET "E_RXD<3>" LOC = "V14" | IOSTANDARD = LVCMOS33 ;
+#NET "E_RXD<4>" LOC = "U14" | IOSTANDARD = LVCMOS33 ;
+NET "E_TX_CLK" LOC = "T7" | IOSTANDARD = LVCMOS33 ;
+NET "E_TX_EN" LOC = "P15" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ;
+NET "E_TXD<0>" LOC = "R11" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ;
+NET "E_TXD<1>" LOC = "T15" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ;
+NET "E_TXD<2>" LOC = "R5"  | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ;
+NET "E_TXD<3>" LOC = "T5"  | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ;
+#NET "E_TXD<4>" LOC = "R6" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ;
+# ==== FPGA Configuration Mode, INIT_B Pins (FPGA) ====
+#NET "FPGA_M0" LOC = "M10" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ;
+#NET "FPGA_M1" LOC = "V11" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ;
+#NET "FPGA_M2" LOC = "T10" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ;
+#NET "FPGA_INIT_B" LOC = "T3" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 4 ;
+#NET "FPGA_RDWR_B" LOC = "U10" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 4 ;
+#NET "FPGA_HSWAP" LOC = "B3" | IOSTANDARD = LVCMOS33 ;
+# ==== FX2 Connector (FX2) ====
+#NET "FX2_CLKIN" LOC = "E10" | IOSTANDARD = LVCMOS33 ;
+#NET "FX2_CLKIO" LOC = "D9" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
+#NET "FX2_CLKOUT" LOC = "D10" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
+# These four connections are shared with the J1 6-pin accessory header
+#NET "FX2_IO<1>" LOC = "B4" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
+#NET "FX2_IO<2>" LOC = "A4" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
+#NET "FX2_IO<3>" LOC = "D5" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
+#NET "FX2_IO<4>" LOC = "C5" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
+# These four connections are shared with the J2 6-pin accessory header
+#NET "FX2_IO<5>" LOC = "A6" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
+#NET "FX2_IO<6>" LOC = "B6" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
+#NET "FX2_IO<7>" LOC = "E7" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
+#NET "FX2_IO<8>" LOC = "F7" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
+# These four connections are shared with the J4 6-pin accessory header
+#NET "FX2_IO<9>" LOC = "D7" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
+#NET "FX2_IO<10>" LOC = "C7" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
+#NET "FX2_IO<11>" LOC = "F8" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
+#NET "FX2_IO<12>" LOC = "E8" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
+# The discrete LEDs are shared with the following 8 FX2 connections
+#NET "FX2_IO<13>" LOC = "F9" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
+#NET "FX2_IO<14>" LOC = "E9" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
+#NET "FX2_IO<15>" LOC = "D11" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
+#NET "FX2_IO<16>" LOC = "C11" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
+#NET "FX2_IO<17>" LOC = "F11" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
+#NET "FX2_IO<18>" LOC = "E11" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
+#NET "FX2_IO<19>" LOC = "E12" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
+#NET "FX2_IO<20>" LOC = "F12" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
+#NET "FX2_IO<21>" LOC = "A13" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
+#NET "FX2_IO<22>" LOC = "B13" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
+#NET "FX2_IO<23>" LOC = "A14" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
+#NET "FX2_IO<24>" LOC = "B14" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
+#NET "FX2_IO<25>" LOC = "C14" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
+#NET "FX2_IO<26>" LOC = "D14" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
+#NET "FX2_IO<27>" LOC = "A16" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
+#NET "FX2_IO<28>" LOC = "B16" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
+#NET "FX2_IO<29>" LOC = "E13" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
+#NET "FX2_IO<30>" LOC = "C4" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
+#NET "FX2_IO<31>" LOC = "B11" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
+#NET "FX2_IO<32>" LOC = "A11" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
+#NET "FX2_IO<33>" LOC = "A8" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
+#NET "FX2_IO<34>" LOC = "G9" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
+#NET "FX2_IP<35>" LOC = "D12" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
+#NET "FX2_IP<36>" LOC = "C12" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
+#NET "FX2_IP<37>" LOC = "A15" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
+#NET "FX2_IP<38>" LOC = "B15" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
+#NET "FX2_IO<39>" LOC = "C3" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
+#NET "FX2_IP<40>" LOC = "C15" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
+# ==== 6-pin header J1 ====
+# These are shared connections with the FX2 connector
+#NET "J1<0>" LOC = "B4" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 6 ;
+#NET "J1<1>" LOC = "A4" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 6 ;
+#NET "J1<2>" LOC = "D5" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 6 ;
+#NET "J1<3>" LOC = "C5" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 6 ;
+# ==== 6-pin header J2 ====
+# These are shared connections with the FX2 connector
+#NET "J2<0>" LOC = "A6" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 6 ;
+#NET "J2<1>" LOC = "B6" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 6 ;
+#NET "J2<2>" LOC = "E7" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 6 ;
+#NET "J2<3>" LOC = "F7" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 6 ;
+# ==== 6-pin header J4 ====
+# These are shared connections with the FX2 connector
+#NET "J4<0>" LOC = "D7" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 6 ;
+#NET "J4<1>" LOC = "C7" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 6 ;
+#NET "J4<2>" LOC = "F8" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 6 ;
+#NET "J4<3>" LOC = "E8" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 6 ;
+# ==== Character LCD (LCD) ====
+#NET "LCD_E" LOC = "M18" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
+#NET "LCD_RS" LOC = "L18" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
+#NET "LCD_RW" LOC = "L17" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
+# LCD data connections are shared with StrataFlash connections SF_D<11:8>
+#NET "SF_D<8>" LOC = "R15" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
+#NET "SF_D<9>" LOC = "R16" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
+#NET "SF_D<10>" LOC = "P17" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
+#NET "SF_D<11>" LOC = "M15" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
+# ==== Discrete LEDs (LED) ====
+# These are shared connections with the FX2 connector
+NET "LED<0>" LOC = "F12" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 ;
+NET "LED<1>" LOC = "E12" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 ;
+NET "LED<2>" LOC = "E11" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 ;
+NET "LED<3>" LOC = "F11" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 ;
+NET "LED<4>" LOC = "C11" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 ;
+NET "LED<5>" LOC = "D11" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 ;
+NET "LED<6>" LOC = "E9" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 ;
+NET "LED<7>" LOC = "F9" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 ;
+# ==== PS/2 Mouse/Keyboard Port (PS2) ====
+NET "PS2_CLK" LOC = "G14" | IOSTANDARD = LVCMOS33 ;
+NET "PS2_DATA" LOC = "G13" | IOSTANDARD = LVCMOS33 ;
+# ==== Rotary Pushbutton Switch (ROT) ====
+NET "ROT_A" LOC = "K18" | IOSTANDARD = LVTTL | PULLUP ;
+NET "ROT_B" LOC = "G18" | IOSTANDARD = LVTTL | PULLUP ;
+NET "ROT_CENTER" LOC = "V16" | IOSTANDARD = LVTTL | PULLDOWN ;
+# ==== RS-232 Serial Ports (RS232) ====
+NET "RS232_DCE_RXD" LOC = "R7" | IOSTANDARD = LVTTL ;
+NET "RS232_DCE_TXD" LOC = "M14" | IOSTANDARD = LVTTL | DRIVE = 8 | SLEW = SLOW ;
+#NET "RS232_DTE_RXD" LOC = "U8" | IOSTANDARD = LVTTL ;
+#NET "RS232_DTE_TXD" LOC = "M13" | IOSTANDARD = LVTTL | DRIVE = 8 | SLEW = SLOW ;
+# ==== DDR SDRAM (SD) ==== (I/O Bank 3, VCCO=2.5V)
+NET "SD_A<0>" LOC = "T1" | IOSTANDARD = SSTL2_I ;
+NET "SD_A<1>" LOC = "R3" | IOSTANDARD = SSTL2_I ;
+NET "SD_A<2>" LOC = "R2" | IOSTANDARD = SSTL2_I ;
+NET "SD_A<3>" LOC = "P1" | IOSTANDARD = SSTL2_I ;
+NET "SD_A<4>" LOC = "F4" | IOSTANDARD = SSTL2_I ;
+NET "SD_A<5>" LOC = "H4" | IOSTANDARD = SSTL2_I ;
+NET "SD_A<6>" LOC = "H3" | IOSTANDARD = SSTL2_I ;
+NET "SD_A<7>" LOC = "H1" | IOSTANDARD = SSTL2_I ;
+NET "SD_A<8>" LOC = "H2" | IOSTANDARD = SSTL2_I ;
+NET "SD_A<9>" LOC = "N4" | IOSTANDARD = SSTL2_I ;
+NET "SD_A<10>" LOC = "T2" | IOSTANDARD = SSTL2_I ;
+NET "SD_A<11>" LOC = "N5" | IOSTANDARD = SSTL2_I ;
+NET "SD_A<12>" LOC = "P2" | IOSTANDARD = SSTL2_I ;
+NET "SD_BA<0>" LOC = "K5" | IOSTANDARD = SSTL2_I ;
+NET "SD_BA<1>" LOC = "K6" | IOSTANDARD = SSTL2_I ;
+NET "SD_CAS" LOC = "C2" | IOSTANDARD = SSTL2_I ;
+NET "SD_CK_N" LOC = "J4" | IOSTANDARD = SSTL2_I ;
+NET "SD_CK_P" LOC = "J5" | IOSTANDARD = SSTL2_I ;
+NET "SD_CKE" LOC = "K3" | IOSTANDARD = SSTL2_I ;
+NET "SD_CS" LOC = "K4" | IOSTANDARD = SSTL2_I ;
+NET "SD_DQ<0>" LOC = "L2" | IOSTANDARD = SSTL2_I ;
+NET "SD_DQ<1>" LOC = "L1" | IOSTANDARD = SSTL2_I ;
+NET "SD_DQ<2>" LOC = "L3" | IOSTANDARD = SSTL2_I ;
+NET "SD_DQ<3>" LOC = "L4" | IOSTANDARD = SSTL2_I ;
+NET "SD_DQ<4>" LOC = "M3" | IOSTANDARD = SSTL2_I ;
+NET "SD_DQ<5>" LOC = "M4" | IOSTANDARD = SSTL2_I ;
+NET "SD_DQ<6>" LOC = "M5" | IOSTANDARD = SSTL2_I ;
+NET "SD_DQ<7>" LOC = "M6" | IOSTANDARD = SSTL2_I ;
+NET "SD_DQ<8>" LOC = "E2" | IOSTANDARD = SSTL2_I ;
+NET "SD_DQ<9>" LOC = "E1" | IOSTANDARD = SSTL2_I ;
+NET "SD_DQ<10>" LOC = "F1" | IOSTANDARD = SSTL2_I ;
+NET "SD_DQ<11>" LOC = "F2" | IOSTANDARD = SSTL2_I ;
+NET "SD_DQ<12>" LOC = "G6" | IOSTANDARD = SSTL2_I ;
+NET "SD_DQ<13>" LOC = "G5" | IOSTANDARD = SSTL2_I ;
+NET "SD_DQ<14>" LOC = "H6" | IOSTANDARD = SSTL2_I ;
+NET "SD_DQ<15>" LOC = "H5" | IOSTANDARD = SSTL2_I ;
+NET "SD_LDM" LOC = "J2" | IOSTANDARD = SSTL2_I ;
+NET "SD_LDQS" LOC = "L6" | IOSTANDARD = SSTL2_I ;
+NET "SD_RAS" LOC = "C1" | IOSTANDARD = SSTL2_I ;
+NET "SD_UDM" LOC = "J1" | IOSTANDARD = SSTL2_I ;
+NET "SD_UDQS" LOC = "G3" | IOSTANDARD = SSTL2_I ;
+NET "SD_WE" LOC = "D1" | IOSTANDARD = SSTL2_I ;
+# Path to allow connection to top DCM connection
+#NET "SD_CK_FB" LOC = "B9" | IOSTANDARD = LVCMOS33 ;
+# Prohibit VREF pins
+CONFIG PROHIBIT = D2;
+CONFIG PROHIBIT = G4;
+CONFIG PROHIBIT = J6;
+CONFIG PROHIBIT = L5;
+CONFIG PROHIBIT = R4;
+# ==== Intel StrataFlash Parallel NOR Flash (SF) ====
+NET "SF_A<0>" LOC = "H17" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
+NET "SF_A<1>" LOC = "J13" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
+NET "SF_A<2>" LOC = "J12" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
+NET "SF_A<3>" LOC = "J14" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
+NET "SF_A<4>" LOC = "J15" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
+NET "SF_A<5>" LOC = "J16" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
+NET "SF_A<6>" LOC = "J17" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
+NET "SF_A<7>" LOC = "K14" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
+NET "SF_A<8>" LOC = "K15" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
+NET "SF_A<9>" LOC = "K12" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
+NET "SF_A<10>" LOC = "K13" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
+NET "SF_A<11>" LOC = "L15" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
+NET "SF_A<12>" LOC = "L16" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
+NET "SF_A<13>" LOC = "T18" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
+NET "SF_A<14>" LOC = "R18" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
+NET "SF_A<15>" LOC = "T17" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
+NET "SF_A<16>" LOC = "U18" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
+NET "SF_A<17>" LOC = "T16" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
+NET "SF_A<18>" LOC = "U15" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
+NET "SF_A<19>" LOC = "V15" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
+NET "SF_A<20>" LOC = "T12" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
+NET "SF_A<21>" LOC = "V13" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
+NET "SF_A<22>" LOC = "V12" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
+NET "SF_A<23>" LOC = "N11" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
+NET "SF_A<24>" LOC = "A11" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
+NET "SF_BYTE" LOC = "C17" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
+NET "SF_CE0" LOC = "D16" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
+NET "SF_D<1>" LOC = "P10" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
+NET "SF_D<2>" LOC = "R10" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
+NET "SF_D<3>" LOC = "V9" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
+NET "SF_D<4>" LOC = "U9" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
+NET "SF_D<5>" LOC = "R9" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
+NET "SF_D<6>" LOC = "M9" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
+NET "SF_D<7>" LOC = "N9" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
+NET "SF_D<8>" LOC = "R15" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
+NET "SF_D<9>" LOC = "R16" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
+NET "SF_D<10>" LOC = "P17" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
+NET "SF_D<11>" LOC = "M15" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
+NET "SF_D<12>" LOC = "M16" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
+NET "SF_D<13>" LOC = "P6" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
+NET "SF_D<14>" LOC = "R8" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
+NET "SF_D<15>" LOC = "T8" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
+NET "SF_OE" LOC = "C18" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
+NET "SF_STS" LOC = "B18" | IOSTANDARD = LVCMOS33 ;
+NET "SF_WE" LOC = "D17" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
+# ==== STMicro SPI serial Flash (SPI) ====
+# some connections shared with SPI Flash, DAC, ADC, and AMP
+NET "SPI_MISO" LOC = "N10" | IOSTANDARD = LVCMOS33 ;
+#NET "SPI_MOSI" LOC = "T4" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 6 ;
+#NET "SPI_SCK" LOC = "U16" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 6 ;
+#NET "SPI_SS_B" LOC = "U3" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 6 ;
+#NET "SPI_ALT_CS_JP11" LOC = "R12" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 6 ;
+# ==== Slide Switches (SW) ====
+NET "SW<0>" LOC = "L13" | IOSTANDARD = LVTTL | PULLUP ;
+NET "SW<1>" LOC = "L14" | IOSTANDARD = LVTTL | PULLUP ;
+NET "SW<2>" LOC = "H18" | IOSTANDARD = LVTTL | PULLUP ;
+NET "SW<3>" LOC = "N17" | IOSTANDARD = LVTTL | PULLUP ;
+# ==== VGA Port (VGA) ====
+NET "VGA_BLUE" LOC = "G15" | IOSTANDARD = LVTTL | DRIVE = 8 | SLEW = FAST ;
+NET "VGA_GREEN" LOC = "H15" | IOSTANDARD = LVTTL | DRIVE = 8 | SLEW = FAST ;
+NET "VGA_HSYNC" LOC = "F15" | IOSTANDARD = LVTTL | DRIVE = 8 | SLEW = FAST ;
+NET "VGA_RED" LOC = "H14" | IOSTANDARD = LVTTL | DRIVE = 8 | SLEW = FAST ;
+NET "VGA_VSYNC" LOC = "F14" | IOSTANDARD = LVTTL | DRIVE = 8 | SLEW = FAST ;
+# ==== Xilinx CPLD (XC) ====
+#NET "XC_CMD<0>" LOC = "P18" | IOSTANDARD = LVTTL | DRIVE = 4 | SLEW = SLOW ;
+#NET "XC_CMD<1>" LOC = "N18" | IOSTANDARD = LVTTL | DRIVE = 4 | SLEW = SLOW ;
+#NET "XC_CPLD_EN" LOC = "B10" | IOSTANDARD = LVTTL ;
+#NET "XC_D<0>" LOC = "G16" | IOSTANDARD = LVTTL | DRIVE = 4 | SLEW = SLOW ;
+#NET "XC_D<1>" LOC = "F18" | IOSTANDARD = LVTTL | DRIVE = 4 | SLEW = SLOW ;
+#NET "XC_D<2>" LOC = "F17" | IOSTANDARD = LVTTL | DRIVE = 4 | SLEW = SLOW ;
+#NET "XC_TRIG" LOC = "R17" | IOSTANDARD = LVCMOS33 ;
+#NET "XC_GCK0" LOC = "H16" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
+#NET "GCLK10" LOC = "C9" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
+NET "CLK_50MHZ" TNM_NET = "CLK_50MHZ";
+NET "clk_reg1" TNM_NET = "clk_reg1";
+TIMESPEC "TS_clk_reg1" = PERIOD "clk_reg1" 40 ns HIGH 50 %;
diff --git a/vhdl/tbench.vhd b/vhdl/tbench.vhd
new file mode 100644 (file)
index 0000000..700c123
--- /dev/null
@@ -0,0 +1,119 @@
+---------------------------------------------------------------------
+-- TITLE: Test Bench
+-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
+-- DATE CREATED: 4/21/01
+-- FILENAME: tbench.vhd
+-- PROJECT: Plasma CPU core
+-- COPYRIGHT: Software placed into the public domain by the author.
+--    Software 'as is' without warranty.  Author liable for nothing.
+-- DESCRIPTION:
+--    This entity provides a test bench for testing the Plasma CPU core.
+---------------------------------------------------------------------
+library ieee;
+use ieee.std_logic_1164.all;
+use work.mlite_pack.all;
+use ieee.std_logic_unsigned.all;
+
+entity tbench is
+end; --entity tbench
+
+architecture logic of tbench is
+   constant memory_type : string := 
+   "TRI_PORT_X";   
+--   "DUAL_PORT_";
+--   "ALTERA_LPM";
+--   "XILINX_16X";
+
+   constant log_file  : string := 
+--   "UNUSED";
+   "output.txt";
+
+   signal clk         : std_logic := '1';
+   signal reset       : std_logic := '1';
+   signal interrupt   : std_logic := '0';
+   signal mem_write   : std_logic;
+   signal address     : std_logic_vector(31 downto 2);
+   signal data_write  : std_logic_vector(31 downto 0);
+   signal data_read   : std_logic_vector(31 downto 0);
+   signal pause1      : std_logic := '0';
+   signal pause2      : std_logic := '0';
+   signal pause       : std_logic;
+   signal no_ddr_start: std_logic;
+   signal no_ddr_stop : std_logic;
+   signal byte_we     : std_logic_vector(3 downto 0);
+   signal uart_write  : std_logic;
+   signal gpioA_in    : std_logic_vector(31 downto 0) := (others => '0');
+begin  --architecture
+   --Uncomment the line below to test interrupts
+   interrupt <= '1' after 20 us when interrupt = '0' else '0' after 445 ns;
+
+   clk   <= not clk after 50 ns;
+   reset <= '0' after 500 ns;
+   pause1 <= '1' after 700 ns when pause1 = '0' else '0' after 200 ns;
+   pause2 <= '1' after 300 ns when pause2 = '0' else '0' after 200 ns;
+   pause <= pause1 or pause2;
+   gpioA_in(20) <= not gpioA_in(20) after 200 ns; --E_RX_CLK
+   gpioA_in(19) <= not gpioA_in(19) after 20 us;  --E_RX_DV
+   gpioA_in(18 downto 15) <= gpioA_in(18 downto 15) + 1 after 400 ns; --E_RX_RXD
+   gpioA_in(14) <= not gpioA_in(14) after 200 ns; --E_TX_CLK
+
+   u1_plasma: plasma
+      generic map (memory_type => memory_type,
+                   ethernet    => '1',
+                   use_cache   => '1',
+                   log_file    => log_file)
+      PORT MAP (
+         clk               => clk,
+         reset             => reset,
+         uart_read         => uart_write,
+         uart_write        => uart_write,
+         address           => address,
+         byte_we           => byte_we,
+         data_write        => data_write,
+         data_read         => data_read,
+         mem_pause_in      => pause,
+         no_ddr_start      => no_ddr_start,
+         no_ddr_stop       => no_ddr_stop,
+         
+         gpio0_out         => open,
+         gpioA_in          => gpioA_in);
+
+   dram_proc: process(clk, address, byte_we, data_write, pause)
+      constant ADDRESS_WIDTH : natural := 16;
+      type storage_array is
+         array(natural range 0 to (2 ** ADDRESS_WIDTH) / 4 - 1) of 
+         std_logic_vector(31 downto 0);
+      variable storage : storage_array;
+      variable data    : std_logic_vector(31 downto 0); 
+      variable index   : natural := 0;
+   begin
+      index := conv_integer(address(ADDRESS_WIDTH-1 downto 2));
+      data := storage(index);
+
+      if byte_we(0) = '1' then
+         data(7 downto 0) := data_write(7 downto 0);
+      end if;
+      if byte_we(1) = '1' then
+         data(15 downto 8) := data_write(15 downto 8);
+      end if;
+      if byte_we(2) = '1' then
+         data(23 downto 16) := data_write(23 downto 16);
+      end if;
+      if byte_we(3) = '1' then
+         data(31 downto 24) := data_write(31 downto 24);
+      end if;
+      
+      if rising_edge(clk) then
+         if address(30 downto 28) = "001" and byte_we /= "0000" then
+            storage(index) := data;
+         end if;
+      end if;
+
+      if pause = '0' then
+         data_read <= data;
+      end if;
+   end process;
+
+
+end; --architecture logic
diff --git a/vhdl/uart.vhd b/vhdl/uart.vhd
new file mode 100644 (file)
index 0000000..5f576fe
--- /dev/null
@@ -0,0 +1,181 @@
+---------------------------------------------------------------------
+-- TITLE: UART
+-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
+-- DATE CREATED: 5/29/02
+-- FILENAME: uart.vhd
+-- PROJECT: Plasma CPU core
+-- COPYRIGHT: Software placed into the public domain by the author.
+--    Software 'as is' without warranty.  Author liable for nothing.
+-- DESCRIPTION:
+--    Implements the UART.
+---------------------------------------------------------------------
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_misc.all;
+use ieee.std_logic_arith.all;
+use ieee.std_logic_textio.all;
+use ieee.std_logic_unsigned.all;
+use std.textio.all;
+use work.mlite_pack.all;
+
+entity uart is
+   generic(log_file : string := "UNUSED");
+   port(clk          : in std_logic;
+        reset        : in std_logic;
+        enable_read  : in std_logic;
+        enable_write : in std_logic;
+        data_in      : in std_logic_vector(7 downto 0);
+        data_out     : out std_logic_vector(7 downto 0);
+        uart_read    : in std_logic;
+        uart_write   : out std_logic;
+        busy_write   : out std_logic;
+        data_avail   : out std_logic);
+end; --entity uart
+
+architecture logic of uart is
+   signal delay_write_reg : std_logic_vector(9 downto 0);
+   signal bits_write_reg  : std_logic_vector(3 downto 0);
+   signal data_write_reg  : std_logic_vector(8 downto 0);
+   signal delay_read_reg  : std_logic_vector(9 downto 0);
+   signal bits_read_reg   : std_logic_vector(3 downto 0);
+   signal data_read_reg   : std_logic_vector(7 downto 0);
+   signal data_save_reg   : std_logic_vector(17 downto 0);
+   signal busy_write_sig  : std_logic;
+   signal read_value_reg  : std_logic_vector(6 downto 0);
+   signal uart_read2      : std_logic;
+
+begin
+
+uart_proc: process(clk, reset, enable_read, enable_write, data_in,
+                   data_write_reg, bits_write_reg, delay_write_reg, 
+                   data_read_reg, bits_read_reg, delay_read_reg,
+                   data_save_reg, read_value_reg, uart_read2,
+                   busy_write_sig, uart_read)
+   constant COUNT_VALUE : std_logic_vector(9 downto 0) :=
+--      "0100011110";  --33MHz/2/57600Hz = 0x11e
+--      "1101100100";  --50MHz/57600Hz = 0x364
+      "0110110010";  --25MHz/57600Hz = 0x1b2 -- Plasma IF uses div2
+--      "0011011001";  --12.5MHz/57600Hz = 0xd9
+--      "0000000100";  --for debug (shorten read_value_reg)
+begin
+   uart_read2 <= read_value_reg(read_value_reg'length - 1);
+
+   if reset = '1' then
+      data_write_reg  <= ZERO(8 downto 1) & '1';
+      bits_write_reg  <= "0000";
+      delay_write_reg <= ZERO(9 downto 0);
+      read_value_reg  <= ONES(read_value_reg'length-1 downto 0);
+      data_read_reg   <= ZERO(7 downto 0);
+      bits_read_reg   <= "0000";
+      delay_read_reg  <= ZERO(9 downto 0);
+      data_save_reg   <= ZERO(17 downto 0);
+   elsif rising_edge(clk) then
+
+      --Write UART
+      if bits_write_reg = "0000" then               --nothing left to write?
+         if enable_write = '1' then
+            delay_write_reg <= ZERO(9 downto 0);    --delay before next bit
+            bits_write_reg <= "1010";               --number of bits to write
+            data_write_reg <= data_in & '0';        --remember data & start bit
+         end if;
+      else
+         if delay_write_reg /= COUNT_VALUE then
+            delay_write_reg <= delay_write_reg + 1; --delay before next bit
+         else
+            delay_write_reg <= ZERO(9 downto 0);    --reset delay
+            bits_write_reg <= bits_write_reg - 1;   --bits left to write
+            data_write_reg <= '1' & data_write_reg(8 downto 1);
+         end if;
+      end if;
+
+      --Average uart_read signal
+      if uart_read = '1' then
+         if read_value_reg /= ONES(read_value_reg'length - 1 downto 0) then
+            read_value_reg <= read_value_reg + 1;
+         end if;
+      else
+         if read_value_reg /= ZERO(read_value_reg'length - 1 downto 0) then
+            read_value_reg <= read_value_reg - 1;
+         end if;
+      end if;
+
+      --Read UART
+      if delay_read_reg = ZERO(9 downto 0) then     --done delay for read?
+         if bits_read_reg = "0000" then             --nothing left to read?
+            if uart_read2 = '0' then                --wait for start bit
+               delay_read_reg <= '0' & COUNT_VALUE(9 downto 1);  --half period
+               bits_read_reg <= "1001";             --bits left to read
+            end if;
+         else
+            delay_read_reg <= COUNT_VALUE;          --initialize delay
+            bits_read_reg <= bits_read_reg - 1;     --bits left to read
+            data_read_reg <= uart_read2 & data_read_reg(7 downto 1);
+         end if;
+      else
+         delay_read_reg <= delay_read_reg - 1;      --delay
+      end if;
+
+      --Control character buffer
+      if bits_read_reg = "0000" and delay_read_reg = COUNT_VALUE then
+         if data_save_reg(8) = '0' or 
+               (enable_read = '1' and data_save_reg(17) = '0') then
+            --Empty buffer
+            data_save_reg(8 downto 0) <= '1' & data_read_reg;
+         else
+            --Second character in buffer
+            data_save_reg(17 downto 9) <= '1' & data_read_reg;
+            if enable_read = '1' then
+               data_save_reg(8 downto 0) <= data_save_reg(17 downto 9);
+            end if;
+         end if;
+      elsif enable_read = '1' then
+         data_save_reg(17) <= '0';                  --data_available
+         data_save_reg(8 downto 0) <= data_save_reg(17 downto 9);
+      end if;
+   end if;  --rising_edge(clk)
+
+   uart_write <= data_write_reg(0);
+   if bits_write_reg /= "0000" 
+-- Comment out the following line for full UART simulation (much slower)
+   and log_file = "UNUSED" 
+   then
+      busy_write_sig <= '1';
+   else
+      busy_write_sig <= '0';
+   end if;
+   busy_write <= busy_write_sig;
+   data_avail <= data_save_reg(8);
+   data_out <= data_save_reg(7 downto 0);
+   
+end process; --uart_proc
+
+-- synthesis_off
+   uart_logger:
+   if log_file /= "UNUSED" generate
+      uart_proc: process(clk, enable_write, data_in)
+         file store_file : text open write_mode is log_file;
+         variable hex_file_line : line;
+         variable c : character;
+         variable index : natural;
+         variable line_length : natural := 0;
+      begin
+         if rising_edge(clk) and busy_write_sig = '0' then
+            if enable_write = '1' then
+               index := conv_integer(data_in(6 downto 0));
+               if index /= 10 then
+                  c := character'val(index);
+                  write(hex_file_line, c);
+                  line_length := line_length + 1;
+               end if;
+               if index = 10 or line_length >= 72 then
+--The following line may have to be commented out for synthesis
+                  writeline(store_file, hex_file_line);
+                  line_length := 0;
+               end if;
+            end if; --uart_sel
+         end if; --rising_edge(clk)
+      end process; --uart_proc
+   end generate; --uart_logger
+-- synthesis_on
+
+end; --architecture logic