See project homepage at <http://opencores.org/project,plasma>.
Actual trunk directory is copied.
--- /dev/null
+/*--------------------------------------------------------------------\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
--- /dev/null
+// 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
--- /dev/null
+/*--------------------------------------------------------------------
+ * 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);
+}
--- /dev/null
+/*--------------------------------------------------------------------
+ * 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
--- /dev/null
+/*--------------------------------------------------------------------
+ * 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
+ ;
+}
--- /dev/null
+/*--------------------------------------------------------------------
+ * 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
+
+
--- /dev/null
+/*--------------------------------------------------------------------
+ * 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
+
--- /dev/null
+# 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
--- /dev/null
+/*--------------------------------------------------------------------
+ * 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
+
+
--- /dev/null
+/*--------------------------------------------------------------------\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
--- /dev/null
+/*--------------------------------------------------------------------
+ * 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);}
+
+
--- /dev/null
+/*--------------------------------------------------------------------
+ * 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
+
--- /dev/null
+/*--------------------------------------------------------------------
+ * 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__
+
--- /dev/null
+/*--------------------------------------------------------------------
+ * 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;
+ }
+ }
+}
+
+
--- /dev/null
+/*--------------------------------------------------------------------\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
--- /dev/null
+/*--------------------------------------------------------------------
+ * 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__
--- /dev/null
+/*--------------------------------------------------------------------
+ * 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
+
--- /dev/null
+/*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;
+}
+
--- /dev/null
+##################################################################
+# 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
+
+
--- /dev/null
+/*--------------------------------------------------------------------
+ * 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;
+}
+
--- /dev/null
+//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;
+}
+
--- /dev/null
+/*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;
+ }
+}
+
--- /dev/null
+/*--------------------------------------------------------------------
+ * 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
--- /dev/null
+/*--------------------------------------------------------------------
+ * 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;
+ }
+ }
+}
+
--- /dev/null
+# 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
--- /dev/null
+/*-------------------------------------------------------------------
+-- 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);
+}
+
--- /dev/null
+#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);
+}
--- /dev/null
+##################################################################
+# 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
+
--- /dev/null
+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
--- /dev/null
+/*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;
+}
+
--- /dev/null
+/*--------------------------------------------------------------------
+ * 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__
+
--- /dev/null
+/* 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
--- /dev/null
+/*-------------------------------------------------------------------\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
--- /dev/null
+/***********************************************************
+| 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;
+}
--- /dev/null
+---------------------------------------------------------------------
+-- 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
+
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+setMode -bscan
+setCable -p auto
+identify
+assignFile -p 2 -file generated/main.mcs
+program -e -p 2 -v
+quit
--- /dev/null
+run
+-ifn main.prj
+-ifmt VHDL
+-ofn main.ngc
+-ofmt NGC -p XC3S500E-FG320-4
+-opt_mode Area
+-opt_level 2
--- /dev/null
+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
--- /dev/null
+setMode -bscan
+setCable -p auto
+identify
+assignFile -p 2 -file generated/main.mcs
+program -e -p 2 -v
+quit
--- /dev/null
+run
+-ifn main.prj
+-ifmt VHDL
+-ofn main.ngc
+-ofmt NGC -p XC3S500E-FG320-4
+-opt_mode Area
+-opt_level 2
--- /dev/null
+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
--- /dev/null
+# 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
--- /dev/null
+---------------------------------------------------------------------
+-- 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
--- /dev/null
+---------------------------------------------------------------------
+-- 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
+
--- /dev/null
+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
--- /dev/null
+---------------------------------------------------------------------\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
--- /dev/null
+---------------------------------------------------------------------
+-- 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
+
--- /dev/null
+---------------------------------------------------------------------
+-- 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
--- /dev/null
+#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
+
--- /dev/null
+---------------------------------------------------------------------
+-- 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
--- /dev/null
+---------------------------------------------------------------------
+-- 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
--- /dev/null
+---------------------------------------------------------------------
+-- 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
+
+
--- /dev/null
+---------------------------------------------------------------------
+-- 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
--- /dev/null
+---------------------------------------------------------------------
+-- 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
--- /dev/null
+---------------------------------------------------------------------
+-- 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
--- /dev/null
+---------------------------------------------------------------------
+-- 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
+
--- /dev/null
+---------------------------------------------------------------------
+-- 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
+
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+---------------------------------------------------------------------
+-- 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
+
--- /dev/null
+---------------------------------------------------------------------
+-- 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
--- /dev/null
+---------------------------------------------------------------------\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
--- /dev/null
+---------------------------------------------------------------------\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
--- /dev/null
+---------------------------------------------------------------------
+-- 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
+
--- /dev/null
+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
--- /dev/null
+#####################################################
+### 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 %;
--- /dev/null
+---------------------------------------------------------------------
+-- 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
--- /dev/null
+---------------------------------------------------------------------
+-- 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