mirror of
git://projects.qi-hardware.com/nn-usb-fpga.git
synced 2025-01-06 15:30:15 +02:00
Adding plasma example
This commit is contained in:
parent
f80360a678
commit
22c469585b
52
plasma/include/plasma.h
Normal file
52
plasma/include/plasma.h
Normal file
@ -0,0 +1,52 @@
|
||||
/*--------------------------------------------------------------------
|
||||
* TITLE: Plasma Hardware Defines
|
||||
* AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
|
||||
* DATE CREATED: 12/17/05
|
||||
* FILENAME: plasma.h
|
||||
* PROJECT: Plasma CPU core
|
||||
* COPYRIGHT: Software placed into the public domain by the author.
|
||||
* Software 'as is' without warranty. Author liable for nothing.
|
||||
* DESCRIPTION:
|
||||
* Plasma Hardware Defines
|
||||
*--------------------------------------------------------------------*/
|
||||
#ifndef __PLASMA_H__
|
||||
#define __PLASMA_H__
|
||||
|
||||
/*********** Hardware addesses ***********/
|
||||
#define RAM_INTERNAL_BASE 0x00000000 //8KB
|
||||
#define RAM_EXTERNAL_BASE 0x10000000 //1MB
|
||||
#define RAM_EXTERNAL_SIZE 0x00100000
|
||||
#define MISC_BASE 0x20000000
|
||||
#define UART_WRITE 0x20000000
|
||||
#define UART_READ 0x20000000
|
||||
#define IRQ_MASK 0x20000010
|
||||
#define IRQ_STATUS 0x20000020
|
||||
#define GPIO0_OUT 0x20000030
|
||||
#define GPIO0_CLEAR 0x20000040
|
||||
#define GPIOA_IN 0x20000050
|
||||
#define COUNTER_REG 0x20000060
|
||||
#define ETHERNET_REG 0x20000070
|
||||
#define FLASH_BASE 0x30000000
|
||||
|
||||
/*********** GPIO out bits ***************/
|
||||
#define ETHERNET_MDIO 0x00200000
|
||||
#define ETHERNET_MDIO_WE 0x00400000
|
||||
#define ETHERENT_MDC 0x00800000
|
||||
#define ETHERNET_ENABLE 0x01000000
|
||||
|
||||
/*********** Interrupt bits **************/
|
||||
#define IRQ_UART_READ_AVAILABLE 0x01
|
||||
#define IRQ_UART_WRITE_AVAILABLE 0x02
|
||||
#define IRQ_COUNTER18_NOT 0x04
|
||||
#define IRQ_COUNTER18 0x08
|
||||
#define IRQ_ETHERNET_RECEIVE 0x10
|
||||
#define IRQ_ETHERNET_TRANSMIT 0x20
|
||||
#define IRQ_GPIO31_NOT 0x40
|
||||
#define IRQ_GPIO31 0x80
|
||||
|
||||
/*********** Ethernet buffers ************/
|
||||
#define ETHERNET_RECEIVE 0x13ff0000
|
||||
#define ETHERNET_TRANSMIT 0x13fe0000
|
||||
|
||||
#endif //__PLASMA_H__
|
||||
|
537
plasma/kernel/dll.h
Normal file
537
plasma/kernel/dll.h
Normal file
@ -0,0 +1,537 @@
|
||||
/*--------------------------------------------------------------------
|
||||
* TITLE: Plasma Dynamic Link Library
|
||||
* AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
|
||||
* DATE CREATED: 4/4/08
|
||||
* FILENAME: dll.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:
|
||||
* Dynamic Link Library
|
||||
*--------------------------------------------------------------------*/
|
||||
#ifndef __DLL_H__
|
||||
#define __DLL_H__
|
||||
|
||||
#define INCLUDE_FILESYS
|
||||
#include "rtos.h"
|
||||
#include "tcpip.h"
|
||||
|
||||
typedef void *(*DllFunc)();
|
||||
|
||||
// Included by Plasma Kernel to create array of function pointers
|
||||
#ifdef DLL_SETUP
|
||||
|
||||
void *DllDummy(void) { printf("Dummy"); return NULL; }
|
||||
|
||||
const DllFunc DllFuncList[] = {
|
||||
(DllFunc)strcpy,
|
||||
(DllFunc)strncpy,
|
||||
(DllFunc)strcat,
|
||||
(DllFunc)strncat,
|
||||
(DllFunc)strcmp,
|
||||
(DllFunc)strncmp,
|
||||
(DllFunc)strstr,
|
||||
(DllFunc)strlen,
|
||||
(DllFunc)memcpy,
|
||||
(DllFunc)memmove,
|
||||
(DllFunc)memcmp,
|
||||
(DllFunc)memset,
|
||||
(DllFunc)abs,
|
||||
(DllFunc)rand,
|
||||
(DllFunc)srand,
|
||||
(DllFunc)strtol,
|
||||
(DllFunc)atoi,
|
||||
(DllFunc)itoa,
|
||||
(DllFunc)sprintf,
|
||||
(DllFunc)sscanf,
|
||||
#ifdef INCLUDE_DUMP
|
||||
(DllFunc)dump,
|
||||
#else //INCLUDE_DUMP
|
||||
DllDummy,
|
||||
#endif //INCLUDE_DUMP
|
||||
#ifdef INCLUDE_QSORT
|
||||
(DllFunc)qsort,
|
||||
(DllFunc)bsearch,
|
||||
#else //INCLUDE_QSORT
|
||||
DllDummy,
|
||||
DllDummy,
|
||||
#endif //INCLUDE_QSORT
|
||||
#ifdef INCLUDE_TIMELIB
|
||||
(DllFunc)mktime,
|
||||
(DllFunc)gmtime_r,
|
||||
(DllFunc)gmtimeDst,
|
||||
(DllFunc)gmtimeDstSet,
|
||||
#else //INCLUDE_TIMELIB
|
||||
DllDummy,
|
||||
DllDummy,
|
||||
DllDummy,
|
||||
DllDummy,
|
||||
#endif //INCLUDE_TIMELIB
|
||||
(DllFunc)OS_AsmInterruptEnable,
|
||||
(DllFunc)OS_HeapCreate,
|
||||
(DllFunc)OS_HeapDestroy,
|
||||
(DllFunc)OS_HeapMalloc,
|
||||
(DllFunc)OS_HeapFree,
|
||||
(DllFunc)OS_HeapAlternate,
|
||||
(DllFunc)OS_HeapRegister,
|
||||
(DllFunc)OS_ThreadCreate,
|
||||
(DllFunc)OS_ThreadExit,
|
||||
(DllFunc)OS_ThreadSelf,
|
||||
(DllFunc)OS_ThreadSleep,
|
||||
(DllFunc)OS_ThreadTime,
|
||||
(DllFunc)OS_ThreadInfoSet,
|
||||
(DllFunc)OS_ThreadInfoGet,
|
||||
(DllFunc)OS_ThreadPriorityGet,
|
||||
(DllFunc)OS_ThreadPrioritySet,
|
||||
(DllFunc)OS_ThreadProcessId,
|
||||
(DllFunc)OS_ThreadCpuLock,
|
||||
(DllFunc)OS_SemaphoreCreate,
|
||||
(DllFunc)OS_SemaphoreDelete,
|
||||
(DllFunc)OS_SemaphorePend,
|
||||
(DllFunc)OS_SemaphorePost,
|
||||
(DllFunc)OS_MutexCreate,
|
||||
(DllFunc)OS_MutexDelete,
|
||||
(DllFunc)OS_MutexPend,
|
||||
(DllFunc)OS_MutexPost,
|
||||
(DllFunc)OS_MQueueCreate,
|
||||
(DllFunc)OS_MQueueDelete,
|
||||
(DllFunc)OS_MQueueSend,
|
||||
(DllFunc)OS_MQueueGet,
|
||||
(DllFunc)OS_Job,
|
||||
(DllFunc)OS_TimerCreate,
|
||||
(DllFunc)OS_TimerDelete,
|
||||
(DllFunc)OS_TimerCallback,
|
||||
(DllFunc)OS_TimerStart,
|
||||
(DllFunc)OS_TimerStop,
|
||||
(DllFunc)OS_InterruptRegister,
|
||||
(DllFunc)OS_InterruptStatus,
|
||||
(DllFunc)OS_InterruptMaskSet,
|
||||
(DllFunc)OS_InterruptMaskClear,
|
||||
(DllFunc)UartPrintf,
|
||||
(DllFunc)UartPrintfPoll,
|
||||
(DllFunc)UartPrintfCritical,
|
||||
(DllFunc)UartScanf,
|
||||
(DllFunc)puts,
|
||||
(DllFunc)getch,
|
||||
(DllFunc)kbhit,
|
||||
(DllFunc)Led,
|
||||
(DllFunc)FP_Sqrt,
|
||||
(DllFunc)FP_Cos,
|
||||
(DllFunc)FP_Sin,
|
||||
(DllFunc)FP_Atan,
|
||||
(DllFunc)FP_Atan2,
|
||||
(DllFunc)FP_Exp,
|
||||
(DllFunc)FP_Log,
|
||||
(DllFunc)FP_Pow,
|
||||
#ifdef INCLUDE_FILESYS
|
||||
(DllFunc)OS_fopen,
|
||||
(DllFunc)OS_fclose,
|
||||
(DllFunc)OS_fread,
|
||||
(DllFunc)OS_fwrite,
|
||||
(DllFunc)OS_fseek,
|
||||
(DllFunc)OS_fmkdir,
|
||||
(DllFunc)OS_fdir,
|
||||
(DllFunc)OS_fdelete,
|
||||
#else //INCLUDE_FILESYS
|
||||
DllDummy,
|
||||
DllDummy,
|
||||
DllDummy,
|
||||
DllDummy,
|
||||
DllDummy,
|
||||
DllDummy,
|
||||
DllDummy,
|
||||
DllDummy,
|
||||
#endif //INCLUDE_FILESYS
|
||||
#ifndef WIN32
|
||||
(DllFunc)FlashRead,
|
||||
(DllFunc)FlashWrite,
|
||||
(DllFunc)FlashErase,
|
||||
#else //WIN32
|
||||
DllDummy,
|
||||
DllDummy,
|
||||
DllDummy,
|
||||
#endif //WIN32
|
||||
(DllFunc)IPOpen,
|
||||
(DllFunc)IPWriteFlush,
|
||||
(DllFunc)IPWrite,
|
||||
(DllFunc)IPRead,
|
||||
(DllFunc)IPClose,
|
||||
(DllFunc)IPPrintf,
|
||||
(DllFunc)IPResolve,
|
||||
(DllFunc)IPAddressSelf,
|
||||
(DllFunc)IPNameValue
|
||||
};
|
||||
|
||||
#endif //DLL_SETUP
|
||||
|
||||
// Included by DLL to call OS functions via array of function pointers
|
||||
#if defined(DLL_CALL) || !defined(DLL_SETUP)
|
||||
|
||||
enum {
|
||||
ENUM_strcpy,
|
||||
ENUM_strncpy,
|
||||
ENUM_strcat,
|
||||
ENUM_strncat,
|
||||
ENUM_strcmp,
|
||||
ENUM_strncmp,
|
||||
ENUM_strstr,
|
||||
ENUM_strlen,
|
||||
ENUM_memcpy,
|
||||
ENUM_memmove,
|
||||
ENUM_memcmp,
|
||||
ENUM_memset,
|
||||
ENUM_abs,
|
||||
ENUM_rand,
|
||||
ENUM_srand,
|
||||
ENUM_strtol,
|
||||
ENUM_atoi,
|
||||
ENUM_itoa,
|
||||
ENUM_sprintf,
|
||||
ENUM_sscanf,
|
||||
ENUM_dump,
|
||||
ENUM_qsort,
|
||||
ENUM_bsearch,
|
||||
ENUM_mktime,
|
||||
ENUM_gmtime_r,
|
||||
ENUM_gmtimeDst,
|
||||
ENUM_gmtimeDstSet,
|
||||
ENUM_OS_AsmInterruptEnable,
|
||||
ENUM_OS_HeapCreate,
|
||||
ENUM_OS_HeapDestroy,
|
||||
ENUM_OS_HeapMalloc,
|
||||
ENUM_OS_HeapFree,
|
||||
ENUM_OS_HeapAlternate,
|
||||
ENUM_OS_HeapRegister,
|
||||
ENUM_OS_ThreadCreate,
|
||||
ENUM_OS_ThreadExit,
|
||||
ENUM_OS_ThreadSelf,
|
||||
ENUM_OS_ThreadSleep,
|
||||
ENUM_OS_ThreadTime,
|
||||
ENUM_OS_ThreadInfoSet,
|
||||
ENUM_OS_ThreadInfoGet,
|
||||
ENUM_OS_ThreadPriorityGet,
|
||||
ENUM_OS_ThreadPrioritySet,
|
||||
ENUM_OS_ThreadProcessId,
|
||||
ENUM_OS_ThreadCpuLock,
|
||||
ENUM_OS_SemaphoreCreate,
|
||||
ENUM_OS_SemaphoreDelete,
|
||||
ENUM_OS_SemaphorePend,
|
||||
ENUM_OS_SemaphorePost,
|
||||
ENUM_OS_MutexCreate,
|
||||
ENUM_OS_MutexDelete,
|
||||
ENUM_OS_MutexPend,
|
||||
ENUM_OS_MutexPost,
|
||||
ENUM_OS_MQueueCreate,
|
||||
ENUM_OS_MQueueDelete,
|
||||
ENUM_OS_MQueueSend,
|
||||
ENUM_OS_MQueueGet,
|
||||
ENUM_OS_Job,
|
||||
ENUM_OS_TimerCreate,
|
||||
ENUM_OS_TimerDelete,
|
||||
ENUM_OS_TimerCallback,
|
||||
ENUM_OS_TimerStart,
|
||||
ENUM_OS_TimerStop,
|
||||
ENUM_OS_InterruptRegister,
|
||||
ENUM_OS_InterruptStatus,
|
||||
ENUM_OS_InterruptMaskSet,
|
||||
ENUM_OS_InterruptMaskClear,
|
||||
ENUM_UartPrintf,
|
||||
ENUM_UartPrintfPoll,
|
||||
ENUM_UartPrintfCritical,
|
||||
ENUM_UartScanf,
|
||||
ENUM_puts,
|
||||
ENUM_getch,
|
||||
ENUM_kbhit,
|
||||
ENUM_Led,
|
||||
ENUM_FP_Sqrt,
|
||||
ENUM_FP_Cos,
|
||||
ENUM_FP_Sin,
|
||||
ENUM_FP_Atan,
|
||||
ENUM_FP_Atan2,
|
||||
ENUM_FP_Exp,
|
||||
ENUM_FP_Log,
|
||||
ENUM_FP_Pow,
|
||||
ENUM_OS_fopen,
|
||||
ENUM_OS_fclose,
|
||||
ENUM_OS_fread,
|
||||
ENUM_OS_fwrite,
|
||||
ENUM_OS_fseek,
|
||||
ENUM_OS_fmkdir,
|
||||
ENUM_OS_fdir,
|
||||
ENUM_OS_fdelete,
|
||||
ENUM_FlashRead,
|
||||
ENUM_FlashWrite,
|
||||
ENUM_FlashErase,
|
||||
ENUM_IPOpen,
|
||||
ENUM_IPWriteFlush,
|
||||
ENUM_IPWrite,
|
||||
ENUM_IPRead,
|
||||
ENUM_IPClose,
|
||||
ENUM_IPPrintf,
|
||||
ENUM_IPResolve,
|
||||
ENUM_IPAddressSelf,
|
||||
ENUM_IPNameValue
|
||||
};
|
||||
|
||||
extern const DllFunc *DllF;
|
||||
|
||||
#undef strcpy
|
||||
#undef strcat
|
||||
#undef strncat
|
||||
#undef strcmp
|
||||
#undef strlen
|
||||
#undef memcpy
|
||||
#undef memcmp
|
||||
#undef memset
|
||||
#undef abs
|
||||
#undef atoi
|
||||
#undef puts
|
||||
#undef getch
|
||||
#undef kbhit
|
||||
|
||||
#define strcpy DllF[ENUM_strcpy]
|
||||
#define strncpy DllF[ENUM_strncpy]
|
||||
#define strcat DllF[ENUM_strcat]
|
||||
#define strncat DllF[ENUM_strncat]
|
||||
#define strcmp (int)DllF[ENUM_strcmp]
|
||||
#define strncmp (int)DllF[ENUM_strncmp]
|
||||
#define strstr DllF[ENUM_strstr]
|
||||
#define strlen (int)DllF[ENUM_strlen]
|
||||
#define memcpy DllF[ENUM_memcpy]
|
||||
#define memmove DllF[ENUM_memmove]
|
||||
#define memcmp (int)DllF[ENUM_memcmp]
|
||||
#define memset DllF[ENUM_memset]
|
||||
#define abs (int)DllF[ENUM_abs]
|
||||
#define rand (int)DllF[ENUM_rand]
|
||||
#define srand DllF[ENUM_srand]
|
||||
#define strtol (int)DllF[ENUM_strtol]
|
||||
#define atoi (int)DllF[ENUM_atoi]
|
||||
#define itoa DllF[ENUM_itoa]
|
||||
#define sprintf DllF[ENUM_sprintf]
|
||||
#define sscanf DllF[ENUM_sscanf]
|
||||
#define dump DllF[ENUM_dump]
|
||||
#define qsort DllF[ENUM_qsort]
|
||||
#define bsearch DllF[ENUM_bsearch]
|
||||
#define mktime DllF[ENUM_mktime]
|
||||
#define gmtime_r DllF[ENUM_gmtime_r]
|
||||
#define gmtimeDst DllF[ENUM_gmtimeDst]
|
||||
#define gmtimeDstSet DllF[ENUM_gmtimeDstSet]
|
||||
#define OS_AsmInterruptEnable (int)DllF[ENUM_OS_AsmInterruptEnable]
|
||||
#define OS_HeapCreate DllF[ENUM_OS_HeapCreate]
|
||||
#define OS_HeapDestroy DllF[ENUM_OS_HeapDestroy]
|
||||
#define OS_HeapMalloc DllF[ENUM_OS_HeapMalloc]
|
||||
#define OS_HeapFree DllF[ENUM_OS_HeapFree]
|
||||
#define OS_HeapAlternate DllF[ENUM_OS_HeapAlternate]
|
||||
#define OS_HeapRegister DllF[ENUM_OS_HeapRegister]
|
||||
#define OS_ThreadCreate DllF[ENUM_OS_ThreadCreate]
|
||||
#define OS_ThreadExit DllF[ENUM_OS_ThreadExit]
|
||||
#define OS_ThreadSelf DllF[ENUM_OS_ThreadSelf]
|
||||
#define OS_ThreadSleep DllF[ENUM_OS_ThreadSleep]
|
||||
#define OS_ThreadTime DllF[ENUM_OS_ThreadTime]
|
||||
#define OS_ThreadInfoSet DllF[ENUM_OS_ThreadInfoSet]
|
||||
#define OS_ThreadInfoGet DllF[ENUM_OS_ThreadInfoGet]
|
||||
#define OS_ThreadPriorityGet (int)DllF[ENUM_OS_ThreadPriorityGet]
|
||||
#define OS_ThreadPrioritySet DllF[ENUM_OS_ThreadPrioritySet]
|
||||
#define OS_ThreadProcessId DllF[ENUM_OS_ThreadProcessId]
|
||||
#define OS_ThreadCpuLock DllF[ENUM_OS_ThreadCpuLock]
|
||||
#define OS_SemaphoreCreate DllF[ENUM_OS_SemaphoreCreate]
|
||||
#define OS_SemaphoreDelete DllF[ENUM_OS_SemaphoreDelete]
|
||||
#define OS_SemaphorePend (int)DllF[ENUM_OS_SemaphorePend]
|
||||
#define OS_SemaphorePost DllF[ENUM_OS_SemaphorePost]
|
||||
#define OS_MutexCreate DllF[ENUM_OS_MutexCreate]
|
||||
#define OS_MutexDelete DllF[ENUM_OS_MutexDelete]
|
||||
#define OS_MutexPend (int)DllF[ENUM_OS_MutexPend]
|
||||
#define OS_MutexPost DllF[ENUM_OS_MutexPost]
|
||||
#define OS_MQueueCreate DllF[ENUM_OS_MQueueCreate]
|
||||
#define OS_MQueueDelete DllF[ENUM_OS_MQueueDelete]
|
||||
#define OS_MQueueSend DllF[ENUM_OS_MQueueSend]
|
||||
#define OS_MQueueGet (int)DllF[ENUM_OS_MQueueGet]
|
||||
#define OS_Job DllF[ENUM_OS_Job]
|
||||
#define OS_TimerCreate DllF[ENUM_OS_TimerCreate]
|
||||
#define OS_TimerDelete DllF[ENUM_OS_TimerDelete]
|
||||
#define OS_TimerCallback DllF[ENUM_OS_TimerCallback]
|
||||
#define OS_TimerStart DllF[ENUM_OS_TimerStart]
|
||||
#define OS_TimerStop DllF[ENUM_OS_TimerStop]
|
||||
#define OS_InterruptRegister DllF[ENUM_OS_InterruptRegister]
|
||||
#define OS_InterruptStatus (int)DllF[ENUM_OS_InterruptStatus]
|
||||
#define OS_InterruptMaskSet DllF[ENUM_OS_InterruptMaskSet]
|
||||
#define OS_InterruptMaskClear DllF[ENUM_OS_InterruptMaskClear]
|
||||
#define UartPrintf DllF[ENUM_UartPrintf]
|
||||
#define UartPrintfPoll DllF[ENUM_UartPrintfPoll]
|
||||
#define UartPrintfCritical DllF[ENUM_UartPrintfCritical]
|
||||
#define UartScanf DllF[ENUM_UartScanf]
|
||||
#define puts DllF[ENUM_puts]
|
||||
#define getch (int)DllF[ENUM_getch]
|
||||
#define kbhit (int)DllF[ENUM_kbhit]
|
||||
#define Led DllF[ENUM_Led]
|
||||
#define FP_Sqrt (float)(int)DllF[ENUM_FP_Sqrt]
|
||||
#define FP_Cos (float)(int)DllF[ENUM_FP_Cos]
|
||||
#define FP_Sin (float)(int)DllF[ENUM_FP_Sin]
|
||||
#define FP_Atan (float)(int)DllF[ENUM_FP_Atan]
|
||||
#define FP_Atan2 (float)(int)DllF[ENUM_FP_Atan2]
|
||||
#define FP_Exp (float)(int)DllF[ENUM_FP_Exp]
|
||||
#define FP_Log (float)(int)DllF[ENUM_FP_Log]
|
||||
#define FP_Pow (float)(int)DllF[ENUM_FP_Pow]
|
||||
#define OS_fopen DllF[ENUM_OS_fopen]
|
||||
#define OS_fclose DllF[ENUM_OS_fclose]
|
||||
#define OS_fread (int)DllF[ENUM_OS_fread]
|
||||
#define OS_fwrite DllF[ENUM_OS_fwrite]
|
||||
#define OS_fseek DllF[ENUM_OS_fseek]
|
||||
#define OS_fmkdir DllF[ENUM_OS_fmkdir]
|
||||
#define OS_fdir DllF[ENUM_OS_fdir]
|
||||
#define OS_fdelete DllF[ENUM_OS_fdelete]
|
||||
#define FlashRead DllF[ENUM_FlashRead]
|
||||
#define FlashWrite DllF[ENUM_FlashWrite]
|
||||
#define FlashErase DllF[ENUM_FlashErase]
|
||||
#define IPOpen DllF[ENUM_IPOpen]
|
||||
#define IPWriteFlush DllF[ENUM_IPWriteFlush]
|
||||
#define IPWrite (int)DllF[ENUM_IPWrite]
|
||||
#define IPRead (int)DllF[ENUM_IPRead]
|
||||
#define IPClose DllF[ENUM_IPClose]
|
||||
#define IPPrintf DllF[ENUM_IPPrintf]
|
||||
#define IPResolve DllF[ENUM_IPResolve]
|
||||
#define IPAddressSelf (int)DllF[ENUM_IPAddressSelf]
|
||||
#define IPNameValue DllF[ENUM_IPNameValue]
|
||||
|
||||
#endif //DLL_CALL
|
||||
|
||||
|
||||
#if defined(DLL_SETUP) && defined(DLL_CALL)
|
||||
const DllFunc *DllF = DllFuncList;
|
||||
#elif !defined(DLL_SETUP) && !defined(DLL_CALL) && !defined(DLL_ENTRY)
|
||||
#define DLL_ENTRY 1
|
||||
#endif //DLL_SETUP && DLL_CALL
|
||||
|
||||
|
||||
// Included by DLL to initialize the DLL
|
||||
#if defined(DLL_ENTRY) && !defined(NO_DLL_ENTRY)
|
||||
const DllFunc *DllF; //array of function pointers
|
||||
extern void *__bss_start;
|
||||
extern void *_end;
|
||||
void Start(IPSocket *socket, char *argv[]);
|
||||
|
||||
//Must be first function in file
|
||||
void *__start(DllFunc *DllFuncList)
|
||||
{
|
||||
int *bss;
|
||||
if(DllFuncList == NULL)
|
||||
return (void*)__start; //address where DLL should be loaded
|
||||
for(bss = (int*)&__bss_start; bss < (int*)&_end; ++bss)
|
||||
*bss = 0;
|
||||
DllF = DllFuncList;
|
||||
return (void*)Start;
|
||||
}
|
||||
#endif //DLL_ENTRY
|
||||
|
||||
|
||||
#ifdef DLL_STRINGS
|
||||
const char * const DllStrings[] = {
|
||||
"strcpy",
|
||||
"strncpy",
|
||||
"strcat",
|
||||
"strncat",
|
||||
"strcmp",
|
||||
"strncmp",
|
||||
"strstr",
|
||||
"strlen",
|
||||
"memcpy",
|
||||
"memmove",
|
||||
"memcmp",
|
||||
"memset",
|
||||
"abs",
|
||||
"rand",
|
||||
"srand",
|
||||
"strtol",
|
||||
"atoi",
|
||||
"itoa",
|
||||
"sprintf",
|
||||
"sscanf",
|
||||
"dump",
|
||||
"qsort",
|
||||
"bsearch",
|
||||
"mktime",
|
||||
"gmtime_r",
|
||||
"gmtimeDst",
|
||||
"gmtimeDstSet",
|
||||
"OS_AsmInterruptEnable",
|
||||
"OS_HeapCreate",
|
||||
"OS_HeapDestroy",
|
||||
"OS_HeapMalloc",
|
||||
"OS_HeapFree",
|
||||
"OS_HeapAlternate",
|
||||
"OS_HeapRegister",
|
||||
"OS_ThreadCreate",
|
||||
"OS_ThreadExit",
|
||||
"OS_ThreadSelf",
|
||||
"OS_ThreadSleep",
|
||||
"OS_ThreadTime",
|
||||
"OS_ThreadInfoSet",
|
||||
"OS_ThreadInfoGet",
|
||||
"OS_ThreadPriorityGet",
|
||||
"OS_ThreadPrioritySet",
|
||||
"OS_ThreadProcessId",
|
||||
"OS_ThreadCpuLock",
|
||||
"OS_SemaphoreCreate",
|
||||
"OS_SemaphoreDelete",
|
||||
"OS_SemaphorePend",
|
||||
"OS_SemaphorePost",
|
||||
"OS_MutexCreate",
|
||||
"OS_MutexDelete",
|
||||
"OS_MutexPend",
|
||||
"OS_MutexPost",
|
||||
"OS_MQueueCreate",
|
||||
"OS_MQueueDelete",
|
||||
"OS_MQueueSend",
|
||||
"OS_MQueueGet",
|
||||
"OS_Job",
|
||||
"OS_TimerCreate",
|
||||
"OS_TimerDelete",
|
||||
"OS_TimerCallback",
|
||||
"OS_TimerStart",
|
||||
"OS_TimerStop",
|
||||
"OS_InterruptRegister",
|
||||
"OS_InterruptStatus",
|
||||
"OS_InterruptMaskSet",
|
||||
"OS_InterruptMaskClear",
|
||||
"printf", //"UartPrintf",
|
||||
"UartPrintfPoll",
|
||||
"UartPrintfCritical",
|
||||
"scanf", //"UartScanf",
|
||||
"puts",
|
||||
"getch",
|
||||
"kbhit",
|
||||
"Led",
|
||||
"FP_Sqrt",
|
||||
"FP_Cos",
|
||||
"FP_Sin",
|
||||
"FP_Atan",
|
||||
"FP_Atan2",
|
||||
"FP_Exp",
|
||||
"FP_Log",
|
||||
"FP_Pow",
|
||||
"OS_fopen",
|
||||
"OS_fclose",
|
||||
"OS_fread",
|
||||
"OS_fwrite",
|
||||
"OS_fseek",
|
||||
"OS_fmkdir",
|
||||
"OS_fdir",
|
||||
"OS_fdelete",
|
||||
"FlashRead",
|
||||
"FlashWrite",
|
||||
"FlashErase",
|
||||
"IPOpen",
|
||||
"IPWriteFlush",
|
||||
"IPWrite",
|
||||
"IPRead",
|
||||
"IPClose",
|
||||
"IPPrintf",
|
||||
"IPResolve",
|
||||
"IPAddressSelf",
|
||||
"IPNameValue",
|
||||
NULL
|
||||
};
|
||||
#endif //DLL_STRINGS
|
||||
|
||||
#endif //__DLL_H__
|
||||
|
38
plasma/kernel/dlltest.c
Normal file
38
plasma/kernel/dlltest.c
Normal file
@ -0,0 +1,38 @@
|
||||
// dlltest.c
|
||||
// Compile this program with "make dlltest".
|
||||
// Then ftp test.bin to /flash/bin/dlltest.
|
||||
// Then from a telnet prompt type "dlltest".
|
||||
#include "dll.h"
|
||||
|
||||
|
||||
void SocketReceive(IPSocket *socket)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void MyThread(void *sock)
|
||||
{
|
||||
char buf[80];
|
||||
int i, bytes;
|
||||
IPSocket *socket = sock;
|
||||
|
||||
for(i = 0; i < 10; ++i)
|
||||
{
|
||||
bytes = IPRead(socket, buf, sizeof(buf)-1);
|
||||
buf[bytes] = 0;
|
||||
IPPrintf(socket, "%d %s\n", i, buf);
|
||||
OS_ThreadSleep(100);
|
||||
}
|
||||
socket->funcPtr = socket->userFunc; //restore socket receive function
|
||||
}
|
||||
|
||||
|
||||
// Function shouldn't block
|
||||
void Start(IPSocket *socket, char *argv[])
|
||||
{
|
||||
IPPrintf(socket, "Hello from dlltest\n");
|
||||
socket->userFunc = socket->funcPtr; //remember prev socket receive func
|
||||
socket->funcPtr = SocketReceive; //new socket receive function
|
||||
OS_ThreadCreate("MyThread", MyThread, socket, 100, 0);
|
||||
}
|
||||
|
408
plasma/kernel/ethernet.c
Normal file
408
plasma/kernel/ethernet.c
Normal file
@ -0,0 +1,408 @@
|
||||
/*--------------------------------------------------------------------
|
||||
* 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;
|
||||
unsigned int ticks, ticksLast=0;
|
||||
IPFrame *ethFrame=NULL;
|
||||
(void)arg;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
OS_InterruptMaskSet(IRQ_ETHERNET_RECEIVE);
|
||||
OS_SemaphorePend(SemEthernet, 50); //wait for interrupt
|
||||
|
||||
//Process all received packets
|
||||
for(;;)
|
||||
{
|
||||
if(ethFrame == NULL)
|
||||
ethFrame = IPFrameGet(FRAME_COUNT_RCV);
|
||||
if(ethFrame == NULL)
|
||||
{
|
||||
OS_ThreadSleep(50);
|
||||
break;
|
||||
}
|
||||
length = EthernetReceive(ethFrame->packet, PACKET_SIZE);
|
||||
if(length == 0)
|
||||
break;
|
||||
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;
|
||||
OS_InterruptMaskClear(IRQ_ETHERNET_TRANSMIT | IRQ_ETHERNET_RECEIVE);
|
||||
OS_SemaphorePost(SemEthernet);
|
||||
}
|
||||
|
||||
|
||||
/******************* 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();
|
||||
for(i = 0; i < 6; ++i)
|
||||
{
|
||||
value = MacAddress[i];
|
||||
gDestMac[i+1] = (unsigned char)((value >> 4) | (value << 4));
|
||||
}
|
||||
|
||||
//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;
|
||||
|
||||
//Start receive DMA
|
||||
MemoryWrite(GPIO0_OUT, ETHERNET_ENABLE);
|
||||
|
||||
//Setup interrupts for receiving data
|
||||
SemEthernet = OS_SemaphoreCreate("eth", 0);
|
||||
SemEthTransmit = OS_SemaphoreCreate("ethT", 1);
|
||||
OS_ThreadCreate("eth", EthernetThread, NULL, 240, 0);
|
||||
OS_InterruptRegister(IRQ_ETHERNET_RECEIVE, EthernetIsr);
|
||||
}
|
767
plasma/kernel/filesys.c
Normal file
767
plasma/kernel/filesys.c
Normal file
@ -0,0 +1,767 @@
|
||||
/*--------------------------------------------------------------------
|
||||
* TITLE: Plasma File System
|
||||
* AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
|
||||
* DATE CREATED: 4/26/07
|
||||
* FILENAME: filesys.c
|
||||
* PROJECT: Plasma CPU core
|
||||
* COPYRIGHT: Software placed into the public domain by the author.
|
||||
* Software 'as is' without warranty. Author liable for nothing.
|
||||
* DESCRIPTION:
|
||||
* Plasma File System. Supports RAM, flash, and disk file systems.
|
||||
* Possible call tree:
|
||||
* OS_fclose()
|
||||
* FileFindRecursive() //find the existing file
|
||||
* FileOpen() //open root file system
|
||||
* FileFind() //find the next level of directory
|
||||
* OS_fread() //read the directory file
|
||||
* BlockRead() //read blocks of directory
|
||||
* MediaBlockRead() //low level read
|
||||
* FileOpen() //open next directory
|
||||
* OS_fwrite() //write file entry into directory
|
||||
* BlockRead() //flush changes to directory
|
||||
*--------------------------------------------------------------------*/
|
||||
#ifdef WIN32
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#define _LIBC
|
||||
#endif
|
||||
#include "rtos.h"
|
||||
|
||||
#define FLASH_SIZE 1024*1024*16
|
||||
#define FLASH_SECTOR_SIZE 1024*128
|
||||
#define FLASH_BLOCK_SIZE 512
|
||||
#define FLASH_LN2_SIZE 9 //2^FLASH_LN2_SIZE == FLASH_BLOCK_SIZE
|
||||
#define FLASH_OFFSET FLASH_SECTOR_SIZE //offset to start of flash file system
|
||||
|
||||
#define BLOCK_SIZE 512
|
||||
#define FILE_NAME_SIZE 40
|
||||
#define FULL_NAME_SIZE 128
|
||||
#define BLOCK_MALLOC 0x0
|
||||
#define BLOCK_EOF 0xffffffff
|
||||
|
||||
typedef enum {
|
||||
FILE_MEDIA_RAM,
|
||||
FILE_MEDIA_FLASH,
|
||||
FILE_MEDIA_DISK
|
||||
} OS_MediaType_e;
|
||||
|
||||
typedef struct OS_FileEntry_s {
|
||||
char name[FILE_NAME_SIZE];
|
||||
uint32 blockIndex; //first block of file
|
||||
uint32 modifiedTime;
|
||||
uint32 length;
|
||||
uint8 isDirectory;
|
||||
uint8 attributes;
|
||||
uint8 valid;
|
||||
uint8 mediaType;
|
||||
uint16 blockSize; //Normally BLOCK_SIZE
|
||||
} OS_FileEntry_t;
|
||||
|
||||
typedef struct OS_Block_s {
|
||||
uint32 next;
|
||||
uint8 data[4];
|
||||
} OS_Block_t;
|
||||
|
||||
struct OS_FILE_s {
|
||||
OS_FileEntry_t fileEntry; //written to directory upon OS_fclose()
|
||||
uint8 fileModified;
|
||||
uint8 blockModified;
|
||||
uint32 blockIndex; //index of block
|
||||
uint32 blockOffset; //byte offset into block
|
||||
uint32 fileOffset; //byte offset into file
|
||||
char fullname[FULL_NAME_SIZE]; //includes full path
|
||||
OS_Block_t *block;
|
||||
OS_Block_t *blockLocal; //local copy for flash or disk file system
|
||||
};
|
||||
|
||||
static OS_FileEntry_t rootFileEntry;
|
||||
static OS_Mutex_t *mutexFilesys;
|
||||
|
||||
// Public prototypes
|
||||
#ifndef _FILESYS_
|
||||
typedef struct OS_FILE_s OS_FILE;
|
||||
#endif
|
||||
OS_FILE *OS_fopen(char *name, char *mode);
|
||||
void OS_fclose(OS_FILE *file);
|
||||
int OS_fread(void *buffer, int size, int count, OS_FILE *file);
|
||||
int OS_fwrite(void *buffer, int size, int count, OS_FILE *file);
|
||||
int OS_fseek(OS_FILE *file, int offset, int mode);
|
||||
int OS_fmkdir(char *name);
|
||||
int OS_fdir(OS_FILE *dir, char name[64]);
|
||||
void OS_fdelete(char *name);
|
||||
|
||||
|
||||
/***************** Media Functions Start ***********************/
|
||||
#ifdef INCLUDE_FLASH
|
||||
#define FLASH_BLOCKS FLASH_SIZE/FLASH_BLOCK_SIZE
|
||||
#define FLASH_START (FLASH_OFFSET+FLASH_BLOCKS/8*2)/FLASH_BLOCK_SIZE
|
||||
static unsigned char FlashBlockEmpty[FLASH_BLOCKS/8];
|
||||
static unsigned char FlashBlockUsed[FLASH_BLOCKS/8];
|
||||
static int FlashBlock;
|
||||
|
||||
//Free unused flash blocks
|
||||
static int MediaBlockCleanup(void)
|
||||
{
|
||||
int i, sector, block, count=0;
|
||||
unsigned char *buf;
|
||||
|
||||
printf("FlashCleanup\n");
|
||||
buf = (unsigned char*)malloc(FLASH_SECTOR_SIZE);
|
||||
if(buf == NULL)
|
||||
return 0;
|
||||
for(sector = FLASH_OFFSET / FLASH_SECTOR_SIZE; sector < FLASH_SIZE / FLASH_SECTOR_SIZE; ++sector)
|
||||
{
|
||||
FlashRead((uint16*)buf, FLASH_SECTOR_SIZE*sector, FLASH_SECTOR_SIZE);
|
||||
if(sector == FLASH_OFFSET / FLASH_SECTOR_SIZE)
|
||||
{
|
||||
for(i = 0; i < FLASH_BLOCKS/8; ++i)
|
||||
FlashBlockEmpty[i] |= ~FlashBlockUsed[i];
|
||||
memcpy(buf, FlashBlockEmpty, sizeof(FlashBlockEmpty));
|
||||
memset(FlashBlockUsed, 0xff, sizeof(FlashBlockUsed));
|
||||
memset(buf+sizeof(FlashBlockEmpty), 0xff, sizeof(FlashBlockUsed));
|
||||
}
|
||||
//Erase empty blocks
|
||||
for(block = 0; block < FLASH_SECTOR_SIZE / FLASH_BLOCK_SIZE; ++block)
|
||||
{
|
||||
i = sector * FLASH_SECTOR_SIZE / FLASH_BLOCK_SIZE + block;
|
||||
if(i < FLASH_BLOCKS/8 && (FlashBlockEmpty[i >> 3] & (1 << (i & 7))))
|
||||
{
|
||||
memset(buf + FLASH_BLOCK_SIZE*block, 0xff, FLASH_BLOCK_SIZE);
|
||||
++count;
|
||||
}
|
||||
}
|
||||
FlashErase(FLASH_SECTOR_SIZE * sector);
|
||||
FlashWrite((uint16*)buf, FLASH_SECTOR_SIZE * sector, FLASH_SECTOR_SIZE);
|
||||
}
|
||||
free(buf);
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
int MediaBlockInit(void)
|
||||
{
|
||||
FlashRead((uint16*)FlashBlockEmpty, FLASH_OFFSET, sizeof(FlashBlockEmpty));
|
||||
FlashRead((uint16*)FlashBlockUsed, FLASH_OFFSET+sizeof(FlashBlockEmpty),
|
||||
sizeof(FlashBlockUsed));
|
||||
FlashBlock = FLASH_START;
|
||||
return FlashBlockEmpty[FlashBlock >> 3] & (1 << (FlashBlock & 7));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static uint32 MediaBlockMalloc(OS_FILE *file)
|
||||
{
|
||||
int i, j;
|
||||
(void)i; (void)j;
|
||||
|
||||
if(file->fileEntry.mediaType == FILE_MEDIA_RAM)
|
||||
return (uint32)malloc(file->fileEntry.blockSize);
|
||||
#ifdef INCLUDE_FLASH
|
||||
//Find empty flash block
|
||||
for(i = FlashBlock; i < FLASH_BLOCKS; ++i)
|
||||
{
|
||||
if(FlashBlockEmpty[i >> 3] & (1 << (i & 7)))
|
||||
{
|
||||
FlashBlock = i + 1;
|
||||
FlashBlockEmpty[i >> 3] &= ~(1 << (i & 7));
|
||||
j = i >> 3;
|
||||
j &= ~1;
|
||||
FlashWrite((uint16*)(FlashBlockEmpty + j), FLASH_OFFSET + j, 2);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
i = MediaBlockCleanup();
|
||||
if(i == 0)
|
||||
return 0;
|
||||
FlashBlock = FLASH_START;
|
||||
return MediaBlockMalloc(file);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static void MediaBlockFree(OS_FILE *file, uint32 blockIndex)
|
||||
{
|
||||
if(file->fileEntry.mediaType == FILE_MEDIA_RAM)
|
||||
free((void*)blockIndex);
|
||||
#ifdef INCLUDE_FLASH
|
||||
else
|
||||
{
|
||||
int i=blockIndex, j;
|
||||
FlashBlockUsed[i >> 3] &= ~(1 << (i & 7));
|
||||
j = i >> 3;
|
||||
j &= ~1;
|
||||
FlashWrite((uint16*)(FlashBlockUsed + j), FLASH_OFFSET + sizeof(FlashBlockEmpty) + j, 2);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static void MediaBlockRead(OS_FILE *file, uint32 blockIndex)
|
||||
{
|
||||
if(file->fileEntry.mediaType == FILE_MEDIA_RAM)
|
||||
file->block = (OS_Block_t*)blockIndex;
|
||||
#ifdef INCLUDE_FLASH
|
||||
else
|
||||
{
|
||||
if(file->blockLocal == NULL)
|
||||
file->blockLocal = (OS_Block_t*)malloc(FLASH_BLOCK_SIZE);
|
||||
file->block = file->blockLocal;
|
||||
FlashRead((uint16*)file->block, blockIndex << FLASH_LN2_SIZE, FLASH_BLOCK_SIZE);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static void MediaBlockWrite(OS_FILE *file, uint32 blockIndex)
|
||||
{
|
||||
(void)file;
|
||||
(void)blockIndex;
|
||||
#ifdef INCLUDE_FLASH
|
||||
if(file->fileEntry.mediaType != FILE_MEDIA_RAM)
|
||||
FlashWrite((uint16*)file->block, blockIndex << FLASH_LN2_SIZE, FLASH_BLOCK_SIZE);
|
||||
#endif
|
||||
}
|
||||
|
||||
/***************** Media Functions End *************************/
|
||||
|
||||
// Get the next block and write the old block if it was modified
|
||||
static void BlockRead(OS_FILE *file, uint32 blockIndex)
|
||||
{
|
||||
uint32 blockIndexSave = blockIndex;
|
||||
|
||||
OS_MutexPend(mutexFilesys);
|
||||
if(blockIndex == BLOCK_MALLOC)
|
||||
{
|
||||
// Get a new block
|
||||
blockIndex = MediaBlockMalloc(file);
|
||||
if(blockIndex == 0)
|
||||
blockIndex = BLOCK_EOF;
|
||||
if(file->block)
|
||||
{
|
||||
// Set next pointer in previous block
|
||||
file->block->next = blockIndex;
|
||||
file->blockModified = 1;
|
||||
}
|
||||
}
|
||||
if(file->block && file->blockModified)
|
||||
{
|
||||
// Write block back to flash or disk
|
||||
MediaBlockWrite(file, file->blockIndex);
|
||||
file->blockModified = 0;
|
||||
}
|
||||
if(blockIndex == BLOCK_EOF)
|
||||
{
|
||||
OS_MutexPost(mutexFilesys);
|
||||
return;
|
||||
}
|
||||
file->blockIndex = blockIndex;
|
||||
file->blockOffset = 0;
|
||||
MediaBlockRead(file, blockIndex);
|
||||
if(blockIndexSave == BLOCK_MALLOC)
|
||||
{
|
||||
memset(file->block, 0xff, file->fileEntry.blockSize);
|
||||
file->blockModified = 1;
|
||||
}
|
||||
OS_MutexPost(mutexFilesys);
|
||||
}
|
||||
|
||||
|
||||
int OS_fread(void *buffer, int size, int count, OS_FILE *file)
|
||||
{
|
||||
int items, bytes;
|
||||
uint8 *buf = (uint8*)buffer;
|
||||
|
||||
for(items = 0; items < count; ++items)
|
||||
{
|
||||
for(bytes = 0; bytes < size; ++bytes)
|
||||
{
|
||||
if(file->fileOffset >= file->fileEntry.length &&
|
||||
file->fileEntry.isDirectory == 0)
|
||||
return items;
|
||||
if(file->blockOffset >= file->fileEntry.blockSize - sizeof(uint32))
|
||||
{
|
||||
if(file->block->next == BLOCK_EOF)
|
||||
return items;
|
||||
BlockRead(file, file->block->next);
|
||||
}
|
||||
*buf++ = file->block->data[file->blockOffset++];
|
||||
++file->fileOffset;
|
||||
}
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
|
||||
int OS_fwrite(void *buffer, int size, int count, OS_FILE *file)
|
||||
{
|
||||
int items, bytes;
|
||||
uint8 *buf = (uint8*)buffer;
|
||||
|
||||
OS_MutexPend(mutexFilesys);
|
||||
file->blockModified = 1;
|
||||
for(items = 0; items < count; ++items)
|
||||
{
|
||||
for(bytes = 0; bytes < size; ++bytes)
|
||||
{
|
||||
if(file->blockOffset >= file->fileEntry.blockSize - sizeof(uint32))
|
||||
{
|
||||
if(file->block->next == BLOCK_EOF)
|
||||
file->block->next = BLOCK_MALLOC;
|
||||
BlockRead(file, file->block->next);
|
||||
if(file->blockIndex == BLOCK_EOF)
|
||||
{
|
||||
count = 0;
|
||||
--items;
|
||||
break;
|
||||
}
|
||||
file->blockModified = 1;
|
||||
}
|
||||
file->block->data[file->blockOffset++] = *buf++;
|
||||
++file->fileOffset;
|
||||
}
|
||||
}
|
||||
file->blockModified = 1;
|
||||
file->fileModified = 1;
|
||||
if(file->fileOffset > file->fileEntry.length)
|
||||
file->fileEntry.length = file->fileOffset;
|
||||
OS_MutexPost(mutexFilesys);
|
||||
return items;
|
||||
}
|
||||
|
||||
|
||||
int OS_fseek(OS_FILE *file, int offset, int mode)
|
||||
{
|
||||
if(mode == 1) //SEEK_CUR
|
||||
offset += file->fileOffset;
|
||||
else if(mode == 2) //SEEK_END
|
||||
offset += file->fileEntry.length;
|
||||
file->fileOffset = offset;
|
||||
BlockRead(file, file->fileEntry.blockIndex);
|
||||
while(offset > (int)file->fileEntry.blockSize - (int)sizeof(uint32))
|
||||
{
|
||||
BlockRead(file, file->block->next);
|
||||
offset -= file->fileEntry.blockSize - (int)sizeof(uint32);
|
||||
}
|
||||
file->blockOffset = offset;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int FileOpen(OS_FILE *file, char *name, OS_FileEntry_t *fileEntry)
|
||||
{
|
||||
memset(file, 0, sizeof(OS_FILE));
|
||||
if(fileEntry == NULL)
|
||||
{
|
||||
// Open root file
|
||||
memcpy(&file->fileEntry, &rootFileEntry, sizeof(OS_FileEntry_t));
|
||||
}
|
||||
else if(fileEntry->valid == 1)
|
||||
{
|
||||
// Open existing file
|
||||
memcpy(&file->fileEntry, fileEntry, sizeof(OS_FileEntry_t));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Initialize new file
|
||||
file->fileModified = 1;
|
||||
file->blockModified = 1;
|
||||
memset(&file->fileEntry, 0, sizeof(OS_FileEntry_t));
|
||||
file->fileEntry.isDirectory = 0;
|
||||
file->fileEntry.length = 0;
|
||||
strncpy(file->fileEntry.name, name, FILE_NAME_SIZE-1);
|
||||
file->fileEntry.blockIndex = 0;
|
||||
file->fileEntry.valid = 1;
|
||||
file->fileEntry.blockSize = fileEntry->blockSize;
|
||||
file->fileEntry.mediaType = fileEntry->mediaType;
|
||||
}
|
||||
BlockRead(file, file->fileEntry.blockIndex); //Get first block
|
||||
file->fileEntry.blockIndex = file->blockIndex;
|
||||
file->fileOffset = 0;
|
||||
if(file->blockIndex == BLOCK_EOF)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int FileFind(OS_FILE *directory, char *name, OS_FileEntry_t *fileEntry)
|
||||
{
|
||||
int count, rc = -1;
|
||||
uint32 blockIndex, blockOffset;
|
||||
uint32 blockIndexEmpty=BLOCK_EOF, blockOffsetEmpty=0;
|
||||
|
||||
// Loop through files in directory
|
||||
for(;;)
|
||||
{
|
||||
blockIndex = directory->blockIndex;
|
||||
blockOffset = directory->blockOffset;
|
||||
count = OS_fread(fileEntry, sizeof(OS_FileEntry_t), 1, directory);
|
||||
if(count == 0 || fileEntry->blockIndex == BLOCK_EOF)
|
||||
break;
|
||||
if(fileEntry->valid == 1 && strcmp(fileEntry->name, name) == 0)
|
||||
{
|
||||
rc = 0; //Found the file in the directory
|
||||
break;
|
||||
}
|
||||
if(fileEntry->valid != 1 && blockIndexEmpty == BLOCK_EOF)
|
||||
{
|
||||
blockIndexEmpty = blockIndex;
|
||||
blockOffsetEmpty = blockOffset;
|
||||
}
|
||||
}
|
||||
if(rc == 0 || directory->fileEntry.mediaType == FILE_MEDIA_FLASH ||
|
||||
blockIndexEmpty == BLOCK_EOF)
|
||||
{
|
||||
// Backup to start of fileEntry or last entry in directory
|
||||
if(directory->blockIndex != blockIndex)
|
||||
BlockRead(directory, blockIndex);
|
||||
directory->blockOffset = blockOffset;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Backup to empty slot
|
||||
if(directory->blockIndex != blockIndexEmpty)
|
||||
BlockRead(directory, blockIndexEmpty);
|
||||
directory->blockOffset = blockOffsetEmpty;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
static int FileFindRecursive(OS_FILE *directory, char *name,
|
||||
OS_FileEntry_t *fileEntry, char *filename)
|
||||
{
|
||||
int rc, length;
|
||||
|
||||
rc = FileOpen(directory, NULL, NULL); //Open root directory
|
||||
for(;;)
|
||||
{
|
||||
if(name[0] == '/')
|
||||
++name;
|
||||
for(length = 0; length < FILE_NAME_SIZE; ++length)
|
||||
{
|
||||
if(name[length] == 0 || name[length] == '/')
|
||||
break;
|
||||
filename[length] = name[length];
|
||||
}
|
||||
filename[length] = 0;
|
||||
rc = FileFind(directory, filename, fileEntry); //Find file
|
||||
if(rc)
|
||||
{
|
||||
// File not found
|
||||
fileEntry->mediaType = directory->fileEntry.mediaType;
|
||||
fileEntry->blockSize = directory->fileEntry.blockSize;
|
||||
fileEntry->valid = 0;
|
||||
if(strstr(name, "/") == NULL)
|
||||
return rc;
|
||||
else
|
||||
return -2; //can't find parent directory
|
||||
}
|
||||
name += length;
|
||||
if(name[0])
|
||||
rc = FileOpen(directory, filename, fileEntry); //Open subdir
|
||||
else
|
||||
break;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
OS_FILE *OS_fopen(char *name, char *mode)
|
||||
{
|
||||
OS_FILE *file;
|
||||
OS_FileEntry_t fileEntry;
|
||||
OS_FILE dir;
|
||||
char filename[FILE_NAME_SIZE]; //Name without directories
|
||||
int rc;
|
||||
|
||||
if(rootFileEntry.blockIndex == 0)
|
||||
{
|
||||
// Mount file system
|
||||
mutexFilesys = OS_MutexCreate("filesys");
|
||||
memset(&dir, 0, sizeof(OS_FILE));
|
||||
dir.fileEntry.blockSize = BLOCK_SIZE;
|
||||
//dir.fileEntry.mediaType = FILE_MEDIA_FLASH; //Test flash
|
||||
BlockRead(&dir, BLOCK_MALLOC);
|
||||
strcpy(rootFileEntry.name, "/");
|
||||
rootFileEntry.mediaType = dir.fileEntry.mediaType;
|
||||
rootFileEntry.blockIndex = dir.blockIndex;
|
||||
rootFileEntry.blockSize = dir.fileEntry.blockSize;
|
||||
rootFileEntry.isDirectory = 1;
|
||||
BlockRead(&dir, BLOCK_EOF); //Flush data
|
||||
#ifdef INCLUDE_FLASH
|
||||
file = OS_fopen("flash", "w+");
|
||||
if(file == NULL)
|
||||
return NULL;
|
||||
file->fileEntry.isDirectory = 1;
|
||||
file->fileEntry.mediaType = FILE_MEDIA_FLASH;
|
||||
file->fileEntry.blockSize = FLASH_BLOCK_SIZE;
|
||||
file->blockLocal = file->block;
|
||||
file->block = NULL;
|
||||
rc = MediaBlockInit();
|
||||
if(rc == 1)
|
||||
BlockRead(file, BLOCK_MALLOC);
|
||||
else
|
||||
BlockRead(file, FLASH_START);
|
||||
file->fileEntry.blockIndex = file->blockIndex;
|
||||
OS_fclose(file);
|
||||
#endif
|
||||
}
|
||||
|
||||
file = (OS_FILE*)malloc(sizeof(OS_FILE));
|
||||
if(file == NULL)
|
||||
return NULL;
|
||||
OS_MutexPend(mutexFilesys);
|
||||
if(name[0] == 0 || strcmp(name, "/") == 0)
|
||||
{
|
||||
FileOpen(file, NULL, NULL);
|
||||
OS_MutexPost(mutexFilesys);
|
||||
return file;
|
||||
}
|
||||
if(mode[0] == 'w')
|
||||
{
|
||||
//Don't over write a directory
|
||||
fileEntry.isDirectory = 0;
|
||||
rc = FileFindRecursive(&dir, name, &fileEntry, filename);
|
||||
if(dir.blockLocal)
|
||||
free(dir.blockLocal);
|
||||
if(rc == 0)
|
||||
{
|
||||
if(fileEntry.isDirectory)
|
||||
{
|
||||
free(file);
|
||||
return NULL;
|
||||
}
|
||||
OS_fdelete(name);
|
||||
}
|
||||
}
|
||||
rc = FileFindRecursive(&dir, name, &fileEntry, filename);
|
||||
if(dir.blockLocal)
|
||||
free(dir.blockLocal);
|
||||
if(rc == -2 || (rc && mode[0] == 'r'))
|
||||
{
|
||||
free(file);
|
||||
OS_MutexPost(mutexFilesys);
|
||||
return NULL;
|
||||
}
|
||||
if(rc)
|
||||
fileEntry.valid = 0;
|
||||
rc = FileOpen(file, filename, &fileEntry); //Open file
|
||||
file->fullname[0] = 0;
|
||||
strncat(file->fullname, name, FULL_NAME_SIZE);
|
||||
OS_MutexPost(mutexFilesys);
|
||||
if(mode[0] == 'a')
|
||||
OS_fseek(file, 0, 2); //goto end of file
|
||||
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
|
52
plasma/kernel/flash.c
Normal file
52
plasma/kernel/flash.c
Normal file
@ -0,0 +1,52 @@
|
||||
/*--------------------------------------------------------------------
|
||||
* TITLE: Plasma Flash
|
||||
* AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
|
||||
* DATE CREATED: 12/17/05
|
||||
* FILENAME: plasma.h
|
||||
* PROJECT: Plasma CPU core
|
||||
* COPYRIGHT: Software placed into the public domain by the author.
|
||||
* Software 'as is' without warranty. Author liable for nothing.
|
||||
* DESCRIPTION:
|
||||
* Plasma flash controller
|
||||
* Only the lower 16-bits of each 32-bit word are connected --
|
||||
* this changes the address mapping to the flash.
|
||||
* ByteOffset and bytes must be a multiple of two.
|
||||
*--------------------------------------------------------------------*/
|
||||
#include "plasma.h"
|
||||
#include "rtos.h"
|
||||
|
||||
|
||||
void FlashRead(uint16 *dst, uint32 byteOffset, int bytes)
|
||||
{
|
||||
volatile uint32 *ptr=(uint32*)(FLASH_BASE + (byteOffset << 1));
|
||||
*ptr = 0xff; //read mode
|
||||
while(bytes > 0)
|
||||
{
|
||||
*dst++ = (uint16)*ptr++;
|
||||
bytes -= 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FlashWrite(uint16 *src, uint32 byteOffset, int bytes)
|
||||
{
|
||||
volatile uint32 *ptr=(uint32*)(FLASH_BASE + (byteOffset << 1));
|
||||
while(bytes > 0)
|
||||
{
|
||||
*ptr = 0x40; //write mode
|
||||
*ptr++ = *src++; //write data
|
||||
while((*ptr & 0x80) == 0) //check status
|
||||
;
|
||||
bytes -= 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FlashErase(uint32 byteOffset)
|
||||
{
|
||||
volatile uint32 *ptr=(uint32*)(FLASH_BASE + (byteOffset << 1));
|
||||
*ptr = 0x20; //erase block
|
||||
*ptr = 0xd0; //confirm
|
||||
while((*ptr & 0x80) == 0) //check status
|
||||
;
|
||||
}
|
230
plasma/kernel/http.c
Normal file
230
plasma/kernel/http.c
Normal file
@ -0,0 +1,230 @@
|
||||
/*--------------------------------------------------------------------
|
||||
* TITLE: Plasma TCP/IP HTTP Server
|
||||
* AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
|
||||
* DATE CREATED: 4/22/06
|
||||
* FILENAME: http.c
|
||||
* PROJECT: Plasma CPU core
|
||||
* COPYRIGHT: Software placed into the public domain by the author.
|
||||
* Software 'as is' without warranty. Author liable for nothing.
|
||||
* DESCRIPTION:
|
||||
* Plasma TCP/IP HTTP Server
|
||||
*--------------------------------------------------------------------*/
|
||||
#ifdef WIN32
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#define _LIBC
|
||||
#endif
|
||||
#include "rtos.h"
|
||||
#include "tcpip.h"
|
||||
#ifdef WIN32
|
||||
#define UartPrintf printf
|
||||
#define OS_MQueueCreate(A,B,C) 0
|
||||
#define OS_MQueueGet(A,B,C) 0
|
||||
#define OS_ThreadCreate(A,B,C,D,E) 0
|
||||
#endif
|
||||
|
||||
static const char pageGif[]=
|
||||
{
|
||||
"HTTP/1.0 200 OK\r\n"
|
||||
"Content-Length: %d\r\n"
|
||||
"Content-Type: binary/gif\r\n\r\n"
|
||||
};
|
||||
static const char pageGif2[]=
|
||||
{
|
||||
"HTTP/1.0 200 OK\r\n"
|
||||
"Content-Type: binary/gif\r\n\r\n"
|
||||
};
|
||||
static const char pageBinary[]=
|
||||
{
|
||||
"HTTP/1.0 200 OK\r\n"
|
||||
"Content-Length: %d\r\n"
|
||||
"Content-Type: binary/binary\r\n\r\n"
|
||||
};
|
||||
static const char pageBinary2[]=
|
||||
{
|
||||
"HTTP/1.0 200 OK\r\n"
|
||||
"Content-Type: binary/binary\r\n\r\n"
|
||||
};
|
||||
static const char pageHtml[]={
|
||||
"HTTP/1.0 200 OK\r\n"
|
||||
"Content-Length: %d\r\n"
|
||||
"Content-Type: text/html\r\n\r\n"
|
||||
};
|
||||
static const char pageHtml2[]={
|
||||
"HTTP/1.0 200 OK\r\n"
|
||||
"Content-Type: text/html\r\n\r\n"
|
||||
};
|
||||
static const char pageText[]={
|
||||
"HTTP/1.0 200 OK\r\n"
|
||||
"Content-Length: %d\r\n"
|
||||
"Content-Type: text/text\r\n\r\n"
|
||||
};
|
||||
static const char pageEmpty[]=
|
||||
{
|
||||
"HTTP/1.0 404 OK\r\n"
|
||||
"Content-Length: 0\r\n"
|
||||
"Content-Type: text/html\r\n\r\n"
|
||||
};
|
||||
|
||||
static const PageEntry_t *HtmlPages;
|
||||
static int HtmlFiles;
|
||||
|
||||
|
||||
void HttpServer(IPSocket *socket)
|
||||
{
|
||||
uint8 buf[600];
|
||||
char filename[80];
|
||||
int bytes, i, length, len, needFooter;
|
||||
char *name=NULL, *page=NULL;
|
||||
const char *header, *header2;
|
||||
|
||||
if(socket == NULL)
|
||||
return;
|
||||
if(socket->funcPtr != HttpServer && socket->funcPtr)
|
||||
{
|
||||
socket->funcPtr(socket);
|
||||
return;
|
||||
}
|
||||
bytes = IPRead(socket, buf, sizeof(buf)-1);
|
||||
if(bytes)
|
||||
{
|
||||
buf[bytes] = 0;
|
||||
if(strncmp((char*)buf, "GET /", 5) == 0)
|
||||
{
|
||||
for(i = 0; ; ++i)
|
||||
{
|
||||
length = HtmlPages[i].length;
|
||||
if(length == -1)
|
||||
break;
|
||||
name = (char*)HtmlPages[i].name;
|
||||
page = (char*)HtmlPages[i].page;
|
||||
len = (int)strlen(name);
|
||||
if(strncmp((char*)buf+4, name, len) == 0)
|
||||
break;
|
||||
}
|
||||
#if defined(WIN32) || defined(INCLUDE_FILESYS)
|
||||
if(length == HTML_LENGTH_LIST_END && HtmlFiles)
|
||||
{
|
||||
FILE *file;
|
||||
char *ptr;
|
||||
|
||||
name = (char*)buf + 5;
|
||||
ptr = strstr(name, " ");
|
||||
if(ptr)
|
||||
*ptr = 0;
|
||||
strcpy(filename, "/web/");
|
||||
strncat(filename, name, 60);
|
||||
file = fopen(filename, "rb");
|
||||
if(file == NULL)
|
||||
{
|
||||
strcpy(filename, "/flash/web/");
|
||||
strncat(filename, name, 60);
|
||||
file = fopen(filename, "rb");
|
||||
}
|
||||
if(file)
|
||||
{
|
||||
if(strstr(name, ".htm"))
|
||||
IPWrite(socket, (uint8*)pageHtml2, sizeof(pageHtml2)-1);
|
||||
else if(strstr(name, ".gif"))
|
||||
IPWrite(socket, (uint8*)pageGif2, sizeof(pageGif2)-1);
|
||||
else
|
||||
IPWrite(socket, (uint8*)pageBinary2, sizeof(pageBinary2)-1);
|
||||
for(;;)
|
||||
{
|
||||
len = fread(buf, 1, sizeof(buf), file);
|
||||
if(len == 0)
|
||||
break;
|
||||
IPWrite(socket, (uint8*)buf, len);
|
||||
}
|
||||
fclose(file);
|
||||
IPWriteFlush(socket);
|
||||
IPClose(socket);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if(length != HTML_LENGTH_LIST_END)
|
||||
{
|
||||
if(length == HTML_LENGTH_CALLBACK)
|
||||
{
|
||||
IPFuncPtr funcPtr = (IPFuncPtr)(uint32)page;
|
||||
funcPtr(socket, buf, bytes);
|
||||
return;
|
||||
}
|
||||
if(length == 0)
|
||||
length = (int)strlen(page);
|
||||
needFooter = 0;
|
||||
header2 = NULL;
|
||||
if(strstr(name, ".html"))
|
||||
header = pageHtml;
|
||||
else if(strstr(name, ".htm") || strcmp(name, "/ ") == 0)
|
||||
{
|
||||
header = pageHtml;
|
||||
header2 = HtmlPages[0].page;
|
||||
needFooter = 1;
|
||||
}
|
||||
else if(strstr(HtmlPages[i].name, ".gif"))
|
||||
header = pageGif;
|
||||
else
|
||||
header = pageBinary;
|
||||
len = 0;
|
||||
if(header2)
|
||||
len += (int)strlen(header2) + (int)strlen(HtmlPages[1].page);
|
||||
sprintf((char*)buf, header, length + len);
|
||||
IPWrite(socket, buf, (int)strlen((char*)buf));
|
||||
if(header2)
|
||||
IPWrite(socket, (uint8*)header2, (int)strlen(header2));
|
||||
IPWrite(socket, (uint8*)page, length);
|
||||
if(needFooter)
|
||||
IPWrite(socket, (uint8*)HtmlPages[1].page, (int)strlen(HtmlPages[1].page));
|
||||
}
|
||||
else
|
||||
{
|
||||
IPWrite(socket, (uint8*)pageEmpty, (int)strlen(pageEmpty));
|
||||
}
|
||||
IPClose(socket);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void HttpInit(const PageEntry_t *Pages, int UseFiles)
|
||||
{
|
||||
HtmlPages = Pages;
|
||||
HtmlFiles = UseFiles;
|
||||
IPOpen(IP_MODE_TCP, 0, 80, HttpServer);
|
||||
IPOpen(IP_MODE_TCP, 0, 8080, HttpServer);
|
||||
}
|
||||
|
||||
|
||||
#ifdef EXAMPLE_HTML
|
||||
//Example test code
|
||||
static void MyProg(IPSocket *socket, char *request, int bytes)
|
||||
{
|
||||
char *text="HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n"
|
||||
"<html><body>Hello World!</body></html>";
|
||||
(void)request; (void)bytes;
|
||||
IPWrite(socket, (uint8*)text, (int)strlen(text));
|
||||
IPClose(socket);
|
||||
}
|
||||
static const PageEntry_t pageEntry[]=
|
||||
{ //name, length, htmlText
|
||||
{"/Header", 0, "<HTML><HEAD><TITLE>Plasma CPU</TITLE></HEAD>\n<BODY>"},
|
||||
{"/Footer", 0, "</BODY></HTML>"},
|
||||
{"/ ", 0, "<h2>Home Page</h2>Welcome! <a href='/other.htm'>Other</a>"
|
||||
" <a href='/cgi/myprog'>myprog</a>"},
|
||||
{"/other.htm ", 0, "<h2>Other</h2>Other."},
|
||||
//{"/binary/plasma.gif ", 1945, PlasmaGif},
|
||||
{"/cgi/myprog", HTML_LENGTH_CALLBACK, (char*)MyProg},
|
||||
{"", HTML_LENGTH_LIST_END, NULL}
|
||||
};
|
||||
void HtmlInit(int UseFiles)
|
||||
{
|
||||
(void)UseFiles;
|
||||
HttpInit(pageEntry, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
666
plasma/kernel/libc.c
Normal file
666
plasma/kernel/libc.c
Normal file
@ -0,0 +1,666 @@
|
||||
/*--------------------------------------------------------------------
|
||||
* 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, Rand2=0xdeafbeef, Rand3=0xc5134306;
|
||||
int rand(void)
|
||||
{
|
||||
int shift;
|
||||
Rand1 += 0x13423123 + Rand2;
|
||||
Rand2 += 0x2312fdea + Rand3;
|
||||
Rand3 += 0xf2a12de1;
|
||||
shift = Rand3 & 31;
|
||||
Rand1 = (Rand1 << (32 - shift)) | (Rand1 >> shift);
|
||||
Rand3 ^= Rand1;
|
||||
shift = (Rand3 >> 8) & 31;
|
||||
Rand2 = (Rand2 << (32 - shift)) | (Rand2 >> shift);
|
||||
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
|
||||
|
192
plasma/kernel/makefile
Normal file
192
plasma/kernel/makefile
Normal file
@ -0,0 +1,192 @@
|
||||
# Makefile for Plasma RTOS and Plasma TCP/IP stack
|
||||
|
||||
ifeq ($(LANG),)
|
||||
|
||||
# Customize for Windows
|
||||
# The MIPS gcc compiler must use the cygwin1.dll that came with the compiler.
|
||||
CC_X86 = cl /O1 /nologo /I..\tools
|
||||
CP = copy
|
||||
RM = del
|
||||
DWIN32 = -DWIN32
|
||||
BIN_MIPS = ..\gccmips_elf
|
||||
TOOLS_DIR = ..\tools\\
|
||||
TOOLS2_DIR = ..\tools
|
||||
APP_DIR = ..\App\\
|
||||
LINUX_PWD =
|
||||
ALIASING =
|
||||
GCC_MIPS = $(BIN_MIPS)\gcc $(CFLAGS)
|
||||
AS_MIPS = $(BIN_MIPS)\as
|
||||
LD_MIPS = $(BIN_MIPS)\ld
|
||||
DUMP_MIPS = $(BIN_MIPS)\objdump
|
||||
CONVERT_BIN = $(TOOLS_DIR)convert_bin.exe
|
||||
OBJ = obj
|
||||
CFLAGS_X86 = /c /DWIN32
|
||||
LFLAGS_X86 =
|
||||
|
||||
else
|
||||
|
||||
# Customized for Linux
|
||||
# See the GNU GCC tab on the Opencores Plasma page
|
||||
CC_X86 = gcc -Wall -O -g -I../tools
|
||||
CP = cp
|
||||
RM = rm -rf
|
||||
DWIN32 =
|
||||
TOOLS_DIR = ../tools/
|
||||
TOOLS2_DIR = ../tools
|
||||
APP_DIR = ../App/
|
||||
LINUX_PWD = ./
|
||||
ALIASING = -fno-strict-aliasing
|
||||
GCC_MIPS = $(BIN_MIPS)mips-elf-gcc $(CFLAGS)
|
||||
AS_MIPS = $(BIN_MIPS)mips-elf-as
|
||||
LD_MIPS = $(BIN_MIPS)mips-elf-ld
|
||||
DUMP_MIPS = $(BIN_MIPS)mips-elf-objdump
|
||||
CONVERT_BIN = $(TOOLS_DIR)convert_bin.exe
|
||||
#CONVERT_BIN = $(BIN_MIPS)mips-elf-objcopy -I elf32-big -O binary test.axf test.bin
|
||||
OBJ = o
|
||||
CFLAGS_X86 = -c -DWIN32 -DLINUX
|
||||
LFLAGS_X86 = -lm
|
||||
|
||||
endif
|
||||
|
||||
# Use software multiplier (don't use mult.vhd)
|
||||
CFLAGS_SW_MULT = -mno-mul -DUSE_SW_MULT
|
||||
|
||||
# Use 16 fewer registers (make reg_bank.vhd smaller)
|
||||
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
|
||||
|
||||
CFLAGS = -O2 -Wall -c -s -I$(TOOLS2_DIR) -msoft-float -fno-builtin
|
||||
#CFLAGS += $(CFLAGS_SW_MULT)
|
||||
#CFLAGS += $(CFLAGS_FEW_REGS)
|
||||
|
||||
# Build just the Plasma RTOS for Plasma CPU
|
||||
rtos:
|
||||
$(AS_MIPS) -o boot.o $(TOOLS_DIR)boot.asm
|
||||
$(GCC_MIPS) rtos.c
|
||||
$(GCC_MIPS) libc.c
|
||||
$(GCC_MIPS) uart.c
|
||||
$(GCC_MIPS) rtos_test.c
|
||||
$(GCC_MIPS) math.c $(ALIASING)
|
||||
$(LD_MIPS) -Ttext 0x10000000 -eentry -Map test.map -s -N -o test.axf \
|
||||
boot.o rtos.o libc.o uart.o rtos_test.o math.o
|
||||
$(CONVERT_BIN)
|
||||
@sort <test.map >test2.map
|
||||
@$(DUMP_MIPS) --disassemble test.axf > test.lst
|
||||
|
||||
# Build the Plasma RTOS, Plasma TCP/IP stack, and web server for the Plasma CPU
|
||||
# Use the serial port and etermip for TCP/IP packets
|
||||
rtos_tcpip:
|
||||
$(AS_MIPS) -o boot.o $(TOOLS_DIR)boot.asm
|
||||
$(GCC_MIPS) rtos.c
|
||||
$(GCC_MIPS) libc.c
|
||||
$(GCC_MIPS) uart.c
|
||||
$(GCC_MIPS) rtos_test.c -DINCLUDE_HTML -DINCLUDE_CONSOLE
|
||||
$(GCC_MIPS) math.c $(ALIASING)
|
||||
$(GCC_MIPS) tcpip.c -DINCLUDE_FILESYS
|
||||
$(GCC_MIPS) http.c -DINCLUDE_FILESYS -DEXAMPLE_HTML
|
||||
$(GCC_MIPS) netutil.c
|
||||
$(GCC_MIPS) filesys.c
|
||||
$(LD_MIPS) -Ttext 0x10000000 -eentry -Map test.map -s -N -o test.axf \
|
||||
boot.o rtos.o libc.o uart.o rtos_test.o math.o tcpip.o \
|
||||
http.o netutil.o filesys.o
|
||||
$(CONVERT_BIN)
|
||||
@sort <test.map >test2.map
|
||||
@$(DUMP_MIPS) --disassemble test.axf > test.lst
|
||||
|
||||
# Use Ethernet for TCP/IP packets, use flash file system
|
||||
rtos_tcpip_eth:
|
||||
$(AS_MIPS) -o boot.o $(TOOLS_DIR)boot.asm
|
||||
$(GCC_MIPS) rtos.c
|
||||
$(GCC_MIPS) libc.c
|
||||
$(GCC_MIPS) uart.c -DNO_PACKETS
|
||||
$(GCC_MIPS) rtos_test.c -DINCLUDE_ETH -DINCLUDE_CONSOLE
|
||||
$(GCC_MIPS) math.c $(ALIASING)
|
||||
$(GCC_MIPS) tcpip.c -DINCLUDE_FILESYS
|
||||
$(GCC_MIPS) http.c -DINCLUDE_FILESYS -DEXAMPLE_HTML
|
||||
$(GCC_MIPS) netutil.c -DINCLUDE_FLASH -DDLL_SETUP
|
||||
$(GCC_MIPS) filesys.c -DINCLUDE_FLASH
|
||||
$(GCC_MIPS) ethernet.c
|
||||
$(GCC_MIPS) flash.c
|
||||
$(LD_MIPS) -Ttext 0x10000000 -eentry -Map test.map -s -N -o test.axf \
|
||||
boot.o rtos.o libc.o uart.o rtos_test.o math.o tcpip.o \
|
||||
http.o netutil.o filesys.o ethernet.o flash.o
|
||||
$(CONVERT_BIN)
|
||||
@sort <test.map >test2.map
|
||||
@$(DUMP_MIPS) --disassemble test.axf > test.lst
|
||||
|
||||
# Build full test application
|
||||
rtosfull:
|
||||
$(AS_MIPS) -o boot.o $(TOOLS_DIR)boot.asm
|
||||
$(GCC_MIPS) rtos.c
|
||||
$(GCC_MIPS) libc.c
|
||||
$(GCC_MIPS) uart.c -DNO_PACKETS
|
||||
$(GCC_MIPS) rtos_test.c -DINCLUDE_ETH -DINCLUDE_CONSOLE
|
||||
$(GCC_MIPS) math.c $(ALIASING)
|
||||
$(GCC_MIPS) tcpip.c -DINCLUDE_FILESYS
|
||||
$(GCC_MIPS) http.c -DINCLUDE_FILESYS
|
||||
$(GCC_MIPS) netutil.c -DINCLUDE_FLASH -DDLL_SETUP
|
||||
$(GCC_MIPS) filesys.c -DINCLUDE_FLASH
|
||||
$(GCC_MIPS) ethernet.c
|
||||
$(GCC_MIPS) flash.c
|
||||
$(GCC_MIPS) -I. $(APP_DIR)html.c -DMainThread=HtmlThread
|
||||
$(GCC_MIPS) -I. $(APP_DIR)image.c
|
||||
$(GCC_MIPS) -I. $(APP_DIR)tictac.c
|
||||
$(GCC_MIPS) -I. $(APP_DIR)tic3d.c
|
||||
$(GCC_MIPS) -I. $(APP_DIR)connect4.c
|
||||
$(LD_MIPS) -Ttext 0x10000000 -eentry -Map test.map -s -N -o test.axf \
|
||||
boot.o rtos.o libc.o uart.o rtos_test.o math.o tcpip.o \
|
||||
http.o netutil.o filesys.o ethernet.o flash.o \
|
||||
html.o image.o tictac.o tic3d.o connect4.o
|
||||
$(CONVERT_BIN)
|
||||
@sort <test.map >test2.map
|
||||
@$(DUMP_MIPS) --disassemble test.axf > test.lst
|
||||
|
||||
# Create a separate Dynamically Linked Library executable
|
||||
# ftp test.bin to /flash/web/dlltest
|
||||
# telnet to board and execute "dlltest"
|
||||
dlltest:
|
||||
$(GCC_MIPS) -G0 dlltest.c
|
||||
$(LD_MIPS) -Ttext 0x10100000 -s -N -o test.axf dlltest.o
|
||||
$(CONVERT_BIN)
|
||||
@$(DUMP_MIPS) --disassemble test.axf > test.lst
|
||||
|
||||
# Test the RTOS running on a PC
|
||||
testrtos:
|
||||
@$(CC_X86) $(CFLAGS_X86) rtos.c
|
||||
@$(CC_X86) $(CFLAGS_X86) libc.c
|
||||
@$(CC_X86) $(CFLAGS_X86) uart.c
|
||||
@$(CC_X86) $(CFLAGS_X86) rtos_test.c
|
||||
@$(CC_X86) $(CFLAGS_X86) math.c $(ALIASING)
|
||||
@$(CC_X86) $(LFLAGS_X86) -o testrtos.exe rtos.$(OBJ) libc.$(OBJ) uart.$(OBJ) rtos_test.$(OBJ) math.$(OBJ)
|
||||
$(LINUX_PWD)testrtos.exe
|
||||
|
||||
# Test the TCP/IP protocol stack running on a PC (requires Windows)
|
||||
testip:
|
||||
@$(CC_X86) $(CFLAGS_X86) tcpip.c
|
||||
@$(CC_X86) $(CFLAGS_X86) http.c /DEXAMPLE_HTML
|
||||
@$(CC_X86) $(CFLAGS_X86) netutil.c
|
||||
@$(CC_X86) $(CFLAGS_X86) filesys.c
|
||||
@$(CC_X86) $(CFLAGS_X86) libc.c /I$(TOOLS_DIR)
|
||||
@$(CC_X86) $(CFLAGS_X86) /DSIMULATE_PLASMA $(TOOLS_DIR)etermip.c
|
||||
@$(CC_X86) $(CFLAGS_X86) os_stubs.c
|
||||
@$(CC_X86) -o testip.exe etermip.obj $(TOOLS_DIR)wpcap.lib \
|
||||
tcpip.obj http.obj netutil.obj filesys.obj libc.obj os_stubs.obj
|
||||
@echo Try http://plasmb/. Try telnet plasmb. Try ftp plasmb.
|
||||
$(LINUX_PWD)testip.exe
|
||||
|
||||
clean:
|
||||
-$(RM) *.o *.obj *.axf *.map *.lst *.hex *.txt *.bin *.exe
|
||||
|
||||
# Run a Plasma CPU opcode simulator (can execute rtos target)
|
||||
run:
|
||||
@$(TOOLS_DIR)mlite.exe test.bin
|
||||
|
||||
disassemble:
|
||||
-@$(TOOLS_DIR)mlite.exe test.bin BD > test.txt
|
||||
|
||||
# Start the EtermIP terminal program to download the code to the Plasma CPU
|
||||
# and permit an Ethernet packets to be transfered.
|
||||
download:
|
||||
@echo Reset board before downloading code
|
||||
$(TOOLS_DIR)etermip.exe
|
||||
|
||||
|
692
plasma/kernel/math.c
Normal file
692
plasma/kernel/math.c
Normal file
@ -0,0 +1,692 @@
|
||||
/*--------------------------------------------------------------------
|
||||
* TITLE: Plasma Floating Point Library
|
||||
* AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
|
||||
* DATE CREATED: 3/2/06
|
||||
* FILENAME: math.c
|
||||
* PROJECT: Plasma CPU core
|
||||
* COPYRIGHT: Software placed into the public domain by the author.
|
||||
* Software 'as is' without warranty. Author liable for nothing.
|
||||
* DESCRIPTION:
|
||||
* Plasma Floating Point Library
|
||||
*--------------------------------------------------------------------
|
||||
* IEEE_fp = sign(1) | exponent(8) | fraction(23)
|
||||
* cos(x)=1-x^2/2!+x^4/4!-x^6/6!+...
|
||||
* exp(x)=1+x+x^2/2!+x^3/3!+...
|
||||
* ln(1+x)=x-x^2/2+x^3/3-x^4/4+...
|
||||
* atan(x)=x-x^3/3+x^5/5-x^7/7+...
|
||||
* pow(x,y)=exp(y*ln(x))
|
||||
* x=tan(a+b)=(tan(a)+tan(b))/(1-tan(a)*tan(b))
|
||||
* atan(x)=b+atan((x-atan(b))/(1+x*atan(b)))
|
||||
* ln(a*x)=ln(a)+ln(x); ln(x^n)=n*ln(x)
|
||||
*--------------------------------------------------------------------*/
|
||||
#include "rtos.h"
|
||||
|
||||
//#define USE_SW_MULT
|
||||
#if !defined(WIN32) && !defined(USE_SW_MULT)
|
||||
#define USE_MULT64
|
||||
#endif
|
||||
|
||||
#define PI ((float)3.1415926)
|
||||
#define PI_2 ((float)(PI/2.0))
|
||||
#define PI2 ((float)(PI*2.0))
|
||||
|
||||
#define FtoL(X) (*(unsigned long*)&(X))
|
||||
#define LtoF(X) (*(float*)&(X))
|
||||
|
||||
|
||||
float FP_Neg(float a_fp)
|
||||
{
|
||||
unsigned long a;
|
||||
a = FtoL(a_fp);
|
||||
a ^= 0x80000000;
|
||||
return LtoF(a);
|
||||
}
|
||||
|
||||
|
||||
float FP_Add(float a_fp, float b_fp)
|
||||
{
|
||||
unsigned long a, b, c;
|
||||
unsigned long as, bs, cs; //sign
|
||||
long ae, af, be, bf, ce, cf; //exponent and fraction
|
||||
a = FtoL(a_fp);
|
||||
b = FtoL(b_fp);
|
||||
as = a >> 31; //sign
|
||||
ae = (a >> 23) & 0xff; //exponent
|
||||
af = 0x00800000 | (a & 0x007fffff); //fraction
|
||||
bs = b >> 31;
|
||||
be = (b >> 23) & 0xff;
|
||||
bf = 0x00800000 | (b & 0x007fffff);
|
||||
if(ae > be)
|
||||
{
|
||||
if(ae - be < 30)
|
||||
bf >>= ae - be;
|
||||
else
|
||||
bf = 0;
|
||||
ce = ae;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(be - ae < 30)
|
||||
af >>= be - ae;
|
||||
else
|
||||
af = 0;
|
||||
ce = be;
|
||||
}
|
||||
cf = (as ? -af : af) + (bs ? -bf : bf);
|
||||
cs = cf < 0;
|
||||
cf = cf>=0 ? cf : -cf;
|
||||
if(cf == 0)
|
||||
return LtoF(cf);
|
||||
while(cf & 0xff000000)
|
||||
{
|
||||
++ce;
|
||||
cf >>= 1;
|
||||
}
|
||||
while((cf & 0xff800000) == 0)
|
||||
{
|
||||
--ce;
|
||||
cf <<= 1;
|
||||
}
|
||||
c = (cs << 31) | (ce << 23) | (cf & 0x007fffff);
|
||||
if(ce < 1)
|
||||
c = 0;
|
||||
return LtoF(c);
|
||||
}
|
||||
|
||||
|
||||
float FP_Sub(float a_fp, float b_fp)
|
||||
{
|
||||
return FP_Add(a_fp, FP_Neg(b_fp));
|
||||
}
|
||||
|
||||
|
||||
float FP_Mult(float a_fp, float b_fp)
|
||||
{
|
||||
unsigned long a, b, c;
|
||||
unsigned long as, af, bs, bf, cs, cf;
|
||||
long ae, be, ce;
|
||||
#ifndef USE_MULT64
|
||||
unsigned long a2, a1, b2, b1, med1, med2;
|
||||
#endif
|
||||
unsigned long hi, lo;
|
||||
a = FtoL(a_fp);
|
||||
b = FtoL(b_fp);
|
||||
as = a >> 31;
|
||||
ae = (a >> 23) & 0xff;
|
||||
af = 0x00800000 | (a & 0x007fffff);
|
||||
bs = b >> 31;
|
||||
be = (b >> 23) & 0xff;
|
||||
bf = 0x00800000 | (b & 0x007fffff);
|
||||
cs = as ^ bs;
|
||||
#ifndef USE_MULT64
|
||||
a1 = af & 0xffff;
|
||||
a2 = af >> 16;
|
||||
b1 = bf & 0xffff;
|
||||
b2 = bf >> 16;
|
||||
lo = a1 * b1;
|
||||
med1 = a2 * b1 + (lo >> 16);
|
||||
med2 = a1 * b2;
|
||||
hi = a2 * b2 + (med1 >> 16) + (med2 >> 16);
|
||||
med1 = (med1 & 0xffff) + (med2 & 0xffff);
|
||||
hi += (med1 >> 16);
|
||||
lo = (med1 << 16) | (lo & 0xffff);
|
||||
#else
|
||||
lo = OS_AsmMult(af, bf, &hi);
|
||||
#endif
|
||||
cf = (hi << 9) | (lo >> 23);
|
||||
ce = ae + be - 0x80 + 1;
|
||||
if(cf == 0)
|
||||
return LtoF(cf);
|
||||
while(cf & 0xff000000)
|
||||
{
|
||||
++ce;
|
||||
cf >>= 1;
|
||||
}
|
||||
c = (cs << 31) | (ce << 23) | (cf & 0x007fffff);
|
||||
if(ce < 1)
|
||||
c = 0;
|
||||
return LtoF(c);
|
||||
}
|
||||
|
||||
|
||||
float FP_Div(float a_fp, float b_fp)
|
||||
{
|
||||
unsigned long a, b, c;
|
||||
unsigned long as, af, bs, bf, cs, cf;
|
||||
unsigned long a1, b1;
|
||||
#ifndef USE_MULT64
|
||||
unsigned long a2, b2, med1, med2;
|
||||
#endif
|
||||
unsigned long hi, lo;
|
||||
long ae, be, ce, d;
|
||||
a = FtoL(a_fp);
|
||||
b = FtoL(b_fp);
|
||||
as = a >> 31;
|
||||
ae = (a >> 23) & 0xff;
|
||||
af = 0x00800000 | (a & 0x007fffff);
|
||||
bs = b >> 31;
|
||||
be = (b >> 23) & 0xff;
|
||||
bf = 0x00800000 | (b & 0x007fffff);
|
||||
cs = as ^ bs;
|
||||
ce = ae - (be - 0x80) + 6 - 8;
|
||||
a1 = af << 4; //8
|
||||
b1 = bf >> 8;
|
||||
cf = a1 / b1;
|
||||
cf <<= 12; //8
|
||||
#if 1 /*non-quick*/
|
||||
#ifndef USE_MULT64
|
||||
a1 = cf & 0xffff;
|
||||
a2 = cf >> 16;
|
||||
b1 = bf & 0xffff;
|
||||
b2 = bf >> 16;
|
||||
lo = a1 * b1;
|
||||
med1 =a2 * b1 + (lo >> 16);
|
||||
med2 = a1 * b2;
|
||||
hi = a2 * b2 + (med1 >> 16) + (med2 >> 16);
|
||||
med1 = (med1 & 0xffff) + (med2 & 0xffff);
|
||||
hi += (med1 >> 16);
|
||||
lo = (med1 << 16) | (lo & 0xffff);
|
||||
#else
|
||||
lo = OS_AsmMult(cf, bf, &hi);
|
||||
#endif
|
||||
lo = (hi << 8) | (lo >> 24);
|
||||
d = af - lo; //remainder
|
||||
assert(-0xffff < d && d < 0xffff);
|
||||
d <<= 16;
|
||||
b1 = bf >> 8;
|
||||
d = d / (long)b1;
|
||||
cf += d;
|
||||
#endif
|
||||
if(cf == 0)
|
||||
return LtoF(cf);
|
||||
while(cf & 0xff000000)
|
||||
{
|
||||
++ce;
|
||||
cf >>= 1;
|
||||
}
|
||||
if(ce < 0)
|
||||
ce = 0;
|
||||
c = (cs << 31) | (ce << 23) | (cf & 0x007fffff);
|
||||
if(ce < 1)
|
||||
c = 0;
|
||||
return LtoF(c);
|
||||
}
|
||||
|
||||
|
||||
long FP_ToLong(float a_fp)
|
||||
{
|
||||
unsigned long a;
|
||||
unsigned long as;
|
||||
long ae;
|
||||
long af, shift;
|
||||
a = FtoL(a_fp);
|
||||
as = a >> 31;
|
||||
ae = (a >> 23) & 0xff;
|
||||
af = 0x00800000 | (a & 0x007fffff);
|
||||
af <<= 7;
|
||||
shift = -(ae - 0x80 - 29);
|
||||
if(shift > 0)
|
||||
{
|
||||
if(shift < 31)
|
||||
af >>= shift;
|
||||
else
|
||||
af = 0;
|
||||
}
|
||||
af = as ? -af: af;
|
||||
return af;
|
||||
}
|
||||
|
||||
|
||||
float FP_ToFloat(long af)
|
||||
{
|
||||
unsigned long a;
|
||||
unsigned long as, ae;
|
||||
as = af>=0 ? 0: 1;
|
||||
af = af>=0 ? af: -af;
|
||||
ae = 0x80 + 22;
|
||||
if(af == 0)
|
||||
return LtoF(af);
|
||||
while(af & 0xff000000)
|
||||
{
|
||||
++ae;
|
||||
af >>= 1;
|
||||
}
|
||||
while((af & 0xff800000) == 0)
|
||||
{
|
||||
--ae;
|
||||
af <<= 1;
|
||||
}
|
||||
a = (as << 31) | (ae << 23) | (af & 0x007fffff);
|
||||
return LtoF(a);
|
||||
}
|
||||
|
||||
|
||||
//0 iff a==b; 1 iff a>b; -1 iff a<b
|
||||
int FP_Cmp(float a_fp, float b_fp)
|
||||
{
|
||||
unsigned long a, b;
|
||||
unsigned long as, ae, af, bs, be, bf;
|
||||
int gt;
|
||||
a = FtoL(a_fp);
|
||||
b = FtoL(b_fp);
|
||||
if(a == b)
|
||||
return 0;
|
||||
as = a >> 31;
|
||||
bs = b >> 31;
|
||||
if(as > bs)
|
||||
return -1;
|
||||
if(as < bs)
|
||||
return 1;
|
||||
gt = as ? -1 : 1;
|
||||
ae = (a >> 23) & 0xff;
|
||||
be = (b >> 23) & 0xff;
|
||||
if(ae > be)
|
||||
return gt;
|
||||
if(ae < be)
|
||||
return -gt;
|
||||
af = 0x00800000 | (a & 0x007fffff);
|
||||
bf = 0x00800000 | (b & 0x007fffff);
|
||||
if(af > bf)
|
||||
return gt;
|
||||
return -gt;
|
||||
}
|
||||
|
||||
|
||||
int __ltsf2(float a, float b)
|
||||
{
|
||||
return FP_Cmp(a, b);
|
||||
}
|
||||
|
||||
int __lesf2(float a, float b)
|
||||
{
|
||||
return FP_Cmp(a, b);
|
||||
}
|
||||
|
||||
int __gtsf2(float a, float b)
|
||||
{
|
||||
return FP_Cmp(a, b);
|
||||
}
|
||||
|
||||
int __gesf2(float a, float b)
|
||||
{
|
||||
return FP_Cmp(a, b);
|
||||
}
|
||||
|
||||
int __eqsf2(float a, float b)
|
||||
{
|
||||
return FtoL(a) != FtoL(b);
|
||||
}
|
||||
|
||||
int __nesf2(float a, float b)
|
||||
{
|
||||
return FtoL(a) != FtoL(b);
|
||||
}
|
||||
|
||||
|
||||
float FP_Sqrt(float a)
|
||||
{
|
||||
float x1, y1, x2, y2, x3;
|
||||
long i;
|
||||
x1 = FP_ToFloat(1);
|
||||
y1 = FP_Sub(FP_Mult(x1, x1), a); //y1=x1*x1-a;
|
||||
x2 = FP_ToFloat(100);
|
||||
y2 = FP_Sub(FP_Mult(x2, x2), a);
|
||||
for(i = 0; i < 10; ++i)
|
||||
{
|
||||
if(FtoL(y1) == FtoL(y2))
|
||||
return x2;
|
||||
//x3=x2-(x1-x2)*y2/(y1-y2);
|
||||
x3 = FP_Sub(x2, FP_Div(FP_Mult(FP_Sub(x1, x2), y2), FP_Sub(y1, y2)));
|
||||
x1 = x2;
|
||||
y1 = y2;
|
||||
x2 = x3;
|
||||
y2 = FP_Sub(FP_Mult(x2, x2), a);
|
||||
}
|
||||
return x2;
|
||||
}
|
||||
|
||||
|
||||
float FP_Cos(float rad)
|
||||
{
|
||||
int n;
|
||||
float answer, x2, top, bottom, sign;
|
||||
while(FP_Cmp(rad, PI2) > 0)
|
||||
rad = FP_Sub(rad, PI2);
|
||||
while(FP_Cmp(rad, (float)0.0) < 0)
|
||||
rad = FP_Add(rad, PI2);
|
||||
answer = 1.0;
|
||||
sign = 1.0;
|
||||
if(FP_Cmp(rad, PI) >= 0)
|
||||
{
|
||||
rad = FP_Sub(rad, PI);
|
||||
sign = FP_ToFloat(-1);
|
||||
}
|
||||
if(FP_Cmp(rad, PI_2) >= 0)
|
||||
{
|
||||
rad = FP_Sub(PI, rad);
|
||||
sign = FP_Neg(sign);
|
||||
}
|
||||
x2 = FP_Mult(rad, rad);
|
||||
top = 1.0;
|
||||
bottom = 1.0;
|
||||
for(n = 2; n < 12; n += 2)
|
||||
{
|
||||
top = FP_Mult(top, FP_Neg(x2));
|
||||
bottom = FP_Mult(bottom, FP_ToFloat((n - 1) * n));
|
||||
answer = FP_Add(answer, FP_Div(top, bottom));
|
||||
}
|
||||
return FP_Mult(answer, sign);
|
||||
}
|
||||
|
||||
|
||||
float FP_Sin(float rad)
|
||||
{
|
||||
const float pi_2=(float)(PI/2.0);
|
||||
return FP_Cos(FP_Sub(rad, pi_2));
|
||||
}
|
||||
|
||||
|
||||
float FP_Atan(float x)
|
||||
{
|
||||
const float b=(float)(PI/8.0);
|
||||
const float atan_b=(float)0.37419668; //atan(b);
|
||||
int n;
|
||||
float answer, x2, top;
|
||||
if(FP_Cmp(x, (float)0.0) >= 0)
|
||||
{
|
||||
if(FP_Cmp(x, (float)1.0) > 0)
|
||||
return FP_Sub(PI_2, FP_Atan(FP_Div((float)1.0, x)));
|
||||
}
|
||||
else
|
||||
{
|
||||
if(FP_Cmp(x, (float)-1.0) > 0)
|
||||
return FP_Sub(-PI_2, FP_Atan(FP_Div((float)1.0, x)));
|
||||
}
|
||||
if(FP_Cmp(x, (float)0.45) > 0)
|
||||
{
|
||||
//answer = (x - atan_b) / (1 + x * atan_b);
|
||||
answer = FP_Div(FP_Sub(x, atan_b), FP_Add(1.0, FP_Mult(x, atan_b)));
|
||||
//answer = b + FP_Atan(answer) - (float)0.034633; /*FIXME fudge?*/
|
||||
answer = FP_Sub(FP_Add(b, FP_Atan(answer)), (float)0.034633);
|
||||
return answer;
|
||||
}
|
||||
if(FP_Cmp(x, (float)-0.45) < 0)
|
||||
{
|
||||
x = FP_Neg(x);
|
||||
//answer = (x - atan_b) / (1 + x * atan_b);
|
||||
answer = FP_Div(FP_Sub(x, atan_b), FP_Add(1.0, FP_Mult(x, atan_b)));
|
||||
//answer = b + FP_Atan(answer) - (float)0.034633; /*FIXME*/
|
||||
answer = FP_Sub(FP_Add(b, FP_Atan(answer)), (float)0.034633);
|
||||
return FP_Neg(answer);
|
||||
}
|
||||
answer = x;
|
||||
x2 = FP_Mult(FP_Neg(x), x);
|
||||
top = x;
|
||||
for(n = 3; n < 14; n += 2)
|
||||
{
|
||||
top = FP_Mult(top, x2);
|
||||
answer = FP_Add(answer, FP_Div(top, FP_ToFloat(n)));
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
|
||||
float FP_Atan2(float y, float x)
|
||||
{
|
||||
float answer,r;
|
||||
r = y / x;
|
||||
answer = FP_Atan(r);
|
||||
if(FP_Cmp(x, (float)0.0) < 0)
|
||||
{
|
||||
if(FP_Cmp(y, (float)0.0) > 0)
|
||||
answer = FP_Add(answer, PI);
|
||||
else
|
||||
answer = FP_Sub(answer, PI);
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
|
||||
float FP_Exp(float x)
|
||||
{
|
||||
const float e2=(float)7.389056099;
|
||||
const float inv_e2=(float)0.135335283;
|
||||
float answer, top, bottom, mult;
|
||||
int n;
|
||||
|
||||
mult = 1.0;
|
||||
while(FP_Cmp(x, (float)2.0) > 0)
|
||||
{
|
||||
mult = FP_Mult(mult, e2);
|
||||
x = FP_Add(x, (float)-2.0);
|
||||
}
|
||||
while(FP_Cmp(x, (float)-2.0) < 0)
|
||||
{
|
||||
mult = FP_Mult(mult, inv_e2);
|
||||
x = FP_Add(x, (float)2.0);
|
||||
}
|
||||
answer = FP_Add((float)1.0, x);
|
||||
top = x;
|
||||
bottom = 1.0;
|
||||
for(n = 2; n < 15; ++n)
|
||||
{
|
||||
top = FP_Mult(top, x);
|
||||
bottom = FP_Mult(bottom, FP_ToFloat(n));
|
||||
answer = FP_Add(answer, FP_Div(top, bottom));
|
||||
}
|
||||
return FP_Mult(answer, mult);
|
||||
}
|
||||
|
||||
|
||||
float FP_Log(float x)
|
||||
{
|
||||
const float log_2=(float)0.69314718; /*log(2.0)*/
|
||||
int n;
|
||||
float answer, top, add;
|
||||
add = 0.0;
|
||||
while(FP_Cmp(x, 16.0) > 0)
|
||||
{
|
||||
x = FP_Mult(x, (float)0.0625);
|
||||
add = FP_Add(add, (float)(log_2 * 4));
|
||||
}
|
||||
while(FP_Cmp(x, 1.5) > 0)
|
||||
{
|
||||
x = FP_Mult(x, 0.5);
|
||||
add = FP_Add(add, log_2);
|
||||
}
|
||||
while(FP_Cmp(x, 0.5) < 0)
|
||||
{
|
||||
x = FP_Mult(x, 2.0);
|
||||
add = FP_Sub(add, log_2);
|
||||
}
|
||||
x = FP_Sub(x, 1.0);
|
||||
answer = 0.0;
|
||||
top = -1.0;
|
||||
for(n = 1; n < 14; ++n)
|
||||
{
|
||||
top = FP_Mult(top, FP_Neg(x));
|
||||
answer = FP_Add(answer, FP_Div(top, FP_ToFloat(n)));
|
||||
}
|
||||
return FP_Add(answer, add);
|
||||
}
|
||||
|
||||
|
||||
float FP_Pow(float x, float y)
|
||||
{
|
||||
return FP_Exp(y * FP_Log(x));
|
||||
}
|
||||
|
||||
|
||||
/********************************************/
|
||||
//These five functions will only be used if the flag "-mno-mul" is enabled
|
||||
#ifdef USE_SW_MULT
|
||||
unsigned long __mulsi3(unsigned long a, unsigned long b)
|
||||
{
|
||||
unsigned long answer = 0;
|
||||
while(b)
|
||||
{
|
||||
if(b & 1)
|
||||
answer += a;
|
||||
a <<= 1;
|
||||
b >>= 1;
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
|
||||
static unsigned long DivideMod(unsigned long a, unsigned long b, int doMod)
|
||||
{
|
||||
unsigned long upper=a, lower=0;
|
||||
int i;
|
||||
a = b << 31;
|
||||
for(i = 0; i < 32; ++i)
|
||||
{
|
||||
lower = lower << 1;
|
||||
if(upper >= a && a && b < 2)
|
||||
{
|
||||
upper = upper - a;
|
||||
lower |= 1;
|
||||
}
|
||||
a = ((b&2) << 30) | (a >> 1);
|
||||
b = b >> 1;
|
||||
}
|
||||
if(!doMod)
|
||||
return lower;
|
||||
return upper;
|
||||
}
|
||||
|
||||
|
||||
unsigned long __udivsi3(unsigned long a, unsigned long b)
|
||||
{
|
||||
return DivideMod(a, b, 0);
|
||||
}
|
||||
|
||||
|
||||
long __divsi3(long a, long b)
|
||||
{
|
||||
long answer, negate=0;
|
||||
if(a < 0)
|
||||
{
|
||||
a = -a;
|
||||
negate = !negate;
|
||||
}
|
||||
if(b < 0)
|
||||
{
|
||||
b = -b;
|
||||
negate = !negate;
|
||||
}
|
||||
answer = DivideMod(a, b, 0);
|
||||
if(negate)
|
||||
answer = -answer;
|
||||
return answer;
|
||||
}
|
||||
|
||||
|
||||
unsigned long __umodsi3(unsigned long a, unsigned long b)
|
||||
{
|
||||
return DivideMod(a, b, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*************** Test *****************/
|
||||
#ifdef WIN32
|
||||
#undef _LIBC
|
||||
#include <math.h>
|
||||
#undef printf
|
||||
#undef getch
|
||||
int printf(const char *, ...);
|
||||
struct {
|
||||
char *name;
|
||||
float low, high;
|
||||
double (*func1)(double);
|
||||
float (*func2)(float);
|
||||
} test_info[]={
|
||||
{"cos", -2*PI, 2*PI, cos, FP_Cos},
|
||||
{"sin", -2*PI, 2*PI, sin, FP_Sin},
|
||||
{"atan", -3.0, 2.0, atan, FP_Atan},
|
||||
{"log", (float)0.01, (float)4.0, log, FP_Log},
|
||||
{"exp", (float)-5.01, (float)30.0, exp, FP_Exp},
|
||||
{"sqrt", (float)0.01, (float)1000.0, sqrt, FP_Sqrt}
|
||||
};
|
||||
|
||||
|
||||
void TestMathFull(void)
|
||||
{
|
||||
float a, b, c, d;
|
||||
float error1, error2, error3, error4, error5;
|
||||
int test;
|
||||
|
||||
a = PI * PI;
|
||||
b = PI;
|
||||
c = FP_Div(a, b);
|
||||
printf("%10f %10f %10f %10f %10f\n",
|
||||
(double)a, (double)b, (double)(a/b), (double)c, (double)(a/b-c));
|
||||
a = a * 200;
|
||||
for(b = -(float)2.718281828*100; b < 300; b += (float)23.678)
|
||||
{
|
||||
c = FP_Div(a, b);
|
||||
d = a / b - c;
|
||||
printf("%10f %10f %10f %10f %10f\n",
|
||||
(double)a, (double)b, (double)(a/b), (double)c, (double)(a/b-c));
|
||||
}
|
||||
//getch();
|
||||
|
||||
for(test = 0; test < 6; ++test)
|
||||
{
|
||||
printf("\nTesting %s\n", test_info[test].name);
|
||||
for(a = test_info[test].low;
|
||||
a <= test_info[test].high;
|
||||
a += (test_info[test].high-test_info[test].low)/(float)20.0)
|
||||
{
|
||||
b = (float)test_info[test].func1(a);
|
||||
c = test_info[test].func2(a);
|
||||
d = b - c;
|
||||
printf("%s %10f %10f %10f %10f\n", test_info[test].name, a, b, c, d);
|
||||
}
|
||||
//getch();
|
||||
}
|
||||
|
||||
a = FP_ToFloat((long)6.0);
|
||||
b = FP_ToFloat((long)2.0);
|
||||
printf("%f %f\n", (double)a, (double)b);
|
||||
c = FP_Add(a, b);
|
||||
printf("add %f %f\n", (double)(a + b), (double)c);
|
||||
c = FP_Sub(a, b);
|
||||
printf("sub %f %f\n", (double)(a - b), (double)c);
|
||||
c = FP_Mult(a, b);
|
||||
printf("mult %f %f\n", (double)(a * b), (double)c);
|
||||
c = FP_Div(a, b);
|
||||
printf("div %f %f\n", (double)(a / b), (double)c);
|
||||
//getch();
|
||||
|
||||
for(a = (float)-13756.54; a < (float)17400.0; a += (float)64.45)
|
||||
{
|
||||
for(b = (float)-875.36; b < (float)935.8; b += (float)36.7)
|
||||
{
|
||||
error1 = (float)1.0 - (a + b) / FP_Add(a, b);
|
||||
error2 = (float)1.0 - (a * b) / FP_Mult(a, b);
|
||||
error3 = (float)1.0 - (a / b) / FP_Div(a, b);
|
||||
error4 = (float)1.0 - a / FP_ToFloat(FP_ToLong(a));
|
||||
error5 = error1 + error2 + error3 + error4;
|
||||
if(error5 < 0.00005)
|
||||
continue;
|
||||
printf("ERROR!\n");
|
||||
printf("a=%f b=%f\n", (double)a, (double)b);
|
||||
printf(" a+b=%f %f\n", (double)(a+b), (double)FP_Add(a, b));
|
||||
printf(" a*b=%f %f\n", (double)(a*b), (double)FP_Mult(a, b));
|
||||
printf(" a/b=%f %f\n", (double)(a/b), (double)FP_Div(a, b));
|
||||
printf(" a=%f %ld %f\n", (double)a, FP_ToLong(a),
|
||||
(double)FP_ToFloat((long)a));
|
||||
printf(" %f %f %f %f\n", (double)error1, (double)error2,
|
||||
(double)error3, (double)error4);
|
||||
//if(error5 > 0.001)
|
||||
// getch();
|
||||
}
|
||||
}
|
||||
printf("done.\n");
|
||||
//getch();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
1159
plasma/kernel/netutil.c
Normal file
1159
plasma/kernel/netutil.c
Normal file
File diff suppressed because it is too large
Load Diff
71
plasma/kernel/os_stubs.c
Normal file
71
plasma/kernel/os_stubs.c
Normal file
@ -0,0 +1,71 @@
|
||||
/*--------------------------------------------------------------------
|
||||
* TITLE: OS stubs
|
||||
* AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
|
||||
* DATE CREATED: 2/18/08
|
||||
* FILENAME: os_stubs.c
|
||||
* PROJECT: Plasma CPU core
|
||||
* COPYRIGHT: Software placed into the public domain by the author.
|
||||
* Software 'as is' without warranty. Author liable for nothing.
|
||||
* DESCRIPTION:
|
||||
*--------------------------------------------------------------------*/
|
||||
#include <stdlib.h>
|
||||
#include "plasma.h"
|
||||
#include "rtos.h"
|
||||
|
||||
unsigned char *flash;
|
||||
int beenInit;
|
||||
|
||||
|
||||
void FlashRead(uint16 *dst, uint32 byteOffset, int bytes)
|
||||
{
|
||||
if(beenInit == 0)
|
||||
{
|
||||
beenInit = 1;
|
||||
flash = (unsigned char*)malloc(1024*1024*16);
|
||||
memset(flash, 0xff, sizeof(flash));
|
||||
}
|
||||
memcpy(dst, flash+byteOffset, bytes);
|
||||
}
|
||||
|
||||
|
||||
void FlashWrite(uint16 *src, uint32 byteOffset, int bytes)
|
||||
{
|
||||
memcpy(flash+byteOffset, src, bytes);
|
||||
}
|
||||
|
||||
|
||||
void FlashErase(uint32 byteOffset)
|
||||
{
|
||||
memset(flash+byteOffset, 0xff, 1024*128);
|
||||
}
|
||||
|
||||
|
||||
//Stub out RTOS functions
|
||||
void UartPrintfCritical(const char *format, ...) {(void)format;}
|
||||
uint32 OS_AsmInterruptEnable(uint32 state) {(void)state; return 0;}
|
||||
void OS_Assert(void) {}
|
||||
OS_Thread_t *OS_ThreadSelf(void) {return NULL;}
|
||||
void OS_ThreadSleep(int ticks) {(void)ticks;}
|
||||
uint32 OS_ThreadTime(void) {return 0;}
|
||||
OS_Mutex_t *OS_MutexCreate(const char *name) {(void)name; return NULL; }
|
||||
void OS_MutexDelete(OS_Mutex_t *semaphore) {(void)semaphore;}
|
||||
void OS_MutexPend(OS_Mutex_t *semaphore) {(void)semaphore;}
|
||||
void OS_MutexPost(OS_Mutex_t *semaphore) {(void)semaphore;}
|
||||
|
||||
OS_MQueue_t *OS_MQueueCreate(const char *name,
|
||||
int messageCount,
|
||||
int messageBytes)
|
||||
{(void)name;(void)messageCount;(void)messageBytes; return NULL;}
|
||||
|
||||
void OS_MQueueDelete(OS_MQueue_t *mQueue) {(void)mQueue;}
|
||||
|
||||
int OS_MQueueSend(OS_MQueue_t *mQueue, void *message)
|
||||
{(void)mQueue;(void)message; return 0;}
|
||||
|
||||
int OS_MQueueGet(OS_MQueue_t *mQueue, void *message, int ticks)
|
||||
{(void)mQueue;(void)message;(void)ticks; return 0;}
|
||||
|
||||
void OS_Job(void (*funcPtr)(), void *arg0, void *arg1, void *arg2)
|
||||
{funcPtr(arg0, arg1, arg2);}
|
||||
|
||||
|
1467
plasma/kernel/rtos.c
Normal file
1467
plasma/kernel/rtos.c
Normal file
File diff suppressed because it is too large
Load Diff
377
plasma/kernel/rtos.h
Normal file
377
plasma/kernel/rtos.h
Normal file
@ -0,0 +1,377 @@
|
||||
/*--------------------------------------------------------------------
|
||||
* TITLE: Plasma Real Time Operating System
|
||||
* AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
|
||||
* DATE CREATED: 12/17/05
|
||||
* FILENAME: rtos.h
|
||||
* PROJECT: Plasma CPU core
|
||||
* COPYRIGHT: Software placed into the public domain by the author.
|
||||
* Software 'as is' without warranty. Author liable for nothing.
|
||||
* DESCRIPTION:
|
||||
* Plasma Real Time Operating System
|
||||
*--------------------------------------------------------------------*/
|
||||
#ifndef __RTOS_H__
|
||||
#define __RTOS_H__
|
||||
|
||||
// Symmetric Multi-Processing
|
||||
#define OS_CPU_COUNT 1
|
||||
|
||||
// Typedefs
|
||||
typedef unsigned int uint32;
|
||||
typedef unsigned short uint16;
|
||||
typedef unsigned char uint8;
|
||||
|
||||
// Memory Access
|
||||
#ifdef WIN32
|
||||
uint32 MemoryRead(uint32 Address);
|
||||
void MemoryWrite(uint32 Address, uint32 Value);
|
||||
#else
|
||||
#define MemoryRead(A) (*(volatile uint32*)(A))
|
||||
#define MemoryWrite(A,V) *(volatile uint32*)(A)=(V)
|
||||
#endif
|
||||
|
||||
/***************** LibC ******************/
|
||||
#if !defined(_LIBC) && !defined(_CTYPE_DEFINED)
|
||||
#define printf UartPrintf
|
||||
//#define printf UartPrintfPoll
|
||||
#define scanf UartScanf
|
||||
#ifndef WIN32
|
||||
#define malloc(S) OS_HeapMalloc(NULL, S)
|
||||
#define free(S) OS_HeapFree(S)
|
||||
#endif
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL (void*)0
|
||||
#endif
|
||||
|
||||
#define assert(A) if((A)==0){OS_Assert();UartPrintfCritical("\r\nAssert %s:%d\r\n", __FILE__, __LINE__);}
|
||||
|
||||
#define isprint(c) (' '<=(c)&&(c)<='~')
|
||||
#define isspace(c) ((c)==' '||(c)=='\t'||(c)=='\n'||(c)=='\r')
|
||||
#define isdigit(c) ('0'<=(c)&&(c)<='9')
|
||||
#define islower(c) ('a'<=(c)&&(c)<='z')
|
||||
#define isupper(c) ('A'<=(c)&&(c)<='Z')
|
||||
#define isalpha(c) (islower(c)||isupper(c))
|
||||
#define isalnum(c) (isalpha(c)||isdigit(c))
|
||||
#undef min
|
||||
#define min(a,b) ((a)<(b)?(a):(b))
|
||||
#define strcpy strcpy2 //don't use intrinsic functions
|
||||
#define strcat strcat2
|
||||
#define strncat strncat2
|
||||
#define strcmp strcmp2
|
||||
#define strlen strlen2
|
||||
#define memcpy memcpy2
|
||||
#define memcmp memcmp2
|
||||
#define memset memset2
|
||||
#define abs abs2
|
||||
#define atoi atoi2
|
||||
|
||||
char *strcpy(char *dst, const char *src);
|
||||
char *strncpy(char *dst, const char *src, int count);
|
||||
char *strcat(char *dst, const char *src);
|
||||
char *strncat(char *dst, const char *src, int count);
|
||||
int strcmp(const char *string1, const char *string2);
|
||||
int strncmp(const char *string1, const char *string2, int count);
|
||||
char *strstr(const char *string, const char *find);
|
||||
int strlen(const char *string);
|
||||
void *memcpy(void *dst, const void *src, unsigned long bytes);
|
||||
void *memmove(void *dst, const void *src, unsigned long bytes);
|
||||
int memcmp(const void *cs, const void *ct, unsigned long bytes);
|
||||
void *memset(void *dst, int c, unsigned long bytes);
|
||||
int abs(int n);
|
||||
int rand(void);
|
||||
void srand(unsigned int seed);
|
||||
long strtol(const char *s, char **end, int base);
|
||||
int atoi(const char *s);
|
||||
char *itoa(int num, char *dst, int base);
|
||||
#ifndef NO_ELLIPSIS
|
||||
int sprintf(char *s, const char *format, ...);
|
||||
int sscanf(const char *s, const char *format, ...);
|
||||
#endif
|
||||
#ifdef INCLUDE_DUMP
|
||||
void dump(const unsigned char *data, int length);
|
||||
#endif
|
||||
#ifdef INCLUDE_QSORT
|
||||
void qsort(void *base,
|
||||
long n,
|
||||
long size,
|
||||
int (*cmp)(const void *,const void *));
|
||||
void *bsearch(const void *key,
|
||||
const void *base,
|
||||
long n,
|
||||
long size,
|
||||
int (*cmp)(const void *,const void *));
|
||||
#endif
|
||||
#ifdef INCLUDE_TIMELIB
|
||||
#define difftime(time2,time1) (time2-time1)
|
||||
typedef unsigned long time_t; //start at 1/1/80
|
||||
struct tm {
|
||||
int tm_sec; //(0,59)
|
||||
int tm_min; //(0,59)
|
||||
int tm_hour; //(0,23)
|
||||
int tm_mday; //(1,31)
|
||||
int tm_mon; //(0,11)
|
||||
int tm_year; //(0,n) from 1900
|
||||
int tm_wday; //(0,6) calculated
|
||||
int tm_yday; //(0,365) calculated
|
||||
int tm_isdst; // calculated
|
||||
};
|
||||
time_t mktime(struct tm *tp);
|
||||
void gmtime_r(const time_t *tp, struct tm *out);
|
||||
void gmtimeDst(time_t dstTimeIn, time_t dstTimeOut);
|
||||
void gmtimeDstSet(time_t *tp, time_t *dstTimeIn, time_t *dstTimeOut);
|
||||
#endif
|
||||
#define _LIBC
|
||||
#endif //_LIBC
|
||||
|
||||
/***************** Assembly **************/
|
||||
typedef uint32 jmp_buf[20];
|
||||
extern uint32 OS_AsmInterruptEnable(uint32 state);
|
||||
extern void OS_AsmInterruptInit(void);
|
||||
extern int setjmp(jmp_buf env);
|
||||
extern void longjmp(jmp_buf env, int val);
|
||||
extern uint32 OS_AsmMult(uint32 a, uint32 b, unsigned long *hi);
|
||||
extern void *OS_Syscall();
|
||||
|
||||
/***************** Heap ******************/
|
||||
#define HEAP_USER (void*)0
|
||||
#define HEAP_SYSTEM (void*)1
|
||||
#define HEAP_SMALL (void*)2
|
||||
#define HEAP_UI (void*)3
|
||||
typedef struct OS_Heap_s OS_Heap_t;
|
||||
OS_Heap_t *OS_HeapCreate(const char *name, void *memory, uint32 size);
|
||||
void OS_HeapDestroy(OS_Heap_t *heap);
|
||||
void *OS_HeapMalloc(OS_Heap_t *heap, int bytes);
|
||||
void OS_HeapFree(void *block);
|
||||
void OS_HeapAlternate(OS_Heap_t *heap, OS_Heap_t *alternate);
|
||||
void OS_HeapRegister(void *index, OS_Heap_t *heap);
|
||||
|
||||
/***************** Critical Sections *****************/
|
||||
#if OS_CPU_COUNT <= 1
|
||||
// Single CPU
|
||||
#define OS_CpuIndex() 0
|
||||
#define OS_CriticalBegin() OS_AsmInterruptEnable(0)
|
||||
#define OS_CriticalEnd(S) OS_AsmInterruptEnable(S)
|
||||
#define OS_SpinLock() 0
|
||||
#define OS_SpinUnlock(S)
|
||||
#else
|
||||
// Symmetric multiprocessing
|
||||
uint32 OS_CpuIndex(void);
|
||||
#define OS_CriticalBegin() OS_SpinLock()
|
||||
#define OS_CriticalEnd(S) OS_SpinUnlock(S)
|
||||
uint32 OS_SpinLock(void);
|
||||
void OS_SpinUnlock(uint32 state);
|
||||
#endif
|
||||
|
||||
/***************** Thread *****************/
|
||||
#ifdef WIN32
|
||||
#define STACK_SIZE_MINIMUM (1024*4)
|
||||
#else
|
||||
#define STACK_SIZE_MINIMUM (1024*1)
|
||||
#endif
|
||||
#define STACK_SIZE_DEFAULT 1024*2
|
||||
#undef THREAD_PRIORITY_IDLE
|
||||
#define THREAD_PRIORITY_IDLE 0
|
||||
#define THREAD_PRIORITY_MAX 255
|
||||
|
||||
typedef void (*OS_FuncPtr_t)(void *arg);
|
||||
typedef struct OS_Thread_s OS_Thread_t;
|
||||
OS_Thread_t *OS_ThreadCreate(const char *name,
|
||||
OS_FuncPtr_t funcPtr,
|
||||
void *arg,
|
||||
uint32 priority,
|
||||
uint32 stackSize);
|
||||
void OS_ThreadExit(void);
|
||||
OS_Thread_t *OS_ThreadSelf(void);
|
||||
void OS_ThreadSleep(int ticks);
|
||||
uint32 OS_ThreadTime(void);
|
||||
void OS_ThreadInfoSet(OS_Thread_t *thread, uint32 index, void *info);
|
||||
void *OS_ThreadInfoGet(OS_Thread_t *thread, uint32 index);
|
||||
uint32 OS_ThreadPriorityGet(OS_Thread_t *thread);
|
||||
void OS_ThreadPrioritySet(OS_Thread_t *thread, uint32 priority);
|
||||
void OS_ThreadProcessId(OS_Thread_t *thread, uint32 processId, OS_Heap_t *heap);
|
||||
void OS_ThreadTick(void *arg);
|
||||
void OS_ThreadCpuLock(OS_Thread_t *thread, int cpuIndex);
|
||||
|
||||
/***************** Semaphore **************/
|
||||
#define OS_SUCCESS 0
|
||||
#define OS_ERROR -1
|
||||
#define OS_WAIT_FOREVER -1
|
||||
#define OS_NO_WAIT 0
|
||||
typedef struct OS_Semaphore_s OS_Semaphore_t;
|
||||
OS_Semaphore_t *OS_SemaphoreCreate(const char *name, uint32 count);
|
||||
void OS_SemaphoreDelete(OS_Semaphore_t *semaphore);
|
||||
int OS_SemaphorePend(OS_Semaphore_t *semaphore, int ticks); //tick ~= 10ms
|
||||
void OS_SemaphorePost(OS_Semaphore_t *semaphore);
|
||||
|
||||
/***************** Mutex ******************/
|
||||
typedef struct OS_Mutex_s OS_Mutex_t;
|
||||
OS_Mutex_t *OS_MutexCreate(const char *name);
|
||||
void OS_MutexDelete(OS_Mutex_t *semaphore);
|
||||
void OS_MutexPend(OS_Mutex_t *semaphore);
|
||||
void OS_MutexPost(OS_Mutex_t *semaphore);
|
||||
|
||||
/***************** MQueue *****************/
|
||||
enum {
|
||||
MESSAGE_TYPE_USER = 0,
|
||||
MESSAGE_TYPE_TIMER = 5
|
||||
};
|
||||
typedef struct OS_MQueue_s OS_MQueue_t;
|
||||
OS_MQueue_t *OS_MQueueCreate(const char *name,
|
||||
int messageCount,
|
||||
int messageBytes);
|
||||
void OS_MQueueDelete(OS_MQueue_t *mQueue);
|
||||
int OS_MQueueSend(OS_MQueue_t *mQueue, void *message);
|
||||
int OS_MQueueGet(OS_MQueue_t *mQueue, void *message, int ticks);
|
||||
|
||||
/***************** Job ********************/
|
||||
void OS_Job(void (*funcPtr)(), void *arg0, void *arg1, void *arg2);
|
||||
|
||||
/***************** Timer ******************/
|
||||
typedef struct OS_Timer_s OS_Timer_t;
|
||||
typedef void (*OS_TimerFuncPtr_t)(OS_Timer_t *timer, uint32 info);
|
||||
OS_Timer_t *OS_TimerCreate(const char *name, OS_MQueue_t *mQueue, uint32 info);
|
||||
void OS_TimerDelete(OS_Timer_t *timer);
|
||||
void OS_TimerCallback(OS_Timer_t *timer, OS_TimerFuncPtr_t callback);
|
||||
void OS_TimerStart(OS_Timer_t *timer, uint32 ticks, uint32 ticksRestart);
|
||||
void OS_TimerStop(OS_Timer_t *timer);
|
||||
|
||||
/***************** ISR ********************/
|
||||
#define STACK_EPC 88/4
|
||||
void OS_InterruptServiceRoutine(uint32 status, uint32 *stack);
|
||||
void OS_InterruptRegister(uint32 mask, OS_FuncPtr_t funcPtr);
|
||||
uint32 OS_InterruptStatus(void);
|
||||
uint32 OS_InterruptMaskSet(uint32 mask);
|
||||
uint32 OS_InterruptMaskClear(uint32 mask);
|
||||
|
||||
/***************** Init ******************/
|
||||
void OS_Init(uint32 *heapStorage, uint32 bytes);
|
||||
void OS_Start(void);
|
||||
void OS_Assert(void);
|
||||
void OS_DebuggerInit(void);
|
||||
void MainThread(void *Arg);
|
||||
|
||||
/***************** MMU ******************/
|
||||
typedef struct {
|
||||
const char *name;
|
||||
OS_FuncPtr_t funcPtr;
|
||||
void *arg;
|
||||
uint32 priority;
|
||||
uint32 stackSize;
|
||||
uint32 heapSize;
|
||||
uint32 processId;
|
||||
OS_Semaphore_t *semaphoreDone;
|
||||
uint8 *memory; //private
|
||||
OS_Heap_t *heap; //private
|
||||
OS_Thread_t *thread; //private
|
||||
} OS_Process_t;
|
||||
void OS_MMUInit(void);
|
||||
void OS_MMUMemoryRegister(uint32 processId,
|
||||
uint32 virtualAddress,
|
||||
uint32 physicalAddress,
|
||||
uint32 size,
|
||||
uint32 writable);
|
||||
OS_Process_t *OS_MMUProcessCreate(OS_Process_t *process);
|
||||
void OS_MMUProcessDelete(OS_Process_t *process);
|
||||
void OS_MMUUartPrintf();
|
||||
void OS_MMUUartScanf();
|
||||
void OS_MMUUartPrintfCritical();
|
||||
|
||||
/***************** UART ******************/
|
||||
typedef uint8* (*PacketGetFunc_t)(void);
|
||||
void UartInit(void);
|
||||
void UartWrite(int ch);
|
||||
uint8 UartRead(void);
|
||||
void UartWriteData(uint8 *data, int length);
|
||||
void UartReadData(uint8 *data, int length);
|
||||
#ifndef NO_ELLIPSIS2
|
||||
void UartPrintf(const char *format, ...);
|
||||
void UartPrintfPoll(const char *format, ...);
|
||||
void UartPrintfCritical(const char *format, ...);
|
||||
void UartPrintfNull(const char *format, ...);
|
||||
void UartScanf(const char *format, ...);
|
||||
#endif
|
||||
void UartPacketConfig(PacketGetFunc_t packetGetFunc,
|
||||
int packetSize,
|
||||
OS_MQueue_t *mQueue);
|
||||
void UartPacketSend(uint8 *data, int bytes);
|
||||
#ifdef WIN32
|
||||
#define puts puts2
|
||||
#define getch getch2
|
||||
#define kbhit kbhit2
|
||||
#endif
|
||||
int puts(const char *string);
|
||||
int getch(void);
|
||||
int kbhit(void);
|
||||
void LogWrite(int a);
|
||||
void LogDump(void);
|
||||
void Led(int mask, int value);
|
||||
|
||||
/***************** Keyboard **************/
|
||||
#define KEYBOARD_RAW 0x100
|
||||
#define KEYBOARD_E0 0x200
|
||||
#define KEYBOARD_RELEASE 0x400
|
||||
void KeyboardInit(void);
|
||||
int KeyboardGetch(void);
|
||||
|
||||
/***************** Math ******************/
|
||||
//IEEE single precision floating point math
|
||||
#ifndef WIN32
|
||||
#define FP_Neg __negsf2
|
||||
#define FP_Add __addsf3
|
||||
#define FP_Sub __subsf3
|
||||
#define FP_Mult __mulsf3
|
||||
#define FP_Div __divsf3
|
||||
#define FP_ToLong __fixsfsi
|
||||
#define FP_ToFloat __floatsisf
|
||||
#define sqrt FP_Sqrt
|
||||
#define cos FP_Cos
|
||||
#define sin FP_Sin
|
||||
#define atan FP_Atan
|
||||
#define log FP_Log
|
||||
#define exp FP_Exp
|
||||
#endif
|
||||
float FP_Neg(float a_fp);
|
||||
float FP_Add(float a_fp, float b_fp);
|
||||
float FP_Sub(float a_fp, float b_fp);
|
||||
float FP_Mult(float a_fp, float b_fp);
|
||||
float FP_Div(float a_fp, float b_fp);
|
||||
long FP_ToLong(float a_fp);
|
||||
float FP_ToFloat(long af);
|
||||
int FP_Cmp(float a_fp, float b_fp);
|
||||
float FP_Sqrt(float a);
|
||||
float FP_Cos(float rad);
|
||||
float FP_Sin(float rad);
|
||||
float FP_Atan(float x);
|
||||
float FP_Atan2(float y, float x);
|
||||
float FP_Exp(float x);
|
||||
float FP_Log(float x);
|
||||
float FP_Pow(float x, float y);
|
||||
|
||||
/***************** Filesys ******************/
|
||||
#ifdef INCLUDE_FILESYS
|
||||
#define FILE OS_FILE
|
||||
#define fopen OS_fopen
|
||||
#define fclose OS_fclose
|
||||
#define fread OS_fread
|
||||
#define fwrite OS_fwrite
|
||||
#define fseek OS_fseek
|
||||
#endif
|
||||
#define _FILESYS_
|
||||
typedef struct OS_FILE_s OS_FILE;
|
||||
OS_FILE *OS_fopen(char *name, char *mode);
|
||||
void OS_fclose(OS_FILE *file);
|
||||
int OS_fread(void *buffer, int size, int count, OS_FILE *file);
|
||||
int OS_fwrite(void *buffer, int size, int count, OS_FILE *file);
|
||||
int OS_fseek(OS_FILE *file, int offset, int mode);
|
||||
int OS_fmkdir(char *name);
|
||||
int OS_fdir(OS_FILE *dir, char name[64]);
|
||||
void OS_fdelete(char *name);
|
||||
int OS_flength(char *entry);
|
||||
|
||||
/***************** Flash ******************/
|
||||
void FlashRead(uint16 *dst, uint32 byteOffset, int bytes);
|
||||
void FlashWrite(uint16 *src, uint32 byteOffset, int bytes);
|
||||
void FlashErase(uint32 byteOffset);
|
||||
|
||||
#endif //__RTOS_H__
|
||||
|
522
plasma/kernel/rtos_test.c
Normal file
522
plasma/kernel/rtos_test.c
Normal file
@ -0,0 +1,522 @@
|
||||
/*--------------------------------------------------------------------
|
||||
* TITLE: Test Plasma Real Time Operating System
|
||||
* AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
|
||||
* DATE CREATED: 1/1/06
|
||||
* FILENAME: rtos_test.c
|
||||
* PROJECT: Plasma CPU core
|
||||
* COPYRIGHT: Software placed into the public domain by the author.
|
||||
* Software 'as is' without warranty. Author liable for nothing.
|
||||
* DESCRIPTION:
|
||||
* Test Plasma Real Time Operating System
|
||||
*--------------------------------------------------------------------*/
|
||||
#include "plasma.h"
|
||||
#include "rtos.h"
|
||||
#include "tcpip.h"
|
||||
|
||||
/* Including mmu.h will cause all OS calls to use SYSCALL */
|
||||
//#include "mmu.h"
|
||||
|
||||
//#define DLL_SETUP
|
||||
//#define DLL_CALL
|
||||
//#include "dll.h"
|
||||
|
||||
#define SEMAPHORE_COUNT 50
|
||||
#define TIMER_COUNT 10
|
||||
|
||||
extern void TestMathFull(void);
|
||||
|
||||
typedef struct {
|
||||
OS_Thread_t *MyThread[TIMER_COUNT];
|
||||
OS_Semaphore_t *MySemaphore[SEMAPHORE_COUNT];
|
||||
OS_Mutex_t *MyMutex;
|
||||
OS_Timer_t *MyTimer[TIMER_COUNT];
|
||||
OS_MQueue_t *MyQueue[TIMER_COUNT];
|
||||
int TimerDone;
|
||||
} TestInfo_t;
|
||||
|
||||
int Global;
|
||||
|
||||
//******************************************************************
|
||||
static void TestCLib(void)
|
||||
{
|
||||
char s1[80], s2[80], *ptr;
|
||||
int rc, v1, v2, v3;
|
||||
|
||||
printf("TestCLib\n");
|
||||
strcpy(s1, "Hello ");
|
||||
memset(s2, 0, sizeof(s2));
|
||||
strncpy(s2, "World wide", 5);
|
||||
strcat(s1, s2);
|
||||
strncat(s1, "!\nthing", 14);
|
||||
printf("%s", s1);
|
||||
rc = strcmp(s1, "Hello World!\n");
|
||||
assert(rc == 0);
|
||||
rc = strcmp(s1, "Hello WOrld!\n");
|
||||
assert(rc > 0);
|
||||
rc = strcmp(s1, "Hello world!\n");
|
||||
assert(rc < 0);
|
||||
rc = strncmp(s1, "Hellx", 4);
|
||||
assert(rc == 0);
|
||||
ptr = strstr(s1, "orl");
|
||||
assert(ptr[0] = 'o');
|
||||
rc = strlen(s1);
|
||||
assert(rc == 13);
|
||||
memcpy(s2, s1, rc+1);
|
||||
rc = memcmp(s1, s2, 8);
|
||||
assert(rc == 0);
|
||||
s2[5] = 'z';
|
||||
rc = memcmp(s1, s2, 8);
|
||||
assert(rc != 0);
|
||||
memset(s2, 0, 5);
|
||||
memset(s2, 'a', 3);
|
||||
rc = abs(-5);
|
||||
itoa(1234, s1, 10);
|
||||
itoa(0, s1, 10);
|
||||
itoa(-1234, s1, 10);
|
||||
itoa(0xabcd, s1, 16);
|
||||
itoa(0x12ab, s1, 16);
|
||||
sprintf(s1, "test c%c d%d 0x%x s%s End\n", 'C', 1234, 0xabcd, "String");
|
||||
printf("%s", s1);
|
||||
sprintf(s1, "test c%c d%6d 0x%6x s%8s End\n", 'C', 1234, 0xabcd, "String");
|
||||
printf("%s", s1);
|
||||
sscanf("1234 -1234 0xabcd text h", "%d %d %x %s", &v1, &v2, &v3, s1);
|
||||
assert(v1 == 1234 && v2 == -1234 && v3 == 0xabcd);
|
||||
assert(strcmp(s1, "text") == 0);
|
||||
//UartScanf("%d %d", &v1, &v2);
|
||||
//printf("v1 = %d v2 = %d\n", v1, v2);
|
||||
printf("Done.\n");
|
||||
}
|
||||
|
||||
//******************************************************************
|
||||
static void TestHeap(void)
|
||||
{
|
||||
uint8 *ptrs[256], size[256], *ptr;
|
||||
int i, j, k, value;
|
||||
|
||||
printf("TestHeap\n");
|
||||
memset(ptrs, 0, sizeof(ptrs));
|
||||
for(i = 0; i < 1000; ++i)
|
||||
{
|
||||
j = rand() & 255;
|
||||
if(ptrs[j])
|
||||
{
|
||||
ptr = ptrs[j];
|
||||
value = size[j];
|
||||
for(k = 0; k < value; ++k)
|
||||
{
|
||||
if(ptr[k] != value)
|
||||
printf("Error\n");
|
||||
}
|
||||
OS_HeapFree(ptrs[j]);
|
||||
}
|
||||
size[j] = (uint8)(rand() & 255);
|
||||
ptrs[j] = OS_HeapMalloc(NULL, size[j]);
|
||||
if(ptrs[j] == NULL)
|
||||
printf("malloc NULL\n");
|
||||
else
|
||||
memset(ptrs[j], size[j], size[j]);
|
||||
}
|
||||
for(i = 0; i < 256; ++i)
|
||||
{
|
||||
if(ptrs[i])
|
||||
OS_HeapFree(ptrs[i]);
|
||||
}
|
||||
printf("Done.\n");
|
||||
}
|
||||
|
||||
//******************************************************************
|
||||
static void MyThreadMain(void *arg)
|
||||
{
|
||||
OS_Thread_t *thread;
|
||||
int priority;
|
||||
|
||||
thread = OS_ThreadSelf();
|
||||
priority = OS_ThreadPriorityGet(thread);
|
||||
OS_ThreadSleep(10);
|
||||
printf("Arg=%d thread=0x%x info=0x%x priority=%d\n",
|
||||
(uint32)arg, thread, OS_ThreadInfoGet(thread, 0), priority);
|
||||
OS_ThreadExit();
|
||||
}
|
||||
|
||||
static void TestThread(void)
|
||||
{
|
||||
OS_Thread_t *thread;
|
||||
int i, priority;
|
||||
|
||||
printf("TestThread\n");
|
||||
for(i = 0; i < 32; ++i)
|
||||
{
|
||||
priority = 50 + i;
|
||||
thread = OS_ThreadCreate("MyThread", MyThreadMain, (uint32*)i, priority, 0);
|
||||
OS_ThreadInfoSet(thread, 0, (void*)(0xabcd + i));
|
||||
//printf("Created thread 0x%x\n", thread);
|
||||
}
|
||||
|
||||
thread = OS_ThreadSelf();
|
||||
priority = OS_ThreadPriorityGet(thread);
|
||||
printf("Priority = %d\n", priority);
|
||||
OS_ThreadPrioritySet(thread, 200);
|
||||
printf("Priority = %d\n", OS_ThreadPriorityGet(thread));
|
||||
OS_ThreadPrioritySet(thread, priority);
|
||||
|
||||
printf("Thread time = %d\n", OS_ThreadTime());
|
||||
OS_ThreadSleep(100);
|
||||
printf("Thread time = %d\n", OS_ThreadTime());
|
||||
}
|
||||
|
||||
//******************************************************************
|
||||
static void TestSemThread(void *arg)
|
||||
{
|
||||
int i;
|
||||
TestInfo_t *info = (TestInfo_t*)arg;
|
||||
|
||||
for(i = 0; i < SEMAPHORE_COUNT/2; ++i)
|
||||
{
|
||||
printf("s");
|
||||
OS_SemaphorePend(info->MySemaphore[i], OS_WAIT_FOREVER);
|
||||
OS_SemaphorePost(info->MySemaphore[i + SEMAPHORE_COUNT/2]);
|
||||
}
|
||||
OS_ThreadExit();
|
||||
}
|
||||
|
||||
static void TestSemaphore(void)
|
||||
{
|
||||
int i, rc;
|
||||
TestInfo_t info;
|
||||
printf("TestSemaphore\n");
|
||||
for(i = 0; i < SEMAPHORE_COUNT; ++i)
|
||||
{
|
||||
info.MySemaphore[i] = OS_SemaphoreCreate("MySem", 0);
|
||||
//printf("sem[%d]=0x%x\n", i, MySemaphore[i]);
|
||||
}
|
||||
|
||||
OS_ThreadCreate("TestSem", TestSemThread, &info, 50, 0);
|
||||
|
||||
for(i = 0; i < SEMAPHORE_COUNT/2; ++i)
|
||||
{
|
||||
printf("S");
|
||||
OS_SemaphorePost(info.MySemaphore[i]);
|
||||
rc = OS_SemaphorePend(info.MySemaphore[i + SEMAPHORE_COUNT/2], 500);
|
||||
assert(rc == 0);
|
||||
}
|
||||
|
||||
printf(":");
|
||||
rc = OS_SemaphorePend(info.MySemaphore[0], 10);
|
||||
assert(rc != 0);
|
||||
printf(":");
|
||||
OS_SemaphorePend(info.MySemaphore[0], 100);
|
||||
printf(":");
|
||||
|
||||
for(i = 0; i < SEMAPHORE_COUNT; ++i)
|
||||
OS_SemaphoreDelete(info.MySemaphore[i]);
|
||||
|
||||
printf("\nDone.\n");
|
||||
}
|
||||
|
||||
//******************************************************************
|
||||
static void TestMutexThread(void *arg)
|
||||
{
|
||||
TestInfo_t *info = (TestInfo_t*)arg;
|
||||
|
||||
printf("Waiting for mutex\n");
|
||||
OS_MutexPend(info->MyMutex);
|
||||
printf("Have Mutex1\n");
|
||||
OS_MutexPend(info->MyMutex);
|
||||
printf("Have Mutex2\n");
|
||||
OS_MutexPend(info->MyMutex);
|
||||
printf("Have Mutex3\n");
|
||||
|
||||
OS_ThreadSleep(100);
|
||||
|
||||
OS_MutexPost(info->MyMutex);
|
||||
OS_MutexPost(info->MyMutex);
|
||||
OS_MutexPost(info->MyMutex);
|
||||
|
||||
OS_ThreadExit();
|
||||
}
|
||||
|
||||
static void TestMutex(void)
|
||||
{
|
||||
TestInfo_t info;
|
||||
printf("TestMutex\n");
|
||||
info.MyMutex = OS_MutexCreate("MyMutex");
|
||||
OS_MutexPend(info.MyMutex);
|
||||
OS_MutexPend(info.MyMutex);
|
||||
OS_MutexPend(info.MyMutex);
|
||||
|
||||
OS_ThreadSleep(100);
|
||||
|
||||
OS_ThreadCreate("TestMutex", TestMutexThread, &info, 50, 0);
|
||||
|
||||
OS_ThreadSleep(50);
|
||||
OS_MutexPost(info.MyMutex);
|
||||
OS_MutexPost(info.MyMutex);
|
||||
OS_MutexPost(info.MyMutex);
|
||||
|
||||
printf("Try get mutex\n");
|
||||
OS_MutexPend(info.MyMutex);
|
||||
printf("Gotit\n");
|
||||
|
||||
OS_MutexDelete(info.MyMutex);
|
||||
printf("Done.\n");
|
||||
}
|
||||
|
||||
//******************************************************************
|
||||
static void TestMQueue(void)
|
||||
{
|
||||
OS_MQueue_t *mqueue;
|
||||
char data[16];
|
||||
int i, rc;
|
||||
|
||||
printf("TestMQueue\n");
|
||||
mqueue = OS_MQueueCreate("MyMQueue", 10, 16);
|
||||
strcpy(data, "Test0");
|
||||
for(i = 0; i < 16; ++i)
|
||||
{
|
||||
data[4] = (char)('0' + i);
|
||||
OS_MQueueSend(mqueue, data);
|
||||
}
|
||||
for(i = 0; i < 16; ++i)
|
||||
{
|
||||
memset(data, 0, sizeof(data));
|
||||
rc = OS_MQueueGet(mqueue, data, 20);
|
||||
if(rc == 0)
|
||||
printf("message=(%s)\n", data);
|
||||
else
|
||||
printf("timeout\n");
|
||||
}
|
||||
|
||||
OS_MQueueDelete(mqueue);
|
||||
printf("Done.\n");
|
||||
}
|
||||
|
||||
//******************************************************************
|
||||
static void TestTimerThread(void *arg)
|
||||
{
|
||||
int index;
|
||||
uint32 data[4];
|
||||
OS_Timer_t *timer;
|
||||
TestInfo_t *info = (TestInfo_t*)arg;
|
||||
|
||||
//printf("TestTimerThread\n");
|
||||
|
||||
OS_ThreadSleep(1);
|
||||
index = (int)OS_ThreadInfoGet(OS_ThreadSelf(), 0);
|
||||
//printf("index=%d\n", index);
|
||||
OS_MQueueGet(info->MyQueue[index], data, 1000);
|
||||
timer = (OS_Timer_t*)data[1];
|
||||
printf("%d ", data[2]);
|
||||
OS_MQueueGet(info->MyQueue[index], data, 1000);
|
||||
printf("%d ", data[2]);
|
||||
++info->TimerDone;
|
||||
OS_ThreadExit();
|
||||
}
|
||||
|
||||
static void TestTimer(void)
|
||||
{
|
||||
int i;
|
||||
TestInfo_t info;
|
||||
|
||||
printf("TestTimer\n");
|
||||
info.TimerDone = 0;
|
||||
for(i = 0; i < TIMER_COUNT; ++i)
|
||||
{
|
||||
info.MyQueue[i] = OS_MQueueCreate("MyQueue", 10, 16);
|
||||
info.MyTimer[i] = OS_TimerCreate("MyTimer", info.MyQueue[i], i);
|
||||
info.MyThread[i] = OS_ThreadCreate("TimerTest", TestTimerThread, &info, 50, 0);
|
||||
OS_ThreadInfoSet(info.MyThread[i], 0, (void*)i);
|
||||
OS_TimerStart(info.MyTimer[i], 10+i*2, 220+i);
|
||||
}
|
||||
|
||||
while(info.TimerDone < TIMER_COUNT)
|
||||
OS_ThreadSleep(10);
|
||||
|
||||
for(i = 0; i < TIMER_COUNT; ++i)
|
||||
{
|
||||
OS_MQueueDelete(info.MyQueue[i]);
|
||||
OS_TimerDelete(info.MyTimer[i]);
|
||||
}
|
||||
|
||||
printf("Done.\n");
|
||||
}
|
||||
|
||||
//******************************************************************
|
||||
#if 1
|
||||
void TestMath(void)
|
||||
{
|
||||
int i;
|
||||
float a, b, sum, diff, mult, div;
|
||||
uint32 compare;
|
||||
|
||||
//Check add subtract multiply and divide
|
||||
for(i = -4; i < 4; ++i)
|
||||
{
|
||||
a = (float)(i * 10 + (float)63.2);
|
||||
b = (float)(-i * 5 + (float)3.5);
|
||||
sum = a + b;
|
||||
diff = a - b;
|
||||
mult = a * b;
|
||||
div = a / b;
|
||||
printf("a=%dE-3 b=%dE-3 sum=%dE-3 diff=%dE-3 mult=%dE-3 div=%dE-3\n",
|
||||
(int)(a*(float)1000), (int)(b*(float)1000),
|
||||
(int)(sum*(float)1000), (int)(diff*(float)1000),
|
||||
(int)(mult*(float)1000), (int)(div*(float)1000));
|
||||
}
|
||||
|
||||
//Comparisons
|
||||
b = (float)2.0;
|
||||
compare = 0;
|
||||
for(i = 1; i < 4; ++i)
|
||||
{
|
||||
a = (float)i;
|
||||
compare = (compare << 1) | (a == b);
|
||||
compare = (compare << 1) | (a != b);
|
||||
compare = (compare << 1) | (a < b);
|
||||
compare = (compare << 1) | (a <= b);
|
||||
compare = (compare << 1) | (a > b);
|
||||
compare = (compare << 1) | (a >= b);
|
||||
}
|
||||
printf("Compare = %8x %s\n", compare,
|
||||
compare==0x1c953 ? "OK" : "ERROR");
|
||||
|
||||
//Cosine
|
||||
for(a = (float)0.0; a <= (float)(3.1415); a += (float)(3.1415/16.0))
|
||||
{
|
||||
b = FP_Cos(a);
|
||||
printf("cos(%4dE-3) = %4dE-3\n",
|
||||
(int)(a*(float)1000.0), (int)(b*(float)1000.0));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//******************************************************************
|
||||
#ifndef WIN32
|
||||
static void MySyscall(void *arg)
|
||||
{
|
||||
uint32 *stack = arg;
|
||||
stack[STACK_EPC] += 4; //skip over SYSCALL
|
||||
printf("Inside MySyscall %d\n", stack[28/4]);
|
||||
}
|
||||
|
||||
void TestSyscall(void)
|
||||
{
|
||||
OS_InterruptRegister((uint32)(1<<31), MySyscall);
|
||||
OS_Syscall(57);
|
||||
OS_ThreadSleep(1);
|
||||
printf("Done\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __MMU_ENUM_H__
|
||||
void TestProcess(void)
|
||||
{
|
||||
OS_Process_t *process;
|
||||
process = (OS_Process_t*)OS_HeapMalloc(NULL, sizeof(OS_Process_t));
|
||||
process->name = "test";
|
||||
process->funcPtr = MainThread;
|
||||
process->arg = NULL;
|
||||
process->priority = 200;
|
||||
process->stackSize = 1024*32;
|
||||
process->heapSize = 1024*128;
|
||||
process->processId = 1;
|
||||
process->semaphoreDone = OS_SemaphoreCreate("processDone", 0);
|
||||
printf("Creating process\n");
|
||||
OS_MMUProcessCreate(process);
|
||||
OS_SemaphorePend(process->semaphoreDone, OS_WAIT_FOREVER);
|
||||
printf("Process done\n");
|
||||
OS_MMUProcessDelete(process);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
//******************************************************************
|
||||
void MMUTest(void);
|
||||
void HtmlThread(void *arg);
|
||||
void ConsoleInit(void);
|
||||
void exit(int);
|
||||
uint8 macAddress[] = {0x00, 0x10, 0xdd, 0xce, 0x15, 0xd4};
|
||||
|
||||
|
||||
void MainThread(void *Arg)
|
||||
{
|
||||
int ch, i, display=1;
|
||||
(void)Arg;
|
||||
#ifdef __MMU_ENUM_H__
|
||||
OS_MMUInit();
|
||||
#endif
|
||||
|
||||
#ifdef INCLUDE_ETH
|
||||
EthernetInit(macAddress);
|
||||
IPInit(EthernetTransmit, macAddress, "plasma");
|
||||
HtmlInit(1);
|
||||
#endif
|
||||
|
||||
#ifdef INCLUDE_HTML
|
||||
IPInit(NULL, macAddress, "plasma");
|
||||
HtmlInit(1);
|
||||
#endif
|
||||
|
||||
#ifdef INCLUDE_CONSOLE
|
||||
ConsoleInit();
|
||||
#endif
|
||||
|
||||
for(;;)
|
||||
{
|
||||
if(display)
|
||||
{
|
||||
printf("\n");
|
||||
printf("1 CLib\n");
|
||||
printf("2 Heap\n");
|
||||
printf("3 Thread\n");
|
||||
printf("4 Semaphore\n");
|
||||
printf("5 Mutex\n");
|
||||
printf("6 MQueue\n");
|
||||
printf("7 Timer\n");
|
||||
printf("8 Math\n");
|
||||
printf("9 Syscall\n");
|
||||
#ifdef __MMU_ENUM_H__
|
||||
printf("p MMU Process\n");
|
||||
#endif
|
||||
}
|
||||
printf("> ");
|
||||
display = 1;
|
||||
ch = UartRead();
|
||||
printf("%c\n", ch);
|
||||
switch(ch)
|
||||
{
|
||||
#ifdef WIN32
|
||||
case '0': exit(0);
|
||||
#endif
|
||||
case '1': TestCLib(); break;
|
||||
case '2': TestHeap(); break;
|
||||
case '3': TestThread(); break;
|
||||
case '4': TestSemaphore(); break;
|
||||
case '5': TestMutex(); break;
|
||||
case '6': TestMQueue(); break;
|
||||
case '7': TestTimer(); break;
|
||||
case '8': TestMath(); break;
|
||||
#ifndef WIN32
|
||||
case '9': TestSyscall(); break;
|
||||
#endif
|
||||
#ifdef __MMU_ENUM_H__
|
||||
case 'p': TestProcess(); break;
|
||||
#endif
|
||||
#ifdef WIN32
|
||||
case 'm': TestMathFull(); break;
|
||||
#endif
|
||||
case 'g': printf("Global=%d\n", ++Global); break;
|
||||
default:
|
||||
printf("E");
|
||||
display = 0;
|
||||
for(i = 0; i < 30; ++i)
|
||||
{
|
||||
while(kbhit())
|
||||
ch = UartRead();
|
||||
OS_ThreadSleep(1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
1679
plasma/kernel/tcpip.c
Normal file
1679
plasma/kernel/tcpip.c
Normal file
File diff suppressed because it is too large
Load Diff
131
plasma/kernel/tcpip.h
Normal file
131
plasma/kernel/tcpip.h
Normal file
@ -0,0 +1,131 @@
|
||||
/*--------------------------------------------------------------------
|
||||
* TITLE: Plasma TCP/IP Protocol Stack
|
||||
* AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
|
||||
* DATE CREATED: 4/22/06
|
||||
* FILENAME: tcpip.h
|
||||
* PROJECT: Plasma CPU core
|
||||
* COPYRIGHT: Software placed into the public domain by the author.
|
||||
* Software 'as is' without warranty. Author liable for nothing.
|
||||
* DESCRIPTION:
|
||||
* Plasma TCP/IP Protocol Stack
|
||||
*--------------------------------------------------------------------*/
|
||||
#ifndef __TCPIP_H__
|
||||
#define __TCPIP_H__
|
||||
#define PACKET_SIZE 600
|
||||
#define FRAME_COUNT 100
|
||||
#define FRAME_COUNT_SYNC 50
|
||||
#define FRAME_COUNT_SEND 10
|
||||
#define FRAME_COUNT_RCV 5
|
||||
#define RETRANSMIT_TIME 110
|
||||
#define SOCKET_TIMEOUT 12
|
||||
#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;
|
||||
void *fileIn;
|
||||
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__
|
549
plasma/kernel/uart.c
Normal file
549
plasma/kernel/uart.c
Normal file
@ -0,0 +1,549 @@
|
||||
/*--------------------------------------------------------------------
|
||||
* TITLE: Plasma Uart Driver
|
||||
* AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
|
||||
* DATE CREATED: 12/31/05
|
||||
* FILENAME: uart.c
|
||||
* PROJECT: Plasma CPU core
|
||||
* COPYRIGHT: Software placed into the public domain by the author.
|
||||
* Software 'as is' without warranty. Author liable for nothing.
|
||||
* DESCRIPTION:
|
||||
* Plasma Uart Driver
|
||||
*--------------------------------------------------------------------*/
|
||||
#define NO_ELLIPSIS2
|
||||
#include "plasma.h"
|
||||
#include "rtos.h"
|
||||
|
||||
#ifndef NO_PACKETS
|
||||
#define SUPPORT_DATA_PACKETS
|
||||
#endif
|
||||
|
||||
#define BUFFER_WRITE_SIZE 128
|
||||
#define BUFFER_READ_SIZE 128
|
||||
#define BUFFER_PRINTF_SIZE 1024
|
||||
#undef UartPrintf
|
||||
|
||||
void UartPrintfCritical(const char *format,
|
||||
int arg0, int arg1, int arg2, int arg3,
|
||||
int arg4, int arg5, int arg6, int arg7);
|
||||
|
||||
typedef struct Buffer_s {
|
||||
uint8 *data;
|
||||
int size;
|
||||
volatile int read, write;
|
||||
volatile int pendingRead, pendingWrite;
|
||||
OS_Semaphore_t *semaphoreRead, *semaphoreWrite;
|
||||
} Buffer_t;
|
||||
|
||||
static Buffer_t *WriteBuffer, *ReadBuffer;
|
||||
static OS_Semaphore_t *SemaphoreUart;
|
||||
static char PrintfString[BUFFER_PRINTF_SIZE]; //Used in UartPrintf
|
||||
|
||||
#ifdef SUPPORT_DATA_PACKETS
|
||||
//For packet processing [0xff lengthMSB lengthLSB checksum data]
|
||||
static PacketGetFunc_t UartPacketGet;
|
||||
static uint8 *PacketCurrent;
|
||||
static uint32 UartPacketSize;
|
||||
static uint32 UartPacketChecksum, Checksum;
|
||||
static OS_MQueue_t *UartPacketMQueue;
|
||||
static uint32 PacketBytes, PacketLength;
|
||||
static uint32 UartPacketOutLength, UartPacketOutByte;
|
||||
int CountOk, CountError;
|
||||
#endif
|
||||
static uint8 *UartPacketOut;
|
||||
|
||||
|
||||
/******************************************/
|
||||
Buffer_t *BufferCreate(int size)
|
||||
{
|
||||
Buffer_t *buffer;
|
||||
buffer = (Buffer_t*)OS_HeapMalloc(NULL, sizeof(Buffer_t) + size);
|
||||
if(buffer == NULL)
|
||||
return NULL;
|
||||
buffer->data = (uint8*)(buffer + 1);
|
||||
buffer->read = 0;
|
||||
buffer->write = 0;
|
||||
buffer->size = size;
|
||||
buffer->pendingRead = 0;
|
||||
buffer->pendingWrite = 0;
|
||||
buffer->semaphoreRead = OS_SemaphoreCreate("BufferRead", 0);
|
||||
buffer->semaphoreWrite = OS_SemaphoreCreate("BufferWrite", 0);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
void BufferWrite(Buffer_t *buffer, int value, int pend)
|
||||
{
|
||||
int writeNext;
|
||||
|
||||
writeNext = buffer->write + 1;
|
||||
if(writeNext >= buffer->size)
|
||||
writeNext = 0;
|
||||
|
||||
//Check if room for value
|
||||
if(writeNext == buffer->read)
|
||||
{
|
||||
if(pend == 0)
|
||||
return;
|
||||
++buffer->pendingWrite;
|
||||
OS_SemaphorePend(buffer->semaphoreWrite, OS_WAIT_FOREVER);
|
||||
}
|
||||
|
||||
buffer->data[buffer->write] = (uint8)value;
|
||||
buffer->write = writeNext;
|
||||
if(buffer->pendingRead)
|
||||
{
|
||||
--buffer->pendingRead;
|
||||
OS_SemaphorePost(buffer->semaphoreRead);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int BufferRead(Buffer_t *buffer, int pend)
|
||||
{
|
||||
int value;
|
||||
|
||||
//Check if empty buffer
|
||||
if(buffer->read == buffer->write)
|
||||
{
|
||||
if(pend == 0)
|
||||
return 0;
|
||||
++buffer->pendingRead;
|
||||
OS_SemaphorePend(buffer->semaphoreRead, OS_WAIT_FOREVER);
|
||||
}
|
||||
|
||||
value = buffer->data[buffer->read];
|
||||
if(++buffer->read >= buffer->size)
|
||||
buffer->read = 0;
|
||||
if(buffer->pendingWrite)
|
||||
{
|
||||
--buffer->pendingWrite;
|
||||
OS_SemaphorePost(buffer->semaphoreWrite);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
/******************************************/
|
||||
#ifdef SUPPORT_DATA_PACKETS
|
||||
static void UartPacketRead(uint32 value)
|
||||
{
|
||||
uint32 message[4];
|
||||
if(PacketBytes == 0 && value == 0xff)
|
||||
{
|
||||
++PacketBytes;
|
||||
}
|
||||
else if(PacketBytes == 1)
|
||||
{
|
||||
++PacketBytes;
|
||||
PacketLength = value << 8;
|
||||
}
|
||||
else if(PacketBytes == 2)
|
||||
{
|
||||
++PacketBytes;
|
||||
PacketLength |= value;
|
||||
if(PacketLength <= UartPacketSize)
|
||||
{
|
||||
if(PacketCurrent == NULL)
|
||||
PacketCurrent = UartPacketGet();
|
||||
}
|
||||
else
|
||||
{
|
||||
PacketBytes = 0;
|
||||
}
|
||||
}
|
||||
else if(PacketBytes == 3)
|
||||
{
|
||||
++PacketBytes;
|
||||
UartPacketChecksum = value;
|
||||
Checksum = 0;
|
||||
}
|
||||
else if(PacketBytes >= 4)
|
||||
{
|
||||
if(PacketCurrent)
|
||||
PacketCurrent[PacketBytes - 4] = (uint8)value;
|
||||
Checksum += value;
|
||||
++PacketBytes;
|
||||
if(PacketBytes - 4 >= PacketLength)
|
||||
{
|
||||
if((uint8)Checksum == UartPacketChecksum)
|
||||
{
|
||||
//Notify thread that a packet has been received
|
||||
++CountOk;
|
||||
message[0] = 0;
|
||||
message[1] = (uint32)PacketCurrent;
|
||||
message[2] = PacketLength;
|
||||
if(PacketCurrent)
|
||||
OS_MQueueSend(UartPacketMQueue, message);
|
||||
PacketCurrent = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
++CountError;
|
||||
//printf("E");
|
||||
}
|
||||
PacketBytes = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int UartPacketWrite(void)
|
||||
{
|
||||
int value=0, i;
|
||||
uint32 message[4];
|
||||
if(UartPacketOut)
|
||||
{
|
||||
if(UartPacketOutByte == 0)
|
||||
{
|
||||
value = 0xff;
|
||||
++UartPacketOutByte;
|
||||
}
|
||||
else if(UartPacketOutByte == 1)
|
||||
{
|
||||
value = UartPacketOutLength >> 8;
|
||||
++UartPacketOutByte;
|
||||
}
|
||||
else if(UartPacketOutByte == 2)
|
||||
{
|
||||
value = (uint8)UartPacketOutLength;
|
||||
++UartPacketOutByte;
|
||||
}
|
||||
else if(UartPacketOutByte == 3)
|
||||
{
|
||||
value = 0;
|
||||
for(i = 0; i < (int)UartPacketOutLength; ++i)
|
||||
value += UartPacketOut[i];
|
||||
value = (uint8)value;
|
||||
++UartPacketOutByte;
|
||||
}
|
||||
else
|
||||
{
|
||||
value = UartPacketOut[UartPacketOutByte - 4];
|
||||
++UartPacketOutByte;
|
||||
if(UartPacketOutByte - 4 >= UartPacketOutLength)
|
||||
{
|
||||
//Notify thread that a packet has been sent
|
||||
message[0] = 1;
|
||||
message[1] = (uint32)UartPacketOut;
|
||||
UartPacketOut = 0;
|
||||
OS_MQueueSend(UartPacketMQueue, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static void UartInterrupt(void *arg)
|
||||
{
|
||||
uint32 status, value, count=0;
|
||||
(void)arg;
|
||||
|
||||
status = OS_InterruptStatus();
|
||||
while(status & IRQ_UART_READ_AVAILABLE)
|
||||
{
|
||||
value = MemoryRead(UART_READ);
|
||||
#ifdef SUPPORT_DATA_PACKETS
|
||||
if(UartPacketGet && (value == 0xff || PacketBytes))
|
||||
UartPacketRead(value);
|
||||
else
|
||||
#endif
|
||||
BufferWrite(ReadBuffer, value, 0);
|
||||
status = OS_InterruptStatus();
|
||||
if(++count >= 16)
|
||||
break;
|
||||
}
|
||||
while(status & IRQ_UART_WRITE_AVAILABLE)
|
||||
{
|
||||
#ifdef SUPPORT_DATA_PACKETS
|
||||
if(UartPacketOut)
|
||||
{
|
||||
value = UartPacketWrite();
|
||||
MemoryWrite(UART_WRITE, value);
|
||||
} else
|
||||
#endif
|
||||
if(WriteBuffer->read != WriteBuffer->write)
|
||||
{
|
||||
value = BufferRead(WriteBuffer, 0);
|
||||
MemoryWrite(UART_WRITE, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
OS_InterruptMaskClear(IRQ_UART_WRITE_AVAILABLE);
|
||||
break;
|
||||
}
|
||||
status = OS_InterruptStatus();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void UartInit(void)
|
||||
{
|
||||
uint32 mask;
|
||||
|
||||
SemaphoreUart = OS_SemaphoreCreate("Uart", 1);
|
||||
WriteBuffer = BufferCreate(BUFFER_WRITE_SIZE);
|
||||
ReadBuffer = BufferCreate(BUFFER_READ_SIZE);
|
||||
|
||||
mask = IRQ_UART_READ_AVAILABLE | IRQ_UART_WRITE_AVAILABLE;
|
||||
OS_InterruptRegister(mask, UartInterrupt);
|
||||
OS_InterruptMaskSet(IRQ_UART_READ_AVAILABLE);
|
||||
}
|
||||
|
||||
|
||||
void UartWrite(int ch)
|
||||
{
|
||||
BufferWrite(WriteBuffer, ch, 1);
|
||||
OS_InterruptMaskSet(IRQ_UART_WRITE_AVAILABLE);
|
||||
}
|
||||
|
||||
|
||||
uint8 UartRead(void)
|
||||
{
|
||||
return (uint8)BufferRead(ReadBuffer, 1);
|
||||
}
|
||||
|
||||
|
||||
void UartWriteData(uint8 *data, int length)
|
||||
{
|
||||
OS_SemaphorePend(SemaphoreUart, OS_WAIT_FOREVER);
|
||||
while(length--)
|
||||
UartWrite(*data++);
|
||||
OS_SemaphorePost(SemaphoreUart);
|
||||
}
|
||||
|
||||
|
||||
void UartReadData(uint8 *data, int length)
|
||||
{
|
||||
OS_SemaphorePend(SemaphoreUart, OS_WAIT_FOREVER);
|
||||
while(length--)
|
||||
*data++ = UartRead();
|
||||
OS_SemaphorePost(SemaphoreUart);
|
||||
}
|
||||
|
||||
|
||||
void UartPrintf(const char *format,
|
||||
int arg0, int arg1, int arg2, int arg3,
|
||||
int arg4, int arg5, int arg6, int arg7)
|
||||
{
|
||||
uint8 *ptr;
|
||||
#if 0
|
||||
//Check for string "!m#~" to mask print statement
|
||||
static char moduleLevel[26];
|
||||
if(format[0] == '!' && format[3] == '~')
|
||||
{
|
||||
int level = format[2] - '5';
|
||||
if('a' <= format[1] && format[1] <= 'z')
|
||||
{
|
||||
if(level < moduleLevel[format[1] - 'a'])
|
||||
return;
|
||||
}
|
||||
else if('A' <= format[1] && format[1] <= 'Z')
|
||||
moduleLevel[format[1] - 'A'] = (char)level;
|
||||
format += 4;
|
||||
}
|
||||
#endif
|
||||
OS_SemaphorePend(SemaphoreUart, OS_WAIT_FOREVER);
|
||||
sprintf(PrintfString, format, arg0, arg1, arg2, arg3,
|
||||
arg4, arg5, arg6, arg7);
|
||||
ptr = (uint8*)PrintfString;
|
||||
while(*ptr)
|
||||
{
|
||||
if(*ptr == '\n')
|
||||
UartWrite('\r');
|
||||
#ifdef SUPPORT_DATA_PACKETS
|
||||
if(*ptr == 0xff)
|
||||
*ptr = '@';
|
||||
#endif
|
||||
UartWrite(*ptr++);
|
||||
}
|
||||
OS_SemaphorePost(SemaphoreUart);
|
||||
}
|
||||
|
||||
|
||||
void UartPrintfPoll(const char *format,
|
||||
int arg0, int arg1, int arg2, int arg3,
|
||||
int arg4, int arg5, int arg6, int arg7)
|
||||
{
|
||||
uint8 *ptr;
|
||||
uint32 state;
|
||||
|
||||
if(SemaphoreUart)
|
||||
OS_SemaphorePend(SemaphoreUart, OS_WAIT_FOREVER);
|
||||
sprintf(PrintfString, format, arg0, arg1, arg2, arg3,
|
||||
arg4, arg5, arg6, arg7);
|
||||
ptr = (uint8*)PrintfString;
|
||||
while(*ptr)
|
||||
{
|
||||
while((MemoryRead(IRQ_STATUS) & IRQ_UART_WRITE_AVAILABLE) == 0)
|
||||
;
|
||||
state = OS_CriticalBegin();
|
||||
if((MemoryRead(IRQ_STATUS) & IRQ_UART_WRITE_AVAILABLE) &&
|
||||
UartPacketOut == NULL)
|
||||
{
|
||||
MemoryWrite(UART_WRITE, *ptr++);
|
||||
}
|
||||
OS_CriticalEnd(state);
|
||||
}
|
||||
if(SemaphoreUart)
|
||||
OS_SemaphorePost(SemaphoreUart);
|
||||
}
|
||||
|
||||
|
||||
void UartPrintfCritical(const char *format,
|
||||
int arg0, int arg1, int arg2, int arg3,
|
||||
int arg4, int arg5, int arg6, int arg7)
|
||||
{
|
||||
uint8 *ptr;
|
||||
uint32 state;
|
||||
|
||||
state = OS_CriticalBegin();
|
||||
sprintf(PrintfString, format, arg0, arg1, arg2, arg3,
|
||||
arg4, arg5, arg6, arg7);
|
||||
ptr = (uint8*)PrintfString;
|
||||
while(*ptr)
|
||||
{
|
||||
while((MemoryRead(IRQ_STATUS) & IRQ_UART_WRITE_AVAILABLE) == 0)
|
||||
;
|
||||
MemoryWrite(UART_WRITE, *ptr++);
|
||||
#ifdef SUPPORT_DATA_PACKETS
|
||||
if(UartPacketOut && UartPacketOutByte - 4 < UartPacketOutLength)
|
||||
{
|
||||
++UartPacketOutByte;
|
||||
--ptr;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
memset(PrintfString, 0, sizeof(PrintfString));
|
||||
OS_CriticalEnd(state);
|
||||
}
|
||||
|
||||
|
||||
void UartPrintfNull(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void UartScanf(const char *format,
|
||||
int arg0, int arg1, int arg2, int arg3,
|
||||
int arg4, int arg5, int arg6, int arg7)
|
||||
{
|
||||
int index = 0, ch;
|
||||
OS_SemaphorePend(SemaphoreUart, OS_WAIT_FOREVER);
|
||||
for(;;)
|
||||
{
|
||||
ch = UartRead();
|
||||
if(ch != '\b' || index)
|
||||
UartWrite(ch);
|
||||
if(ch == '\n' || ch == '\r')
|
||||
break;
|
||||
else if(ch == '\b')
|
||||
{
|
||||
if(index)
|
||||
{
|
||||
UartWrite(' ');
|
||||
UartWrite(ch);
|
||||
--index;
|
||||
}
|
||||
}
|
||||
else if(index < sizeof(PrintfString))
|
||||
PrintfString[index++] = (uint8)ch;
|
||||
}
|
||||
UartWrite('\n');
|
||||
PrintfString[index] = 0;
|
||||
sscanf(PrintfString, format, arg0, arg1, arg2, arg3,
|
||||
arg4, arg5, arg6, arg7);
|
||||
OS_SemaphorePost(SemaphoreUart);
|
||||
}
|
||||
|
||||
|
||||
#ifdef SUPPORT_DATA_PACKETS
|
||||
void UartPacketConfig(PacketGetFunc_t PacketGetFunc,
|
||||
int PacketSize,
|
||||
OS_MQueue_t *mQueue)
|
||||
{
|
||||
UartPacketGet = PacketGetFunc;
|
||||
UartPacketSize = PacketSize;
|
||||
UartPacketMQueue = mQueue;
|
||||
}
|
||||
|
||||
|
||||
void UartPacketSend(uint8 *data, int bytes)
|
||||
{
|
||||
UartPacketOutByte = 0;
|
||||
UartPacketOutLength = bytes;
|
||||
UartPacketOut = data;
|
||||
OS_InterruptMaskSet(IRQ_UART_WRITE_AVAILABLE);
|
||||
}
|
||||
#else
|
||||
void UartPacketConfig(PacketGetFunc_t PacketGetFunc,
|
||||
int PacketSize,
|
||||
OS_MQueue_t *mQueue)
|
||||
{ (void)PacketGetFunc; (void)PacketSize; (void)mQueue; }
|
||||
|
||||
|
||||
void UartPacketSend(uint8 *data, int bytes)
|
||||
{ (void)data; (void)bytes; }
|
||||
#endif
|
||||
|
||||
|
||||
void Led(int mask, int value)
|
||||
{
|
||||
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
|
||||
|
239
plasma/lib/crt0.S
Normal file
239
plasma/lib/crt0.S
Normal file
@ -0,0 +1,239 @@
|
||||
##################################################################
|
||||
# TITLE: Boot Up Code
|
||||
# AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
|
||||
# DATE CREATED: 1/12/02
|
||||
# FILENAME: boot.asm
|
||||
# PROJECT: Plasma CPU core
|
||||
# COPYRIGHT: Software placed into the public domain by the author.
|
||||
# Software 'as is' without warranty. Author liable for nothing.
|
||||
# DESCRIPTION:
|
||||
# Initializes the stack pointer and jumps to main().
|
||||
##################################################################
|
||||
#Reserve 512 bytes for stack
|
||||
.comm InitStack, 512
|
||||
|
||||
.text
|
||||
.align 2
|
||||
.global entry
|
||||
.ent entry
|
||||
entry:
|
||||
.set noreorder
|
||||
|
||||
#These four instructions should be the first instructions.
|
||||
#convert.exe previously initialized $gp, .sbss_start, .bss_end, $sp
|
||||
la $gp, _gp #initialize global pointer
|
||||
la $5, __bss_start #$5 = .sbss_start
|
||||
la $4, _end #$2 = .bss_end
|
||||
la $sp, InitStack+488 #initialize stack pointer
|
||||
|
||||
$BSS_CLEAR:
|
||||
sw $0, 0($5)
|
||||
slt $3, $5, $4
|
||||
bnez $3, $BSS_CLEAR
|
||||
addiu $5, $5, 4
|
||||
|
||||
jal main
|
||||
nop
|
||||
$L1:
|
||||
j $L1
|
||||
|
||||
.end entry
|
||||
|
||||
|
||||
###################################################
|
||||
#address 0x3c
|
||||
.global interrupt_service_routine
|
||||
.ent interrupt_service_routine
|
||||
interrupt_service_routine:
|
||||
.set noreorder
|
||||
.set noat
|
||||
|
||||
#Registers $26 and $27 are reserved for the OS
|
||||
#Save all temporary registers
|
||||
#Slots 0($29) through 12($29) reserved for saving a0-a3
|
||||
addi $29, $29, -104 #adjust sp
|
||||
sw $1, 16($29) #at
|
||||
sw $2, 20($29) #v0
|
||||
sw $3, 24($29) #v1
|
||||
sw $4, 28($29) #a0
|
||||
sw $5, 32($29) #a1
|
||||
sw $6, 36($29) #a2
|
||||
sw $7, 40($29) #a3
|
||||
sw $8, 44($29) #t0
|
||||
sw $9, 48($29) #t1
|
||||
sw $10, 52($29) #t2
|
||||
sw $11, 56($29) #t3
|
||||
sw $12, 60($29) #t4
|
||||
sw $13, 64($29) #t5
|
||||
sw $14, 68($29) #t6
|
||||
sw $15, 72($29) #t7
|
||||
sw $24, 76($29) #t8
|
||||
sw $25, 80($29) #t9
|
||||
sw $31, 84($29) #lr
|
||||
mfc0 $26, $14 #C0_EPC=14 (Exception PC)
|
||||
addi $26, $26, -4 #Backup one opcode
|
||||
sw $26, 88($29) #pc
|
||||
mfhi $27
|
||||
sw $27, 92($29) #hi
|
||||
mflo $27
|
||||
sw $27, 96($29) #lo
|
||||
|
||||
lui $6, 0x2000
|
||||
lw $4, 0x20($6) #IRQ_STATUS
|
||||
lw $6, 0x10($6) #IRQ_MASK
|
||||
and $4, $4, $6
|
||||
jal OS_InterruptServiceRoutine
|
||||
addi $5, $29, 0
|
||||
|
||||
#Restore all temporary registers
|
||||
lw $1, 16($29) #at
|
||||
lw $2, 20($29) #v0
|
||||
lw $3, 24($29) #v1
|
||||
lw $4, 28($29) #a0
|
||||
lw $5, 32($29) #a1
|
||||
lw $6, 36($29) #a2
|
||||
lw $7, 40($29) #a3
|
||||
lw $8, 44($29) #t0
|
||||
lw $9, 48($29) #t1
|
||||
lw $10, 52($29) #t2
|
||||
lw $11, 56($29) #t3
|
||||
lw $12, 60($29) #t4
|
||||
lw $13, 64($29) #t5
|
||||
lw $14, 68($29) #t6
|
||||
lw $15, 72($29) #t7
|
||||
lw $24, 76($29) #t8
|
||||
lw $25, 80($29) #t9
|
||||
lw $31, 84($29) #lr
|
||||
lw $26, 88($29) #pc
|
||||
lw $27, 92($29) #hi
|
||||
mthi $27
|
||||
lw $27, 96($29) #lo
|
||||
mtlo $27
|
||||
addi $29, $29, 104 #adjust sp
|
||||
|
||||
isr_return:
|
||||
ori $27, $0, 0x1 #re-enable interrupts
|
||||
jr $26
|
||||
mtc0 $27, $12 #STATUS=1; enable interrupts
|
||||
|
||||
.end interrupt_service_routine
|
||||
.set at
|
||||
|
||||
|
||||
###################################################
|
||||
.global OS_AsmInterruptEnable
|
||||
.ent OS_AsmInterruptEnable
|
||||
OS_AsmInterruptEnable:
|
||||
.set noreorder
|
||||
mfc0 $2, $12
|
||||
jr $31
|
||||
mtc0 $4, $12 #STATUS=1; enable interrupts
|
||||
#nop
|
||||
.set reorder
|
||||
.end OS_AsmInterruptEnable
|
||||
|
||||
|
||||
###################################################
|
||||
.global OS_AsmInterruptInit
|
||||
.ent OS_AsmInterruptInit
|
||||
OS_AsmInterruptInit:
|
||||
.set noreorder
|
||||
#Patch interrupt vector to 0x1000003c
|
||||
la $5, OS_AsmPatchValue
|
||||
lw $6, 0($5)
|
||||
sw $6, 0x3c($0)
|
||||
lw $6, 4($5)
|
||||
sw $6, 0x40($0)
|
||||
lw $6, 8($5)
|
||||
sw $6, 0x44($0)
|
||||
lw $6, 12($5)
|
||||
jr $31
|
||||
sw $6, 0x48($0)
|
||||
|
||||
OS_AsmPatchValue:
|
||||
#Registers $26 and $27 are reserved for the OS
|
||||
#Code to place at address 0x3c
|
||||
lui $26, 0x1000
|
||||
ori $26, $26, 0x3c
|
||||
jr $26
|
||||
nop
|
||||
|
||||
.set reorder
|
||||
.end OS_AsmInterruptInit
|
||||
|
||||
|
||||
###################################################
|
||||
.global setjmp
|
||||
.ent setjmp
|
||||
setjmp:
|
||||
.set noreorder
|
||||
sw $16, 0($4) #s0
|
||||
sw $17, 4($4) #s1
|
||||
sw $18, 8($4) #s2
|
||||
sw $19, 12($4) #s3
|
||||
sw $20, 16($4) #s4
|
||||
sw $21, 20($4) #s5
|
||||
sw $22, 24($4) #s6
|
||||
sw $23, 28($4) #s7
|
||||
sw $30, 32($4) #s8
|
||||
sw $28, 36($4) #gp
|
||||
sw $29, 40($4) #sp
|
||||
sw $31, 44($4) #lr
|
||||
jr $31
|
||||
ori $2, $0, 0
|
||||
|
||||
.set reorder
|
||||
.end setjmp
|
||||
|
||||
|
||||
###################################################
|
||||
.global longjmp
|
||||
.ent longjmp
|
||||
longjmp:
|
||||
.set noreorder
|
||||
lw $16, 0($4) #s0
|
||||
lw $17, 4($4) #s1
|
||||
lw $18, 8($4) #s2
|
||||
lw $19, 12($4) #s3
|
||||
lw $20, 16($4) #s4
|
||||
lw $21, 20($4) #s5
|
||||
lw $22, 24($4) #s6
|
||||
lw $23, 28($4) #s7
|
||||
lw $30, 32($4) #s8
|
||||
lw $28, 36($4) #gp
|
||||
lw $29, 40($4) #sp
|
||||
lw $31, 44($4) #lr
|
||||
jr $31
|
||||
ori $2, $5, 0
|
||||
|
||||
.set reorder
|
||||
.end longjmp
|
||||
|
||||
|
||||
###################################################
|
||||
.global OS_AsmMult
|
||||
.ent OS_AsmMult
|
||||
OS_AsmMult:
|
||||
.set noreorder
|
||||
multu $4, $5
|
||||
mflo $2
|
||||
mfhi $4
|
||||
jr $31
|
||||
sw $4, 0($6)
|
||||
|
||||
.set reorder
|
||||
.end OS_AsmMult
|
||||
|
||||
|
||||
###################################################
|
||||
.global OS_Syscall
|
||||
.ent OS_Syscall
|
||||
OS_Syscall:
|
||||
.set noreorder
|
||||
syscall 0
|
||||
jr $31
|
||||
nop
|
||||
.set reorder
|
||||
.end OS_Syscall
|
||||
|
||||
|
87
plasma/lib/ddr_init.c
Normal file
87
plasma/lib/ddr_init.c
Normal file
@ -0,0 +1,87 @@
|
||||
/*--------------------------------------------------------------------
|
||||
* 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
|
54
plasma/lib/no_os.c
Normal file
54
plasma/lib/no_os.c
Normal file
@ -0,0 +1,54 @@
|
||||
#include "plasma.h"
|
||||
|
||||
#define MemoryRead(A) (*(volatile unsigned int*)(A))
|
||||
#define MemoryWrite(A,V) *(volatile unsigned int*)(A)=(V)
|
||||
|
||||
int putchar(int value)
|
||||
{
|
||||
while((MemoryRead(IRQ_STATUS) & IRQ_UART_WRITE_AVAILABLE) == 0)
|
||||
;
|
||||
MemoryWrite(UART_WRITE, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int puts(const char *string)
|
||||
{
|
||||
while(*string)
|
||||
{
|
||||
if(*string == '\n')
|
||||
putchar('\r');
|
||||
putchar(*string++);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void print_hex(unsigned long num)
|
||||
{
|
||||
long i;
|
||||
unsigned long j;
|
||||
for(i = 28; i >= 0; i -= 4)
|
||||
{
|
||||
j = (num >> i) & 0xf;
|
||||
if(j < 10)
|
||||
putchar('0' + j);
|
||||
else
|
||||
putchar('a' - 10 + j);
|
||||
}
|
||||
}
|
||||
|
||||
void OS_InterruptServiceRoutine(unsigned int status)
|
||||
{
|
||||
(void)status;
|
||||
putchar('I');
|
||||
}
|
||||
|
||||
int kbhit(void)
|
||||
{
|
||||
return MemoryRead(IRQ_STATUS) & IRQ_UART_READ_AVAILABLE;
|
||||
}
|
||||
|
||||
int getch(void)
|
||||
{
|
||||
while(!kbhit()) ;
|
||||
return MemoryRead(UART_READ);
|
||||
}
|
78
plasma/logic/Makefile
Normal file
78
plasma/logic/Makefile
Normal file
@ -0,0 +1,78 @@
|
||||
DESIGN = plasma_3e
|
||||
PINS = $(DESIGN).ucf
|
||||
DEVICE = xc3s500e-fg320-4
|
||||
BGFLAGS = -g TdoPin:PULLNONE -g DonePin:PULLUP \
|
||||
-g CRC:enable -g StartUpClk:CCLK
|
||||
|
||||
|
||||
SIM_CMD = /opt/cad/modeltech/bin/vsim
|
||||
SIM_COMP_SCRIPT = simulation/$(DESIGN)_TB.do
|
||||
#SIM_INIT_SCRIPT = simulation/$(DESIGN)_init.do
|
||||
SIMGEN_OPTIONS = -p $(FPGA_ARCH) -lang $(LANGUAGE)
|
||||
|
||||
SRC_HDL = plasma.vhd alu.vhd control.vhd mem_ctrl.vhd mult.vhd shifter.vhd bus_mux.vhd ddr_ctrl.vhd mlite_cpu.vhd pc_next.vhd cache.vhd eth_dma.vhd mlite_pack.vhd pipeline.vhd reg_bank.vhd uart.vhd plasma_3e.vhd ram_image.vhd
|
||||
|
||||
|
||||
|
||||
|
||||
all: bits
|
||||
|
||||
remake: clean-build all
|
||||
|
||||
clean:
|
||||
rm -rf *~ */*~ a.out *.log *.key *.edf *.ps trace.dat
|
||||
rm -rf *.bit rm -rf simulation/work simulation/*wlf
|
||||
|
||||
clean-build:
|
||||
rm -rf build
|
||||
|
||||
cleanall: clean
|
||||
rm -rf build work $(DESIGN).bit
|
||||
|
||||
bits: $(DESIGN).bit
|
||||
|
||||
#
|
||||
# Synthesis
|
||||
#
|
||||
build/project.src:
|
||||
@[ -d build ] || mkdir build
|
||||
@rm -f $@
|
||||
for i in $(SRC); do echo verilog work ../$$i >> $@; done
|
||||
for i in $(SRC_HDL); do echo VHDL work ../$$i >> $@; done
|
||||
|
||||
build/project.xst: build/project.src
|
||||
echo "run" > $@
|
||||
echo "-top $(DESIGN) " >> $@
|
||||
echo "-p $(DEVICE)" >> $@
|
||||
echo "-opt_mode Area" >> $@
|
||||
echo "-opt_level 1" >> $@
|
||||
echo "-ifn project.src" >> $@
|
||||
echo "-ifmt mixed" >> $@
|
||||
echo "-ofn project.ngc" >> $@
|
||||
echo "-ofmt NGC" >> $@
|
||||
echo "-rtlview yes" >> $@
|
||||
|
||||
build/project.ngc: build/project.xst $(SRC)
|
||||
cd build && xst -ifn project.xst -ofn project.log
|
||||
|
||||
build/project.ngd: build/project.ngc $(PINS)
|
||||
cd build && ngdbuild -p $(DEVICE) project.ngc -uc ../$(PINS)
|
||||
|
||||
build/project.ncd: build/project.ngd
|
||||
cd build && map -pr b -p $(DEVICE) project
|
||||
|
||||
build/project_r.ncd: build/project.ncd
|
||||
cd build && par -w project project_r.ncd
|
||||
|
||||
build/project_r.twr: build/project_r.ncd
|
||||
cd build && trce -v 25 project_r.ncd project.pcf
|
||||
|
||||
$(DESIGN).bit: build/project_r.ncd build/project_r.twr
|
||||
cd build && bitgen project_r.ncd -l -w $(BGFLAGS)
|
||||
@mv -f build/project_r.bit $@
|
||||
upload: $(DESIGN).bit
|
||||
LD_PRELOAD=/usr/lib/libusb-driver.so impact -batch prog.cmd
|
||||
|
||||
sim:
|
||||
cd simulation; $(SIM_CMD) -do $(DESIGN)_TB.do
|
||||
|
15
plasma/logic/_impact.cmd
Normal file
15
plasma/logic/_impact.cmd
Normal file
@ -0,0 +1,15 @@
|
||||
setMode -bs
|
||||
setMode -bs
|
||||
setCable -port auto
|
||||
Identify
|
||||
identifyMPM
|
||||
assignFile -p 1 -file "/home/cain/Embedded/plasma/work/Example/logic/plasma_3e.bit"
|
||||
Program -p 1 -defaultVersion 0
|
||||
Program -p 1 -defaultVersion 0
|
||||
Program -p 1 -defaultVersion 0
|
||||
Program -p 1 -defaultVersion 0
|
||||
assignFile -p 1 -file "/home/cain/Embedded/plasma/work/Example/logic/plasma_3e.bit"
|
||||
Program -p 1 -defaultVersion 0
|
||||
Program -p 1 -defaultVersion 0
|
||||
Program -p 1 -defaultVersion 0
|
||||
saveProjectFile -file "/home/cain/Embedded/plasma/work/Example/logic/default.ipf"
|
61
plasma/logic/alu.vhd
Normal file
61
plasma/logic/alu.vhd
Normal file
@ -0,0 +1,61 @@
|
||||
---------------------------------------------------------------------
|
||||
-- TITLE: Arithmetic Logic Unit
|
||||
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
|
||||
-- DATE CREATED: 2/8/01
|
||||
-- FILENAME: alu.vhd
|
||||
-- PROJECT: Plasma CPU core
|
||||
-- COPYRIGHT: Software placed into the public domain by the author.
|
||||
-- Software 'as is' without warranty. Author liable for nothing.
|
||||
-- DESCRIPTION:
|
||||
-- Implements the ALU.
|
||||
---------------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use work.mlite_pack.all;
|
||||
|
||||
entity alu is
|
||||
generic(alu_type : string := "DEFAULT");
|
||||
port(a_in : in std_logic_vector(31 downto 0);
|
||||
b_in : in std_logic_vector(31 downto 0);
|
||||
alu_function : in alu_function_type;
|
||||
c_alu : out std_logic_vector(31 downto 0));
|
||||
end; --alu
|
||||
|
||||
architecture logic of alu is
|
||||
signal do_add : std_logic;
|
||||
signal sum : std_logic_vector(32 downto 0);
|
||||
signal less_than : std_logic;
|
||||
begin
|
||||
|
||||
do_add <= '1' when alu_function = ALU_ADD else '0';
|
||||
sum <= bv_adder(a_in, b_in, do_add);
|
||||
less_than <= sum(32) when a_in(31) = b_in(31) or alu_function = ALU_LESS_THAN
|
||||
else a_in(31);
|
||||
|
||||
GENERIC_ALU: if alu_type = "DEFAULT" generate
|
||||
c_alu <= sum(31 downto 0) when alu_function=ALU_ADD or
|
||||
alu_function=ALU_SUBTRACT else
|
||||
ZERO(31 downto 1) & less_than when alu_function=ALU_LESS_THAN or
|
||||
alu_function=ALU_LESS_THAN_SIGNED else
|
||||
a_in or b_in when alu_function=ALU_OR else
|
||||
a_in and b_in when alu_function=ALU_AND else
|
||||
a_in xor b_in when alu_function=ALU_XOR else
|
||||
a_in nor b_in when alu_function=ALU_NOR else
|
||||
ZERO;
|
||||
end generate;
|
||||
|
||||
AREA_OPTIMIZED_ALU: if alu_type/="DEFAULT" generate
|
||||
c_alu <= sum(31 downto 0) when alu_function=ALU_ADD or
|
||||
alu_function=ALU_SUBTRACT else (others => 'Z');
|
||||
c_alu <= ZERO(31 downto 1) & less_than when alu_function=ALU_LESS_THAN or
|
||||
alu_function=ALU_LESS_THAN_SIGNED else
|
||||
(others => 'Z');
|
||||
c_alu <= a_in or b_in when alu_function=ALU_OR else (others => 'Z');
|
||||
c_alu <= a_in and b_in when alu_function=ALU_AND else (others => 'Z');
|
||||
c_alu <= a_in xor b_in when alu_function=ALU_XOR else (others => 'Z');
|
||||
c_alu <= a_in nor b_in when alu_function=ALU_NOR else (others => 'Z');
|
||||
c_alu <= ZERO when alu_function=ALU_NOTHING else (others => 'Z');
|
||||
end generate;
|
||||
|
||||
end; --architecture logic
|
||||
|
136
plasma/logic/bus_mux.vhd
Normal file
136
plasma/logic/bus_mux.vhd
Normal file
@ -0,0 +1,136 @@
|
||||
---------------------------------------------------------------------
|
||||
-- TITLE: Bus Multiplexer / Signal Router
|
||||
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
|
||||
-- DATE CREATED: 2/8/01
|
||||
-- FILENAME: bus_mux.vhd
|
||||
-- PROJECT: Plasma CPU core
|
||||
-- COPYRIGHT: Software placed into the public domain by the author.
|
||||
-- Software 'as is' without warranty. Author liable for nothing.
|
||||
-- DESCRIPTION:
|
||||
-- This entity is the main signal router.
|
||||
-- It multiplexes signals from multiple sources to the correct location.
|
||||
-- The outputs are as follows:
|
||||
-- a_bus : goes to the ALU
|
||||
-- b_bus : goes to the ALU
|
||||
-- reg_dest_out : goes to the register bank
|
||||
-- take_branch : goes to pc_next
|
||||
---------------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use work.mlite_pack.all;
|
||||
|
||||
entity bus_mux is
|
||||
port(imm_in : in std_logic_vector(15 downto 0);
|
||||
reg_source : in std_logic_vector(31 downto 0);
|
||||
a_mux : in a_source_type;
|
||||
a_out : out std_logic_vector(31 downto 0);
|
||||
|
||||
reg_target : in std_logic_vector(31 downto 0);
|
||||
b_mux : in b_source_type;
|
||||
b_out : out std_logic_vector(31 downto 0);
|
||||
|
||||
c_bus : in std_logic_vector(31 downto 0);
|
||||
c_memory : in std_logic_vector(31 downto 0);
|
||||
c_pc : in std_logic_vector(31 downto 2);
|
||||
c_pc_plus4 : in std_logic_vector(31 downto 2);
|
||||
c_mux : in c_source_type;
|
||||
reg_dest_out : out std_logic_vector(31 downto 0);
|
||||
|
||||
branch_func : in branch_function_type;
|
||||
take_branch : out std_logic);
|
||||
end; --entity bus_mux
|
||||
|
||||
architecture logic of bus_mux is
|
||||
begin
|
||||
|
||||
--Determine value of a_bus
|
||||
amux: process(reg_source, imm_in, a_mux, c_pc)
|
||||
begin
|
||||
case a_mux is
|
||||
when A_FROM_REG_SOURCE =>
|
||||
a_out <= reg_source;
|
||||
when A_FROM_IMM10_6 =>
|
||||
a_out <= ZERO(31 downto 5) & imm_in(10 downto 6);
|
||||
when A_FROM_PC =>
|
||||
a_out <= c_pc & "00";
|
||||
when others =>
|
||||
a_out <= c_pc & "00";
|
||||
end case;
|
||||
end process;
|
||||
|
||||
--Determine value of b_bus
|
||||
bmux: process(reg_target, imm_in, b_mux)
|
||||
begin
|
||||
case b_mux is
|
||||
when B_FROM_REG_TARGET =>
|
||||
b_out <= reg_target;
|
||||
when B_FROM_IMM =>
|
||||
b_out <= ZERO(31 downto 16) & imm_in;
|
||||
when B_FROM_SIGNED_IMM =>
|
||||
if imm_in(15) = '0' then
|
||||
b_out(31 downto 16) <= ZERO(31 downto 16);
|
||||
else
|
||||
b_out(31 downto 16) <= "1111111111111111";
|
||||
end if;
|
||||
b_out(15 downto 0) <= imm_in;
|
||||
when B_FROM_IMMX4 =>
|
||||
if imm_in(15) = '0' then
|
||||
b_out(31 downto 18) <= "00000000000000";
|
||||
else
|
||||
b_out(31 downto 18) <= "11111111111111";
|
||||
end if;
|
||||
b_out(17 downto 0) <= imm_in & "00";
|
||||
when others =>
|
||||
b_out <= reg_target;
|
||||
end case;
|
||||
end process;
|
||||
|
||||
--Determine value of c_bus
|
||||
cmux: process(c_bus, c_memory, c_pc, c_pc_plus4, imm_in, c_mux)
|
||||
begin
|
||||
case c_mux is
|
||||
when C_FROM_ALU => -- | C_FROM_SHIFT | C_FROM_MULT =>
|
||||
reg_dest_out <= c_bus;
|
||||
when C_FROM_MEMORY =>
|
||||
reg_dest_out <= c_memory;
|
||||
when C_FROM_PC =>
|
||||
reg_dest_out <= c_pc(31 downto 2) & "00";
|
||||
when C_FROM_PC_PLUS4 =>
|
||||
reg_dest_out <= c_pc_plus4 & "00";
|
||||
when C_FROM_IMM_SHIFT16 =>
|
||||
reg_dest_out <= imm_in & ZERO(15 downto 0);
|
||||
when others =>
|
||||
reg_dest_out <= c_bus;
|
||||
end case;
|
||||
end process;
|
||||
|
||||
--Determine value of take_branch
|
||||
pc_mux: process(branch_func, reg_source, reg_target)
|
||||
variable is_equal : std_logic;
|
||||
begin
|
||||
if reg_source = reg_target then
|
||||
is_equal := '1';
|
||||
else
|
||||
is_equal := '0';
|
||||
end if;
|
||||
case branch_func is
|
||||
when BRANCH_LTZ =>
|
||||
take_branch <= reg_source(31);
|
||||
when BRANCH_LEZ =>
|
||||
take_branch <= reg_source(31) or is_equal;
|
||||
when BRANCH_EQ =>
|
||||
take_branch <= is_equal;
|
||||
when BRANCH_NE =>
|
||||
take_branch <= not is_equal;
|
||||
when BRANCH_GEZ =>
|
||||
take_branch <= not reg_source(31);
|
||||
when BRANCH_GTZ =>
|
||||
take_branch <= not reg_source(31) and not is_equal;
|
||||
when BRANCH_YES =>
|
||||
take_branch <= '1';
|
||||
when others =>
|
||||
take_branch <= '0';
|
||||
end case;
|
||||
end process;
|
||||
|
||||
end; --architecture logic
|
175
plasma/logic/cache.vhd
Normal file
175
plasma/logic/cache.vhd
Normal file
@ -0,0 +1,175 @@
|
||||
---------------------------------------------------------------------
|
||||
-- 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.
|
||||
---------------------------------------------------------------------
|
||||
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_check : out std_logic; --Stage1: address_next in first 2MB DDR
|
||||
cache_checking : out std_logic; --Stage2: cache checking
|
||||
cache_miss : out std_logic); --Stage2-3: cache miss
|
||||
end; --cache
|
||||
|
||||
architecture logic of cache is
|
||||
subtype state_type is std_logic_vector(1 downto 0);
|
||||
constant STATE_CHECK : state_type := "00";
|
||||
constant STATE_CHECKING : state_type := "01";
|
||||
constant STATE_MISSED : state_type := "10";
|
||||
constant STATE_WRITING : 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, cache_we,
|
||||
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_CHECK =>
|
||||
cache_checking <= '0';
|
||||
cache_miss <= '0';
|
||||
state <= STATE_CHECK;
|
||||
when STATE_CHECKING =>
|
||||
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_CHECK;
|
||||
end if;
|
||||
cache_we <= '0';
|
||||
when STATE_MISSED =>
|
||||
cache_checking <= '0';
|
||||
cache_miss <= '1';
|
||||
cache_we <= '1';
|
||||
if mem_busy = '1' then
|
||||
state <= STATE_MISSED;
|
||||
else
|
||||
state <= STATE_CHECK;
|
||||
end if;
|
||||
when STATE_WRITING =>
|
||||
cache_checking <= '0';
|
||||
cache_miss <= '0';
|
||||
cache_we <= '0';
|
||||
if mem_busy = '1' then
|
||||
state <= STATE_WRITING;
|
||||
else
|
||||
state <= STATE_CHECK;
|
||||
end if;
|
||||
when others =>
|
||||
cache_checking <= '0';
|
||||
cache_miss <= '0';
|
||||
cache_we <= '0';
|
||||
state <= STATE_CHECK;
|
||||
end case; --state
|
||||
|
||||
if state = STATE_CHECK and state_reg /= STATE_MISSED then
|
||||
cache_address <= '0' & address_next(11 downto 2);
|
||||
if address_next(30 downto 21) = "0010000000" then --first 2MB of DDR
|
||||
cache_check <= '1';
|
||||
if byte_we_next = "0000" then
|
||||
cache_we <= '0';
|
||||
state_next <= STATE_CHECKING;
|
||||
else
|
||||
cache_we <= '1';
|
||||
state_next <= STATE_WRITING;
|
||||
end if;
|
||||
else
|
||||
cache_check <= '0';
|
||||
cache_we <= '0';
|
||||
state_next <= STATE_CHECK;
|
||||
end if;
|
||||
else
|
||||
cache_address <= '0' & cpu_address(11 downto 2);
|
||||
cache_check <= '0';
|
||||
state_next <= state;
|
||||
end if;
|
||||
|
||||
if byte_we_next = "0000" or byte_we_next = "1111" then
|
||||
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_CHECK;
|
||||
cache_tag_reg <= ZERO(8 downto 0);
|
||||
elsif rising_edge(clk) then
|
||||
state_reg <= state_next;
|
||||
if state = STATE_CHECK 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
|
||||
|
658
plasma/logic/code.txt
Normal file
658
plasma/logic/code.txt
Normal file
@ -0,0 +1,658 @@
|
||||
3c1c0000
|
||||
379c8a34
|
||||
3c040000
|
||||
34840a48
|
||||
3c050000
|
||||
34a50a64
|
||||
3c1d0000
|
||||
37bd0c60
|
||||
ac800000
|
||||
0085182a
|
||||
1460fffd
|
||||
24840004
|
||||
0c0001d5
|
||||
00000000
|
||||
0800000e
|
||||
23bdff98
|
||||
afa10010
|
||||
afa20014
|
||||
afa30018
|
||||
afa4001c
|
||||
afa50020
|
||||
afa60024
|
||||
afa70028
|
||||
afa8002c
|
||||
afa90030
|
||||
afaa0034
|
||||
afab0038
|
||||
afac003c
|
||||
afad0040
|
||||
afae0044
|
||||
afaf0048
|
||||
afb8004c
|
||||
afb90050
|
||||
afbf0054
|
||||
401a7000
|
||||
235afffc
|
||||
afba0058
|
||||
0000d810
|
||||
afbb005c
|
||||
0000d812
|
||||
afbb0060
|
||||
23a50000
|
||||
3c062000
|
||||
8cc40020
|
||||
8cc60010
|
||||
0c00020a
|
||||
00862024
|
||||
8fa10010
|
||||
8fa20014
|
||||
8fa30018
|
||||
8fa4001c
|
||||
8fa50020
|
||||
8fa60024
|
||||
8fa70028
|
||||
8fa8002c
|
||||
8fa90030
|
||||
8faa0034
|
||||
8fab0038
|
||||
8fac003c
|
||||
8fad0040
|
||||
8fae0044
|
||||
8faf0048
|
||||
8fb8004c
|
||||
8fb90050
|
||||
8fbf0054
|
||||
8fba0058
|
||||
8fbb005c
|
||||
03600011
|
||||
8fbb0060
|
||||
03600013
|
||||
23bd0068
|
||||
341b0001
|
||||
03400008
|
||||
409b6000
|
||||
40026000
|
||||
03e00008
|
||||
40846000
|
||||
3c050000
|
||||
24a50160
|
||||
8ca60000
|
||||
ac06003c
|
||||
8ca60004
|
||||
ac060040
|
||||
8ca60008
|
||||
ac060044
|
||||
8ca6000c
|
||||
03e00008
|
||||
ac060048
|
||||
3c1a1000
|
||||
375a003c
|
||||
03400008
|
||||
00000000
|
||||
ac900000
|
||||
ac910004
|
||||
ac920008
|
||||
ac93000c
|
||||
ac940010
|
||||
ac950014
|
||||
ac960018
|
||||
ac97001c
|
||||
ac9e0020
|
||||
ac9c0024
|
||||
ac9d0028
|
||||
ac9f002c
|
||||
03e00008
|
||||
34020000
|
||||
8c900000
|
||||
8c910004
|
||||
8c920008
|
||||
8c93000c
|
||||
8c940010
|
||||
8c950014
|
||||
8c960018
|
||||
8c97001c
|
||||
8c9e0020
|
||||
8c9c0024
|
||||
8c9d0028
|
||||
8c9f002c
|
||||
03e00008
|
||||
34a20000
|
||||
00850019
|
||||
00001012
|
||||
00002010
|
||||
03e00008
|
||||
acc40000
|
||||
3c020000
|
||||
24420a48
|
||||
a0400008
|
||||
24050007
|
||||
00403825
|
||||
3083000f
|
||||
2862000a
|
||||
10400003
|
||||
00a73021
|
||||
10000002
|
||||
24620030
|
||||
24620037
|
||||
a0c20000
|
||||
24a5ffff
|
||||
04a1fff6
|
||||
00042102
|
||||
3c020000
|
||||
03e00008
|
||||
24420a48
|
||||
3c020000
|
||||
24420a58
|
||||
a040000a
|
||||
00803025
|
||||
24050009
|
||||
00404025
|
||||
3c07cccc
|
||||
34e7cccd
|
||||
00c70019
|
||||
00a82021
|
||||
24a5ffff
|
||||
00004810
|
||||
000918c2
|
||||
00031080
|
||||
00431021
|
||||
00021040
|
||||
00c21023
|
||||
24420030
|
||||
a0820000
|
||||
04a1fff4
|
||||
00603025
|
||||
3c020000
|
||||
03e00008
|
||||
24420a58
|
||||
27bdffe0
|
||||
afbf0018
|
||||
afb10014
|
||||
afb00010
|
||||
0c000090
|
||||
00808825
|
||||
0c0001ef
|
||||
00402025
|
||||
3c040000
|
||||
0c0001ef
|
||||
24840980
|
||||
3c023b9a
|
||||
3442c9ff
|
||||
0051102b
|
||||
1040001e
|
||||
3c030004
|
||||
34634b83
|
||||
00111242
|
||||
00430019
|
||||
3c030000
|
||||
246309cc
|
||||
00002810
|
||||
000581c2
|
||||
00101080
|
||||
00431021
|
||||
8c440000
|
||||
0c0001ef
|
||||
00000000
|
||||
3c040000
|
||||
0c0001ef
|
||||
24840984
|
||||
00101140
|
||||
00501023
|
||||
00021080
|
||||
00501023
|
||||
00021100
|
||||
00501021
|
||||
000210c0
|
||||
00501023
|
||||
00021940
|
||||
00621823
|
||||
00031880
|
||||
00701821
|
||||
00031a40
|
||||
02238823
|
||||
3c0205f5
|
||||
3442e0ff
|
||||
0051102b
|
||||
10400023
|
||||
3c0255e6
|
||||
34423b89
|
||||
02220019
|
||||
3c030000
|
||||
246309cc
|
||||
00002810
|
||||
00058642
|
||||
00101080
|
||||
00431021
|
||||
8c440000
|
||||
0c0001ef
|
||||
00000000
|
||||
3c040000
|
||||
0c0001ef
|
||||
24840990
|
||||
00101040
|
||||
00501021
|
||||
00021180
|
||||
00501023
|
||||
00021080
|
||||
00501023
|
||||
00021100
|
||||
00501023
|
||||
00021140
|
||||
00501021
|
||||
00021200
|
||||
02228823
|
||||
3c02000f
|
||||
3442423f
|
||||
0051102b
|
||||
14400005
|
||||
3c020131
|
||||
3c040000
|
||||
0c0001ef
|
||||
2484099c
|
||||
3c020131
|
||||
34422cff
|
||||
0051102b
|
||||
10400021
|
||||
3c026b5f
|
||||
3442ca6b
|
||||
02220019
|
||||
3c030000
|
||||
246309cc
|
||||
00002810
|
||||
00058582
|
||||
26020014
|
||||
00021080
|
||||
00431021
|
||||
8c440000
|
||||
0c0001ef
|
||||
00000000
|
||||
0c0001de
|
||||
24040020
|
||||
00101940
|
||||
00701823
|
||||
00031180
|
||||
00431023
|
||||
000210c0
|
||||
00501021
|
||||
00021880
|
||||
00431021
|
||||
000211c0
|
||||
02228823
|
||||
3c02000f
|
||||
3442423f
|
||||
0051102b
|
||||
14400009
|
||||
3c02431b
|
||||
3c040000
|
||||
0c0001ef
|
||||
2484099c
|
||||
3c02000f
|
||||
3442423f
|
||||
0051102b
|
||||
10400017
|
||||
3c02431b
|
||||
3442de83
|
||||
02220019
|
||||
3c030000
|
||||
246309cc
|
||||
00002810
|
||||
00058482
|
||||
00101080
|
||||
00431021
|
||||
8c440000
|
||||
0c0001ef
|
||||
00000000
|
||||
3c040000
|
||||
0c0001ef
|
||||
248409a8
|
||||
00101940
|
||||
00701823
|
||||
00031180
|
||||
00431023
|
||||
000210c0
|
||||
00501021
|
||||
00021180
|
||||
02228823
|
||||
3c020001
|
||||
3442869f
|
||||
0051102b
|
||||
10400020
|
||||
3c030a7c
|
||||
34635ac5
|
||||
00111142
|
||||
00430019
|
||||
3c030000
|
||||
246309cc
|
||||
00002810
|
||||
000581c2
|
||||
00101080
|
||||
00431021
|
||||
8c440000
|
||||
0c0001ef
|
||||
00000000
|
||||
3c040000
|
||||
0c0001ef
|
||||
24840990
|
||||
00101040
|
||||
00501021
|
||||
00021980
|
||||
00431021
|
||||
00021080
|
||||
00501021
|
||||
00021080
|
||||
00501021
|
||||
00021140
|
||||
02228823
|
||||
2e2203e8
|
||||
10400005
|
||||
2e224e20
|
||||
3c040000
|
||||
0c0001ef
|
||||
248409b4
|
||||
2e224e20
|
||||
1440001f
|
||||
2e2203e8
|
||||
3c02d1b7
|
||||
34421759
|
||||
02220019
|
||||
3c030000
|
||||
246309cc
|
||||
00002810
|
||||
00058342
|
||||
26020014
|
||||
00021080
|
||||
00431021
|
||||
8c440000
|
||||
0c0001ef
|
||||
00000000
|
||||
0c0001de
|
||||
24040020
|
||||
00101080
|
||||
00501021
|
||||
000210c0
|
||||
00501023
|
||||
00021100
|
||||
00501021
|
||||
00021100
|
||||
02228823
|
||||
2e2203e8
|
||||
10400008
|
||||
3c021062
|
||||
3c040000
|
||||
0c0001ef
|
||||
248409b4
|
||||
2e2203e8
|
||||
14400017
|
||||
2e220064
|
||||
3c021062
|
||||
34424dd3
|
||||
02220019
|
||||
3c030000
|
||||
246309cc
|
||||
00002810
|
||||
00058182
|
||||
00101080
|
||||
00431021
|
||||
8c440000
|
||||
0c0001ef
|
||||
00000000
|
||||
3c040000
|
||||
0c0001ef
|
||||
248409c0
|
||||
00101140
|
||||
00501023
|
||||
00021080
|
||||
00501021
|
||||
000210c0
|
||||
02228823
|
||||
2e220064
|
||||
14400017
|
||||
2e220014
|
||||
3c0251eb
|
||||
3442851f
|
||||
02220019
|
||||
3c030000
|
||||
246309cc
|
||||
00002810
|
||||
00058142
|
||||
00101080
|
||||
00431021
|
||||
8c440000
|
||||
0c0001ef
|
||||
00000000
|
||||
3c040000
|
||||
0c0001ef
|
||||
24840990
|
||||
00101040
|
||||
00501021
|
||||
000210c0
|
||||
00501021
|
||||
00021080
|
||||
02228823
|
||||
2e220014
|
||||
14400014
|
||||
3c030000
|
||||
3c02cccc
|
||||
3442cccd
|
||||
02220019
|
||||
246309cc
|
||||
00002810
|
||||
000580c2
|
||||
26020014
|
||||
00021080
|
||||
00431021
|
||||
8c440000
|
||||
0c0001ef
|
||||
00000000
|
||||
0c0001de
|
||||
24040020
|
||||
00101080
|
||||
00501021
|
||||
00021040
|
||||
02228823
|
||||
3c030000
|
||||
246309cc
|
||||
00111080
|
||||
00431021
|
||||
8c440000
|
||||
0c0001ef
|
||||
00000000
|
||||
0c0001de
|
||||
2404000d
|
||||
0c0001de
|
||||
2404000a
|
||||
8fbf0018
|
||||
8fb10014
|
||||
8fb00010
|
||||
03e00008
|
||||
27bd0020
|
||||
27bdffe8
|
||||
afbf0014
|
||||
afb00010
|
||||
24100003
|
||||
0c0000a8
|
||||
02002025
|
||||
00101040
|
||||
1000fffc
|
||||
02028021
|
||||
3c022000
|
||||
34420020
|
||||
8c420000
|
||||
00000000
|
||||
30420002
|
||||
14400008
|
||||
3c022000
|
||||
3c032000
|
||||
34630020
|
||||
8c620000
|
||||
00000000
|
||||
30420002
|
||||
1040fffc
|
||||
3c022000
|
||||
ac440000
|
||||
03e00008
|
||||
00000000
|
||||
27bdffe0
|
||||
afb00010
|
||||
00808025
|
||||
afbf0018
|
||||
afb10014
|
||||
92020000
|
||||
00000000
|
||||
1040000d
|
||||
2411000a
|
||||
00000000
|
||||
14510003
|
||||
00000000
|
||||
0c0001de
|
||||
2404000d
|
||||
92040000
|
||||
0c0001de
|
||||
26100001
|
||||
92020000
|
||||
00000000
|
||||
1440fff5
|
||||
00000000
|
||||
8fbf0018
|
||||
8fb10014
|
||||
8fb00010
|
||||
00001025
|
||||
03e00008
|
||||
27bd0020
|
||||
27bdffe8
|
||||
afbf0010
|
||||
0c0001de
|
||||
24040049
|
||||
8fbf0010
|
||||
00000000
|
||||
03e00008
|
||||
27bd0018
|
||||
3c022000
|
||||
34420020
|
||||
8c420000
|
||||
03e00008
|
||||
30420001
|
||||
27bdffe8
|
||||
afbf0010
|
||||
0c000212
|
||||
00000000
|
||||
1040fffd
|
||||
3c022000
|
||||
8c420000
|
||||
8fbf0010
|
||||
00000000
|
||||
03e00008
|
||||
27bd0018
|
||||
00000000
|
||||
00000000
|
||||
00000000
|
||||
00000000
|
||||
00000000
|
||||
00000000
|
||||
6e696e65
|
||||
74790000
|
||||
65696768
|
||||
74790000
|
||||
73657665
|
||||
6e747900
|
||||
73697874
|
||||
79000000
|
||||
66696674
|
||||
79000000
|
||||
666f7274
|
||||
79000000
|
||||
74686972
|
||||
74790000
|
||||
7477656e
|
||||
74790000
|
||||
6e696e65
|
||||
7465656e
|
||||
00000000
|
||||
65696768
|
||||
7465656e
|
||||
00000000
|
||||
73657665
|
||||
6e746565
|
||||
6e000000
|
||||
73697874
|
||||
65656e00
|
||||
66696674
|
||||
65656e00
|
||||
666f7572
|
||||
7465656e
|
||||
00000000
|
||||
74686972
|
||||
7465656e
|
||||
00000000
|
||||
7477656c
|
||||
76650000
|
||||
656c6576
|
||||
656e0000
|
||||
74656e00
|
||||
6e696e65
|
||||
00000000
|
||||
65696768
|
||||
74000000
|
||||
73657665
|
||||
6e000000
|
||||
73697800
|
||||
66697665
|
||||
00000000
|
||||
666f7572
|
||||
00000000
|
||||
74687265
|
||||
65000000
|
||||
74776f00
|
||||
6f6e6500
|
||||
00000000
|
||||
3a200000
|
||||
2062696c
|
||||
6c696f6e
|
||||
20000000
|
||||
2068756e
|
||||
64726564
|
||||
20000000
|
||||
6d696c6c
|
||||
696f6e20
|
||||
00000000
|
||||
206d696c
|
||||
6c696f6e
|
||||
20000000
|
||||
74686f75
|
||||
73616e64
|
||||
20000000
|
||||
2074686f
|
||||
7573616e
|
||||
64200000
|
||||
0000097c
|
||||
00000978
|
||||
00000974
|
||||
0000096c
|
||||
00000964
|
||||
0000095c
|
||||
00000958
|
||||
00000950
|
||||
00000948
|
||||
00000940
|
||||
0000093c
|
||||
00000934
|
||||
0000092c
|
||||
00000920
|
||||
00000914
|
||||
0000090c
|
||||
00000904
|
||||
000008f8
|
||||
000008ec
|
||||
000008e0
|
||||
0000097c
|
||||
0000093c
|
||||
000008d8
|
||||
000008d0
|
||||
000008c8
|
||||
000008c0
|
||||
000008b8
|
||||
000008b0
|
||||
000008a8
|
||||
000008a0
|
||||
00000000
|
481
plasma/logic/control.vhd
Normal file
481
plasma/logic/control.vhd
Normal file
@ -0,0 +1,481 @@
|
||||
---------------------------------------------------------------------
|
||||
-- TITLE: Controller / Opcode Decoder
|
||||
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
|
||||
-- DATE CREATED: 2/8/01
|
||||
-- FILENAME: control.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) is a registered trademark of MIPS Technologies.
|
||||
-- MIPS Technologies does not endorse and is not associated with
|
||||
-- this project.
|
||||
-- DESCRIPTION:
|
||||
-- Controls the CPU by decoding the opcode and generating control
|
||||
-- signals to the rest of the CPU.
|
||||
-- This entity decodes the MIPS(tm) opcode into a
|
||||
-- Very-Long-Word-Instruction.
|
||||
-- The 32-bit opcode is converted to a
|
||||
-- 6+6+6+16+4+2+4+3+2+2+3+2+4 = 60 bit VLWI opcode.
|
||||
-- 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
|
||||
---------------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use work.mlite_pack.all;
|
||||
|
||||
entity control is
|
||||
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; --entity control
|
||||
|
||||
architecture logic of control is
|
||||
begin
|
||||
|
||||
control_proc: process(opcode, intr_signal)
|
||||
variable op, func : std_logic_vector(5 downto 0);
|
||||
variable rs, rt, rd : std_logic_vector(5 downto 0);
|
||||
variable rtx : std_logic_vector(4 downto 0);
|
||||
variable imm : std_logic_vector(15 downto 0);
|
||||
variable alu_function : alu_function_type;
|
||||
variable shift_function : shift_function_type;
|
||||
variable mult_function : mult_function_type;
|
||||
variable a_source : a_source_type;
|
||||
variable b_source : b_source_type;
|
||||
variable c_source : c_source_type;
|
||||
variable pc_source : pc_source_type;
|
||||
variable branch_function: branch_function_type;
|
||||
variable mem_source : mem_source_type;
|
||||
variable is_syscall : std_logic;
|
||||
begin
|
||||
alu_function := ALU_NOTHING;
|
||||
shift_function := SHIFT_NOTHING;
|
||||
mult_function := MULT_NOTHING;
|
||||
a_source := A_FROM_REG_SOURCE;
|
||||
b_source := B_FROM_REG_TARGET;
|
||||
c_source := C_FROM_NULL;
|
||||
pc_source := FROM_INC4;
|
||||
branch_function := BRANCH_EQ;
|
||||
mem_source := MEM_FETCH;
|
||||
op := opcode(31 downto 26);
|
||||
rs := '0' & opcode(25 downto 21);
|
||||
rt := '0' & opcode(20 downto 16);
|
||||
rtx := opcode(20 downto 16);
|
||||
rd := '0' & opcode(15 downto 11);
|
||||
func := opcode(5 downto 0);
|
||||
imm := opcode(15 downto 0);
|
||||
is_syscall := '0';
|
||||
|
||||
case op is
|
||||
when "000000" => --SPECIAL
|
||||
case func is
|
||||
when "000000" => --SLL r[rd]=r[rt]<<re;
|
||||
a_source := A_FROM_IMM10_6;
|
||||
c_source := C_FROM_SHIFT;
|
||||
shift_function := SHIFT_LEFT_UNSIGNED;
|
||||
|
||||
when "000010" => --SRL r[rd]=u[rt]>>re;
|
||||
a_source := A_FROM_IMM10_6;
|
||||
c_source := C_FROM_shift;
|
||||
shift_function := SHIFT_RIGHT_UNSIGNED;
|
||||
|
||||
when "000011" => --SRA r[rd]=r[rt]>>re;
|
||||
a_source := A_FROM_IMM10_6;
|
||||
c_source := C_FROM_SHIFT;
|
||||
shift_function := SHIFT_RIGHT_SIGNED;
|
||||
|
||||
when "000100" => --SLLV r[rd]=r[rt]<<r[rs];
|
||||
c_source := C_FROM_SHIFT;
|
||||
shift_function := SHIFT_LEFT_UNSIGNED;
|
||||
|
||||
when "000110" => --SRLV r[rd]=u[rt]>>r[rs];
|
||||
c_source := C_FROM_SHIFT;
|
||||
shift_function := SHIFT_RIGHT_UNSIGNED;
|
||||
|
||||
when "000111" => --SRAV r[rd]=r[rt]>>r[rs];
|
||||
c_source := C_FROM_SHIFT;
|
||||
shift_function := SHIFT_RIGHT_SIGNED;
|
||||
|
||||
when "001000" => --JR s->pc_next=r[rs];
|
||||
pc_source := FROM_BRANCH;
|
||||
alu_function := ALU_ADD;
|
||||
branch_function := BRANCH_YES;
|
||||
|
||||
when "001001" => --JALR r[rd]=s->pc_next; s->pc_next=r[rs];
|
||||
c_source := C_FROM_PC_PLUS4;
|
||||
pc_source := FROM_BRANCH;
|
||||
alu_function := ALU_ADD;
|
||||
branch_function := BRANCH_YES;
|
||||
|
||||
--when "001010" => --MOVZ if(!r[rt]) r[rd]=r[rs]; /*IV*/
|
||||
--when "001011" => --MOVN if(r[rt]) r[rd]=r[rs]; /*IV*/
|
||||
|
||||
when "001100" => --SYSCALL
|
||||
is_syscall := '1';
|
||||
|
||||
when "001101" => --BREAK s->wakeup=1;
|
||||
is_syscall := '1';
|
||||
|
||||
--when "001111" => --SYNC s->wakeup=1;
|
||||
|
||||
when "010000" => --MFHI r[rd]=s->hi;
|
||||
c_source := C_FROM_MULT;
|
||||
mult_function := MULT_READ_HI;
|
||||
|
||||
when "010001" => --FTHI s->hi=r[rs];
|
||||
mult_function := MULT_WRITE_HI;
|
||||
|
||||
when "010010" => --MFLO r[rd]=s->lo;
|
||||
c_source := C_FROM_MULT;
|
||||
mult_function := MULT_READ_LO;
|
||||
|
||||
when "010011" => --MTLO s->lo=r[rs];
|
||||
mult_function := MULT_WRITE_LO;
|
||||
|
||||
when "011000" => --MULT s->lo=r[rs]*r[rt]; s->hi=0;
|
||||
mult_function := MULT_SIGNED_MULT;
|
||||
|
||||
when "011001" => --MULTU s->lo=r[rs]*r[rt]; s->hi=0;
|
||||
mult_function := MULT_MULT;
|
||||
|
||||
when "011010" => --DIV s->lo=r[rs]/r[rt]; s->hi=r[rs]%r[rt];
|
||||
mult_function := MULT_SIGNED_DIVIDE;
|
||||
|
||||
when "011011" => --DIVU s->lo=r[rs]/r[rt]; s->hi=r[rs]%r[rt];
|
||||
mult_function := MULT_DIVIDE;
|
||||
|
||||
when "100000" => --ADD r[rd]=r[rs]+r[rt];
|
||||
c_source := C_FROM_ALU;
|
||||
alu_function := ALU_ADD;
|
||||
|
||||
when "100001" => --ADDU r[rd]=r[rs]+r[rt];
|
||||
c_source := C_FROM_ALU;
|
||||
alu_function := ALU_ADD;
|
||||
|
||||
when "100010" => --SUB r[rd]=r[rs]-r[rt];
|
||||
c_source := C_FROM_ALU;
|
||||
alu_function := ALU_SUBTRACT;
|
||||
|
||||
when "100011" => --SUBU r[rd]=r[rs]-r[rt];
|
||||
c_source := C_FROM_ALU;
|
||||
alu_function := ALU_SUBTRACT;
|
||||
|
||||
when "100100" => --AND r[rd]=r[rs]&r[rt];
|
||||
c_source := C_FROM_ALU;
|
||||
alu_function := ALU_AND;
|
||||
|
||||
when "100101" => --OR r[rd]=r[rs]|r[rt];
|
||||
c_source := C_FROM_ALU;
|
||||
alu_function := ALU_OR;
|
||||
|
||||
when "100110" => --XOR r[rd]=r[rs]^r[rt];
|
||||
c_source := C_FROM_ALU;
|
||||
alu_function := ALU_XOR;
|
||||
|
||||
when "100111" => --NOR r[rd]=~(r[rs]|r[rt]);
|
||||
c_source := C_FROM_ALU;
|
||||
alu_function := ALU_NOR;
|
||||
|
||||
when "101010" => --SLT r[rd]=r[rs]<r[rt];
|
||||
c_source := C_FROM_ALU;
|
||||
alu_function := ALU_LESS_THAN_SIGNED;
|
||||
|
||||
when "101011" => --SLTU r[rd]=u[rs]<u[rt];
|
||||
c_source := C_FROM_ALU;
|
||||
alu_function := ALU_LESS_THAN;
|
||||
|
||||
when "101101" => --DADDU r[rd]=r[rs]+u[rt];
|
||||
c_source := C_FROM_ALU;
|
||||
alu_function := ALU_ADD;
|
||||
|
||||
--when "110001" => --TGEU
|
||||
--when "110010" => --TLT
|
||||
--when "110011" => --TLTU
|
||||
--when "110100" => --TEQ
|
||||
--when "110110" => --TNE
|
||||
when others =>
|
||||
end case;
|
||||
|
||||
when "000001" => --REGIMM
|
||||
rt := "000000";
|
||||
rd := "011111";
|
||||
a_source := A_FROM_PC;
|
||||
b_source := B_FROM_IMMX4;
|
||||
alu_function := ALU_ADD;
|
||||
pc_source := FROM_BRANCH;
|
||||
branch_function := BRANCH_GTZ;
|
||||
--if(test) pc=pc+imm*4
|
||||
|
||||
case rtx is
|
||||
when "10000" => --BLTZAL r[31]=s->pc_next; branch=r[rs]<0;
|
||||
c_source := C_FROM_PC_PLUS4;
|
||||
branch_function := BRANCH_LTZ;
|
||||
|
||||
when "00000" => --BLTZ branch=r[rs]<0;
|
||||
branch_function := BRANCH_LTZ;
|
||||
|
||||
when "10001" => --BGEZAL r[31]=s->pc_next; branch=r[rs]>=0;
|
||||
c_source := C_FROM_PC_PLUS4;
|
||||
branch_function := BRANCH_GEZ;
|
||||
|
||||
when "00001" => --BGEZ branch=r[rs]>=0;
|
||||
branch_function := BRANCH_GEZ;
|
||||
|
||||
--when "10010" => --BLTZALL r[31]=s->pc_next; lbranch=r[rs]<0;
|
||||
--when "00010" => --BLTZL lbranch=r[rs]<0;
|
||||
--when "10011" => --BGEZALL r[31]=s->pc_next; lbranch=r[rs]>=0;
|
||||
--when "00011" => --BGEZL lbranch=r[rs]>=0;
|
||||
|
||||
when others =>
|
||||
end case;
|
||||
|
||||
when "000011" => --JAL r[31]=s->pc_next; s->pc_next=(s->pc&0xf0000000)|target;
|
||||
c_source := C_FROM_PC_PLUS4;
|
||||
rd := "011111";
|
||||
pc_source := FROM_OPCODE25_0;
|
||||
|
||||
when "000010" => --J s->pc_next=(s->pc&0xf0000000)|target;
|
||||
pc_source := FROM_OPCODE25_0;
|
||||
|
||||
when "000100" => --BEQ branch=r[rs]==r[rt];
|
||||
a_source := A_FROM_PC;
|
||||
b_source := B_FROM_IMMX4;
|
||||
alu_function := ALU_ADD;
|
||||
pc_source := FROM_BRANCH;
|
||||
branch_function := BRANCH_EQ;
|
||||
|
||||
when "000101" => --BNE branch=r[rs]!=r[rt];
|
||||
a_source := A_FROM_PC;
|
||||
b_source := B_FROM_IMMX4;
|
||||
alu_function := ALU_ADD;
|
||||
pc_source := FROM_BRANCH;
|
||||
branch_function := BRANCH_NE;
|
||||
|
||||
when "000110" => --BLEZ branch=r[rs]<=0;
|
||||
a_source := A_FROM_PC;
|
||||
b_source := b_FROM_IMMX4;
|
||||
alu_function := ALU_ADD;
|
||||
pc_source := FROM_BRANCH;
|
||||
branch_function := BRANCH_LEZ;
|
||||
|
||||
when "000111" => --BGTZ branch=r[rs]>0;
|
||||
a_source := A_FROM_PC;
|
||||
b_source := B_FROM_IMMX4;
|
||||
alu_function := ALU_ADD;
|
||||
pc_source := FROM_BRANCH;
|
||||
branch_function := BRANCH_GTZ;
|
||||
|
||||
when "001000" => --ADDI r[rt]=r[rs]+(short)imm;
|
||||
b_source := B_FROM_SIGNED_IMM;
|
||||
c_source := C_FROM_ALU;
|
||||
rd := rt;
|
||||
alu_function := ALU_ADD;
|
||||
|
||||
when "001001" => --ADDIU u[rt]=u[rs]+(short)imm;
|
||||
b_source := B_FROM_SIGNED_IMM;
|
||||
c_source := C_FROM_ALU;
|
||||
rd := rt;
|
||||
alu_function := ALU_ADD;
|
||||
|
||||
when "001010" => --SLTI r[rt]=r[rs]<(short)imm;
|
||||
b_source := B_FROM_SIGNED_IMM;
|
||||
c_source := C_FROM_ALU;
|
||||
rd := rt;
|
||||
alu_function := ALU_LESS_THAN_SIGNED;
|
||||
|
||||
when "001011" => --SLTIU u[rt]=u[rs]<(unsigned long)(short)imm;
|
||||
b_source := B_FROM_SIGNED_IMM;
|
||||
c_source := C_FROM_ALU;
|
||||
rd := rt;
|
||||
alu_function := ALU_LESS_THAN;
|
||||
|
||||
when "001100" => --ANDI r[rt]=r[rs]&imm;
|
||||
b_source := B_FROM_IMM;
|
||||
c_source := C_FROM_ALU;
|
||||
rd := rt;
|
||||
alu_function := ALU_AND;
|
||||
|
||||
when "001101" => --ORI r[rt]=r[rs]|imm;
|
||||
b_source := B_FROM_IMM;
|
||||
c_source := C_FROM_ALU;
|
||||
rd := rt;
|
||||
alu_function := ALU_OR;
|
||||
|
||||
when "001110" => --XORI r[rt]=r[rs]^imm;
|
||||
b_source := B_FROM_IMM;
|
||||
c_source := C_FROM_ALU;
|
||||
rd := rt;
|
||||
alu_function := ALU_XOR;
|
||||
|
||||
when "001111" => --LUI r[rt]=(imm<<16);
|
||||
c_source := C_FROM_IMM_SHIFT16;
|
||||
rd := rt;
|
||||
|
||||
when "010000" => --COP0
|
||||
alu_function := ALU_OR;
|
||||
c_source := C_FROM_ALU;
|
||||
if opcode(23) = '0' then --move from CP0
|
||||
rs := '1' & opcode(15 downto 11);
|
||||
rt := "000000";
|
||||
rd := '0' & opcode(20 downto 16);
|
||||
else --move to CP0
|
||||
rs := "000000";
|
||||
rd(5) := '1';
|
||||
pc_source := FROM_BRANCH; --delay possible interrupt
|
||||
branch_function := BRANCH_NO;
|
||||
end if;
|
||||
|
||||
--when "010001" => --COP1
|
||||
--when "010010" => --COP2
|
||||
--when "010011" => --COP3
|
||||
--when "010100" => --BEQL lbranch=r[rs]==r[rt];
|
||||
--when "010101" => --BNEL lbranch=r[rs]!=r[rt];
|
||||
--when "010110" => --BLEZL lbranch=r[rs]<=0;
|
||||
--when "010111" => --BGTZL lbranch=r[rs]>0;
|
||||
|
||||
when "100000" => --LB r[rt]=*(signed char*)ptr;
|
||||
a_source := A_FROM_REG_SOURCE;
|
||||
b_source := B_FROM_SIGNED_IMM;
|
||||
alu_function := ALU_ADD;
|
||||
rd := rt;
|
||||
c_source := C_FROM_MEMORY;
|
||||
mem_source := MEM_READ8S; --address=(short)imm+r[rs];
|
||||
|
||||
when "100001" => --LH r[rt]=*(signed short*)ptr;
|
||||
a_source := A_FROM_REG_SOURCE;
|
||||
b_source := B_FROM_SIGNED_IMM;
|
||||
alu_function := ALU_ADD;
|
||||
rd := rt;
|
||||
c_source := C_FROM_MEMORY;
|
||||
mem_source := MEM_READ16S; --address=(short)imm+r[rs];
|
||||
|
||||
when "100010" => --LWL //Not Implemented
|
||||
a_source := A_FROM_REG_SOURCE;
|
||||
b_source := B_FROM_SIGNED_IMM;
|
||||
alu_function := ALU_ADD;
|
||||
rd := rt;
|
||||
c_source := C_FROM_MEMORY;
|
||||
mem_source := MEM_READ32;
|
||||
|
||||
when "100011" => --LW r[rt]=*(long*)ptr;
|
||||
a_source := A_FROM_REG_SOURCE;
|
||||
b_source := B_FROM_SIGNED_IMM;
|
||||
alu_function := ALU_ADD;
|
||||
rd := rt;
|
||||
c_source := C_FROM_MEMORY;
|
||||
mem_source := MEM_READ32;
|
||||
|
||||
when "100100" => --LBU r[rt]=*(unsigned char*)ptr;
|
||||
a_source := A_FROM_REG_SOURCE;
|
||||
b_source := B_FROM_SIGNED_IMM;
|
||||
alu_function := ALU_ADD;
|
||||
rd := rt;
|
||||
c_source := C_FROM_MEMORY;
|
||||
mem_source := MEM_READ8; --address=(short)imm+r[rs];
|
||||
|
||||
when "100101" => --LHU r[rt]=*(unsigned short*)ptr;
|
||||
a_source := A_FROM_REG_SOURCE;
|
||||
b_source := B_FROM_SIGNED_IMM;
|
||||
alu_function := ALU_ADD;
|
||||
rd := rt;
|
||||
c_source := C_FROM_MEMORY;
|
||||
mem_source := MEM_READ16; --address=(short)imm+r[rs];
|
||||
|
||||
--when "100110" => --LWR //Not Implemented
|
||||
|
||||
when "101000" => --SB *(char*)ptr=(char)r[rt];
|
||||
a_source := A_FROM_REG_SOURCE;
|
||||
b_source := B_FROM_SIGNED_IMM;
|
||||
alu_function := ALU_ADD;
|
||||
mem_source := MEM_WRITE8; --address=(short)imm+r[rs];
|
||||
|
||||
when "101001" => --SH *(short*)ptr=(short)r[rt];
|
||||
a_source := A_FROM_REG_SOURCE;
|
||||
b_source := B_FROM_SIGNED_IMM;
|
||||
alu_function := ALU_ADD;
|
||||
mem_source := MEM_WRITE16;
|
||||
|
||||
when "101010" => --SWL //Not Implemented
|
||||
a_source := A_FROM_REG_SOURCE;
|
||||
b_source := B_FROM_SIGNED_IMM;
|
||||
alu_function := ALU_ADD;
|
||||
mem_source := MEM_WRITE32; --address=(short)imm+r[rs];
|
||||
|
||||
when "101011" => --SW *(long*)ptr=r[rt];
|
||||
a_source := A_FROM_REG_SOURCE;
|
||||
b_source := B_FROM_SIGNED_IMM;
|
||||
alu_function := ALU_ADD;
|
||||
mem_source := MEM_WRITE32; --address=(short)imm+r[rs];
|
||||
|
||||
--when "101110" => --SWR //Not Implemented
|
||||
--when "101111" => --CACHE
|
||||
--when "110000" => --LL r[rt]=*(long*)ptr;
|
||||
--when "110001" => --LWC1
|
||||
--when "110010" => --LWC2
|
||||
--when "110011" => --LWC3
|
||||
--when "110101" => --LDC1
|
||||
--when "110110" => --LDC2
|
||||
--when "110111" => --LDC3
|
||||
--when "111000" => --SC *(long*)ptr=r[rt]; r[rt]=1;
|
||||
--when "111001" => --SWC1
|
||||
--when "111010" => --SWC2
|
||||
--when "111011" => --SWC3
|
||||
--when "111101" => --SDC1
|
||||
--when "111110" => --SDC2
|
||||
--when "111111" => --SDC3
|
||||
when others =>
|
||||
end case;
|
||||
|
||||
if c_source = C_FROM_NULL then
|
||||
rd := "000000";
|
||||
end if;
|
||||
|
||||
if intr_signal = '1' or is_syscall = '1' then
|
||||
rs := "111111"; --interrupt vector
|
||||
rt := "000000";
|
||||
rd := "101110"; --save PC in EPC
|
||||
alu_function := ALU_OR;
|
||||
shift_function := SHIFT_NOTHING;
|
||||
mult_function := MULT_NOTHING;
|
||||
branch_function := BRANCH_YES;
|
||||
a_source := A_FROM_REG_SOURCE;
|
||||
b_source := B_FROM_REG_TARGET;
|
||||
c_source := C_FROM_PC;
|
||||
pc_source := FROM_LBRANCH;
|
||||
mem_source := MEM_FETCH;
|
||||
exception_out <= '1';
|
||||
else
|
||||
exception_out <= '0';
|
||||
end if;
|
||||
|
||||
rs_index <= rs;
|
||||
rt_index <= rt;
|
||||
rd_index <= rd;
|
||||
imm_out <= imm;
|
||||
alu_func <= alu_function;
|
||||
shift_func <= shift_function;
|
||||
mult_func <= mult_function;
|
||||
branch_func <= branch_function;
|
||||
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;
|
||||
|
||||
end process;
|
||||
|
||||
end; --logic
|
354
plasma/logic/ddr_ctrl.vhd
Normal file
354
plasma/logic/ddr_ctrl.vhd
Normal file
@ -0,0 +1,354 @@
|
||||
---------------------------------------------------------------------
|
||||
-- TITLE: DDR SDRAM Interface
|
||||
-- AUTHORS: Steve Rhoads (rhoadss@yahoo.com)
|
||||
-- DATE CREATED: 7/26/07
|
||||
-- FILENAME: ddr_ctrl.vhd
|
||||
-- PROJECT: Plasma CPU core
|
||||
-- COPYRIGHT: Software placed into the public domain by the author.
|
||||
-- Software 'as is' without warranty. Author liable for nothing.
|
||||
-- DESCRIPTION:
|
||||
-- Double Data Rate Sychronous Dynamic Random Access Memory Interface
|
||||
--
|
||||
-- For: 64 MB = MT46V32M16, 512Mb, 32Mb x 16 (default)
|
||||
-- ROW = address(25 downto 13)
|
||||
-- BANK = address(12 downto 11)
|
||||
-- COL = address(10 downto 2)
|
||||
--
|
||||
-- Changes are needed for 32 MB = MT46V16M16, 256Mb, 16Mb x 16
|
||||
-- ROW = address(24 downto 12) -- 25 ignored
|
||||
-- BANK = address(11 downto 10)
|
||||
-- COL = address(9 downto 2) --also change ddr_init.c
|
||||
--
|
||||
-- Changes are needed for 128 MB = MT46V64M16, 1Gb, 64Mb x 16
|
||||
-- ROW = address(26 downto 14)
|
||||
-- BANK = address(13 downto 12)
|
||||
-- COL = address(11 downto 2) --also change ddr_init.c
|
||||
--
|
||||
-- Requires CAS latency=2; burst size=2.
|
||||
-- Requires clk changes on rising_edge(clk_2x).
|
||||
-- Requires active, address, byte_we, data_w stable throughout transfer.
|
||||
-- DLL mode requires 77MHz. Non-DLL mode runs at 25 MHz.
|
||||
--
|
||||
-- cycle_cnt 777777770000111122223333444455556666777777777777
|
||||
-- clk_2x --__--__--__--__--__--__--__--__--__--__--__--__
|
||||
-- clk ____----____----____----____----____----____----
|
||||
-- SD_CLK ----____----____----____----____----____----____
|
||||
-- cmd ____write+++WRITE+++____________________________
|
||||
-- SD_DQ ~~~~~~~~~~~~~~uuuullllUUUULLLL~~~~~~~~~~~~~~~~~~
|
||||
--
|
||||
-- cycle_cnt 777777770000111122223333444455556666777777777777
|
||||
-- clk_2x --__--__--__--__--__--__--__--__--__--__--__--__
|
||||
-- clk ____----____----____----____----____----____----
|
||||
-- SD_CLK ----____----____----____----____----____----____
|
||||
-- cmd ____read++++________________________read++++____
|
||||
-- SD_DQ ~~~~~~~~~~~~~~~~~~~~~~~~uuuullll~~~~~~~~~~~~~~~~
|
||||
-- SD_DQnDLL ~~~~~~~~~~~~~~~~~~~~~~~~~~uuuullll~~~~~~~~~~~~~~
|
||||
-- pause ____------------------------________------------
|
||||
--
|
||||
-- Must run DdrInit() to initialize DDR chip.
|
||||
-- Read Micron DDR SDRAM MT46V32M16 data sheet for more details.
|
||||
---------------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
use ieee.std_logic_arith.all;
|
||||
use work.mlite_pack.all;
|
||||
|
||||
entity ddr_ctrl is
|
||||
port(
|
||||
clk : in std_logic;
|
||||
clk_2x : in std_logic;
|
||||
reset_in : in std_logic;
|
||||
|
||||
address : in std_logic_vector(25 downto 2);
|
||||
byte_we : in std_logic_vector(3 downto 0);
|
||||
data_w : in std_logic_vector(31 downto 0);
|
||||
data_r : out std_logic_vector(31 downto 0);
|
||||
active : in std_logic;
|
||||
no_start : in std_logic;
|
||||
no_stop : in std_logic;
|
||||
pause : out std_logic;
|
||||
|
||||
SD_CK_P : out std_logic; --clock_positive
|
||||
SD_CK_N : out std_logic; --clock_negative
|
||||
SD_CKE : out std_logic; --clock_enable
|
||||
|
||||
SD_BA : out std_logic_vector(1 downto 0); --bank_address
|
||||
SD_A : out std_logic_vector(12 downto 0); --address(row or col)
|
||||
SD_CS : out std_logic; --chip_select
|
||||
SD_RAS : out std_logic; --row_address_strobe
|
||||
SD_CAS : out std_logic; --column_address_strobe
|
||||
SD_WE : out std_logic; --write_enable
|
||||
|
||||
SD_DQ : inout std_logic_vector(15 downto 0); --data
|
||||
SD_UDM : out std_logic; --upper_byte_enable
|
||||
SD_UDQS : inout std_logic; --upper_data_strobe
|
||||
SD_LDM : out std_logic; --low_byte_enable
|
||||
SD_LDQS : inout std_logic); --low_data_strobe
|
||||
end; --entity ddr
|
||||
|
||||
architecture logic of ddr_ctrl is
|
||||
|
||||
--Commands for bits RAS & CAS & WE
|
||||
subtype command_type is std_logic_vector(2 downto 0);
|
||||
constant COMMAND_LMR : command_type := "000";
|
||||
constant COMMAND_AUTO_REFRESH : command_type := "001";
|
||||
constant COMMAND_PRECHARGE : command_type := "010";
|
||||
constant COMMAND_ACTIVE : command_type := "011";
|
||||
constant COMMAND_WRITE : command_type := "100";
|
||||
constant COMMAND_READ : command_type := "101";
|
||||
constant COMMAND_TERMINATE : command_type := "110";
|
||||
constant COMMAND_NOP : command_type := "111";
|
||||
|
||||
subtype ddr_state_type is std_logic_vector(3 downto 0);
|
||||
constant STATE_POWER_ON : ddr_state_type := "0000";
|
||||
constant STATE_IDLE : ddr_state_type := "0001";
|
||||
constant STATE_ROW_ACTIVATE : ddr_state_type := "0010";
|
||||
constant STATE_ROW_ACTIVE : ddr_state_type := "0011";
|
||||
constant STATE_READ : ddr_state_type := "0100";
|
||||
constant STATE_READ2 : ddr_state_type := "0101";
|
||||
constant STATE_READ3 : ddr_state_type := "0110";
|
||||
constant STATE_PRECHARGE : ddr_state_type := "0111";
|
||||
constant STATE_PRECHARGE2 : ddr_state_type := "1000";
|
||||
|
||||
signal state_prev : ddr_state_type;
|
||||
signal refresh_cnt : std_logic_vector(7 downto 0);
|
||||
signal data_write2 : std_logic_vector(47 downto 0); --write pipeline
|
||||
signal byte_we_reg2 : std_logic_vector(5 downto 0); --write pipeline
|
||||
signal write_active : std_logic;
|
||||
signal write_prev : std_logic;
|
||||
signal cycle_count : std_logic_vector(2 downto 0); --half clocks since op
|
||||
signal cycle_count2 : std_logic_vector(2 downto 0); --delayed by quarter clock
|
||||
signal cke_reg : std_logic;
|
||||
signal clk_p : std_logic;
|
||||
signal bank_open : std_logic_vector(3 downto 0);
|
||||
signal data_read : std_logic_vector(31 downto 0);
|
||||
|
||||
begin
|
||||
ddr_proc: process(clk, clk_p, clk_2x, reset_in,
|
||||
address, byte_we, data_w, active, no_start, no_stop,
|
||||
SD_DQ, SD_UDQS, SD_LDQS,
|
||||
state_prev, refresh_cnt,
|
||||
byte_we_reg2, data_write2,
|
||||
cycle_count, cycle_count2, write_prev,
|
||||
write_active, cke_reg, bank_open,
|
||||
data_read)
|
||||
type address_array_type is array(3 downto 0) of std_logic_vector(12 downto 0);
|
||||
variable address_row : address_array_type;
|
||||
variable command : std_logic_vector(2 downto 0); --RAS & CAS & WE
|
||||
variable bank_index : integer;
|
||||
variable state_current : ddr_state_type;
|
||||
|
||||
begin
|
||||
|
||||
command := COMMAND_NOP;
|
||||
bank_index := conv_integer(address(12 downto 11));
|
||||
state_current := state_prev;
|
||||
|
||||
--DDR state machine to determine state_current and command
|
||||
case state_prev is
|
||||
when STATE_POWER_ON =>
|
||||
if active = '1' then
|
||||
if byte_we /= "0000" then
|
||||
command := address(6 downto 4); --LMR="000"
|
||||
else
|
||||
state_current := STATE_IDLE; --read transistions to STATE_IDLE
|
||||
end if;
|
||||
end if;
|
||||
|
||||
when STATE_IDLE =>
|
||||
if refresh_cnt(7) = '1' then
|
||||
state_current := STATE_PRECHARGE;
|
||||
command := COMMAND_AUTO_REFRESH;
|
||||
elsif active = '1' and no_start = '0' then
|
||||
state_current := STATE_ROW_ACTIVATE;
|
||||
command := COMMAND_ACTIVE;
|
||||
end if;
|
||||
|
||||
when STATE_ROW_ACTIVATE =>
|
||||
state_current := STATE_ROW_ACTIVE;
|
||||
|
||||
when STATE_ROW_ACTIVE =>
|
||||
if refresh_cnt(7) = '1' then
|
||||
if write_prev = '0' then
|
||||
state_current := STATE_PRECHARGE;
|
||||
command := COMMAND_PRECHARGE;
|
||||
end if;
|
||||
elsif active = '1' and no_start = '0' then
|
||||
if bank_open(bank_index) = '0' then
|
||||
state_current := STATE_ROW_ACTIVATE;
|
||||
command := COMMAND_ACTIVE;
|
||||
elsif address(25 downto 13) /= address_row(bank_index) then
|
||||
if write_prev = '0' then
|
||||
state_current := STATE_PRECHARGE;
|
||||
command := COMMAND_PRECHARGE;
|
||||
end if;
|
||||
else
|
||||
if byte_we /= "0000" then
|
||||
command := COMMAND_WRITE;
|
||||
elsif write_prev = '0' then
|
||||
state_current := STATE_READ;
|
||||
command := COMMAND_READ;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
when STATE_READ =>
|
||||
state_current := STATE_READ2;
|
||||
|
||||
when STATE_READ2 =>
|
||||
state_current := STATE_READ3;
|
||||
|
||||
when STATE_READ3 =>
|
||||
if no_stop = '0' then
|
||||
state_current := STATE_ROW_ACTIVE;
|
||||
end if;
|
||||
|
||||
when STATE_PRECHARGE =>
|
||||
state_current := STATE_PRECHARGE2;
|
||||
|
||||
when STATE_PRECHARGE2 =>
|
||||
state_current := STATE_IDLE;
|
||||
|
||||
when others =>
|
||||
state_current := STATE_IDLE;
|
||||
end case; --state_prev
|
||||
|
||||
--rising_edge(clk) domain registers
|
||||
if reset_in = '1' then
|
||||
state_prev <= STATE_POWER_ON;
|
||||
cke_reg <= '0';
|
||||
refresh_cnt <= ZERO(7 downto 0);
|
||||
write_prev <= '0';
|
||||
write_active <= '0';
|
||||
bank_open <= "0000";
|
||||
elsif rising_edge(clk) then
|
||||
|
||||
if active = '1' then
|
||||
cke_reg <= '1';
|
||||
end if;
|
||||
|
||||
if command = COMMAND_WRITE then
|
||||
write_prev <= '1';
|
||||
elsif cycle_count2(2 downto 1) = "11" then
|
||||
write_prev <= '0';
|
||||
end if;
|
||||
|
||||
if command = COMMAND_WRITE then
|
||||
write_active <= '1';
|
||||
elsif cycle_count2 = "100" then
|
||||
write_active <= '0';
|
||||
end if;
|
||||
|
||||
if command = COMMAND_ACTIVE then
|
||||
bank_open(bank_index) <= '1';
|
||||
address_row(bank_index) := address(25 downto 13);
|
||||
end if;
|
||||
|
||||
if command = COMMAND_PRECHARGE then
|
||||
bank_open <= "0000";
|
||||
end if;
|
||||
|
||||
if command = COMMAND_AUTO_REFRESH then
|
||||
refresh_cnt <= ZERO(7 downto 0);
|
||||
else
|
||||
refresh_cnt <= refresh_cnt + 1;
|
||||
end if;
|
||||
|
||||
state_prev <= state_current;
|
||||
|
||||
end if; --rising_edge(clk)
|
||||
|
||||
--rising_edge(clk_2x) domain registers
|
||||
if reset_in = '1' then
|
||||
cycle_count <= "000";
|
||||
elsif rising_edge(clk_2x) then
|
||||
--Cycle_count
|
||||
if (command = COMMAND_READ or command = COMMAND_WRITE) and clk = '1' then
|
||||
cycle_count <= "000";
|
||||
elsif cycle_count /= "111" then
|
||||
cycle_count <= cycle_count + 1;
|
||||
end if;
|
||||
|
||||
clk_p <= clk; --earlier version of not clk
|
||||
|
||||
--Read data (DLL disabled)
|
||||
if cycle_count = "100" then
|
||||
data_read(31 downto 16) <= SD_DQ; --data
|
||||
elsif cycle_count = "101" then
|
||||
data_read(15 downto 0) <= SD_DQ;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
--falling_edge(clk_2x) domain registers
|
||||
if reset_in = '1' then
|
||||
cycle_count2 <= "000";
|
||||
data_write2 <= ZERO(15 downto 0) & ZERO;
|
||||
byte_we_reg2 <= "000000";
|
||||
elsif falling_edge(clk_2x) then
|
||||
cycle_count2 <= cycle_count;
|
||||
|
||||
--Write pipeline
|
||||
if clk = '0' then
|
||||
data_write2 <= data_write2(31 downto 16) & data_w;
|
||||
byte_we_reg2 <= byte_we_reg2(3 downto 2) & byte_we;
|
||||
else
|
||||
data_write2(47 downto 16) <= data_write2(31 downto 0);
|
||||
byte_we_reg2(5 downto 2) <= byte_we_reg2(3 downto 0);
|
||||
end if;
|
||||
|
||||
--Read data (DLL enabled)
|
||||
--if cycle_count = "100" then
|
||||
-- data_read(31 downto 16) <= SD_DQ; --data
|
||||
--elsif cycle_count = "101" then
|
||||
-- data_read(15 downto 0) <= SD_DQ;
|
||||
--end if;
|
||||
end if;
|
||||
|
||||
data_r <= data_read;
|
||||
|
||||
--Write data
|
||||
if write_active = '1' then
|
||||
SD_UDQS <= clk_p; --upper_data_strobe
|
||||
SD_LDQS <= clk_p; --low_data_strobe
|
||||
SD_DQ <= data_write2(47 downto 32); --data
|
||||
SD_UDM <= not byte_we_reg2(5); --upper_byte_enable
|
||||
SD_LDM <= not byte_we_reg2(4); --low_byte_enable
|
||||
else
|
||||
SD_UDQS <= 'Z'; --upper_data_strobe
|
||||
SD_LDQS <= 'Z'; --low_data_strobe
|
||||
SD_DQ <= "ZZZZZZZZZZZZZZZZ"; --data
|
||||
SD_UDM <= 'Z';
|
||||
SD_LDM <= 'Z';
|
||||
end if;
|
||||
|
||||
--DDR control signals
|
||||
SD_CK_P <= clk_p; --clock_positive
|
||||
SD_CK_N <= not clk_p; --clock_negative
|
||||
SD_CKE <= cke_reg; --clock_enable
|
||||
|
||||
SD_BA <= address(12 downto 11); --bank_address
|
||||
if command = COMMAND_ACTIVE or state_current = STATE_POWER_ON then
|
||||
SD_A <= address(25 downto 13); --address row
|
||||
elsif command = COMMAND_READ or command = COMMAND_WRITE then
|
||||
SD_A <= "000" & address(10 downto 2) & "0"; --address col
|
||||
else
|
||||
SD_A <= "0010000000000"; --PERCHARGE all banks
|
||||
end if;
|
||||
|
||||
SD_CS <= not cke_reg; --chip_select
|
||||
SD_RAS <= command(2); --row_address_strobe
|
||||
SD_CAS <= command(1); --column_address_strobe
|
||||
SD_WE <= command(0); --write_enable
|
||||
|
||||
if active = '1' and state_current /= STATE_POWER_ON and
|
||||
command /= COMMAND_WRITE and state_prev /= STATE_READ3 then
|
||||
pause <= '1';
|
||||
else
|
||||
pause <= '0';
|
||||
end if;
|
||||
|
||||
end process; --ddr_proc
|
||||
|
||||
end; --architecture logic
|
||||
|
BIN
plasma/logic/default.ipf
Normal file
BIN
plasma/logic/default.ipf
Normal file
Binary file not shown.
BIN
plasma/logic/default.ipf_ISE_Backup
Normal file
BIN
plasma/logic/default.ipf_ISE_Backup
Normal file
Binary file not shown.
183
plasma/logic/eth_dma.vhd
Normal file
183
plasma/logic/eth_dma.vhd
Normal file
@ -0,0 +1,183 @@
|
||||
---------------------------------------------------------------------
|
||||
-- TITLE: Ethernet DMA
|
||||
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
|
||||
-- DATE CREATED: 12/27/07
|
||||
-- FILENAME: eth_dma.vhd
|
||||
-- PROJECT: Plasma CPU core
|
||||
-- COPYRIGHT: Software placed into the public domain by the author.
|
||||
-- Software 'as is' without warranty. Author liable for nothing.
|
||||
-- DESCRIPTION:
|
||||
-- Ethernet DMA (Direct Memory Access) controller.
|
||||
-- Reads four bits and writes four bits from/to the Ethernet PHY each
|
||||
-- 2.5 MHz clock cycle. Received data is DMAed starting at 0x13ff0000
|
||||
-- transmit data is read from 0x13fd0000.
|
||||
-- To send a packet write bytes/4 to Ethernet send register.
|
||||
---------------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
use ieee.std_logic_arith.all;
|
||||
use work.mlite_pack.all;
|
||||
|
||||
entity eth_dma is port(
|
||||
clk : in std_logic; --25 MHz
|
||||
reset : in std_logic;
|
||||
enable_eth : in std_logic; --enable receive DMA
|
||||
select_eth : in std_logic;
|
||||
rec_isr : out std_logic; --data received
|
||||
send_isr : out std_logic; --transmit done
|
||||
|
||||
address : out std_logic_vector(31 downto 2); --to DDR
|
||||
byte_we : out std_logic_vector(3 downto 0);
|
||||
data_write : out std_logic_vector(31 downto 0);
|
||||
data_read : in std_logic_vector(31 downto 0);
|
||||
pause_in : in std_logic;
|
||||
|
||||
mem_address : in std_logic_vector(31 downto 2); --from CPU
|
||||
mem_byte_we : in std_logic_vector(3 downto 0);
|
||||
data_w : in std_logic_vector(31 downto 0);
|
||||
pause_out : out std_logic;
|
||||
|
||||
E_RX_CLK : in std_logic; --2.5 MHz receive
|
||||
E_RX_DV : in std_logic; --data valid
|
||||
E_RXD : in std_logic_vector(3 downto 0); --receive nibble
|
||||
E_TX_CLK : in std_logic; --2.5 MHz transmit
|
||||
E_TX_EN : out std_logic; --transmit enable
|
||||
E_TXD : out std_logic_vector(3 downto 0)); --transmit nibble
|
||||
end; --entity eth_dma
|
||||
|
||||
architecture logic of eth_dma is
|
||||
signal rec_clk : std_logic_vector(1 downto 0); --receive
|
||||
signal rec_store : std_logic_vector(31 downto 0); --to DDR
|
||||
signal rec_data : std_logic_vector(27 downto 0);
|
||||
signal rec_cnt : std_logic_vector(2 downto 0); --nibbles
|
||||
signal rec_words : std_logic_vector(13 downto 0);
|
||||
signal rec_dma : std_logic_vector(1 downto 0); --active & request
|
||||
signal rec_done : std_logic;
|
||||
|
||||
signal send_clk : std_logic_vector(1 downto 0); --transmit
|
||||
signal send_read : std_logic_vector(31 downto 0); --from DDR
|
||||
signal send_data : std_logic_vector(31 downto 0);
|
||||
signal send_cnt : std_logic_vector(2 downto 0); --nibbles
|
||||
signal send_words : std_logic_vector(8 downto 0);
|
||||
signal send_level : std_logic_vector(8 downto 0);
|
||||
signal send_dma : std_logic_vector(1 downto 0); --active & request
|
||||
signal send_enable: std_logic;
|
||||
|
||||
begin --architecture
|
||||
|
||||
dma_proc: process(clk, reset, enable_eth, select_eth,
|
||||
data_read, pause_in, mem_address, mem_byte_we, data_w,
|
||||
E_RX_CLK, E_RX_DV, E_RXD, E_TX_CLK,
|
||||
rec_clk, rec_store, rec_data,
|
||||
rec_cnt, rec_words, rec_dma, rec_done,
|
||||
send_clk, send_read, send_data, send_cnt, send_words,
|
||||
send_level, send_dma, send_enable)
|
||||
begin
|
||||
|
||||
if reset = '1' then
|
||||
rec_clk <= "00";
|
||||
rec_cnt <= "000";
|
||||
rec_words <= ZERO(13 downto 0);
|
||||
rec_dma <= "00";
|
||||
rec_done <= '0';
|
||||
send_clk <= "00";
|
||||
send_cnt <= "000";
|
||||
send_words <= ZERO(8 downto 0);
|
||||
send_level <= ZERO(8 downto 0);
|
||||
send_dma <= "00";
|
||||
send_enable <= '0';
|
||||
elsif rising_edge(clk) then
|
||||
|
||||
--Receive nibble on low->high E_RX_CLK. Send to DDR every 32 bits.
|
||||
rec_clk <= rec_clk(0) & E_RX_CLK;
|
||||
if rec_clk = "01" and enable_eth = '1' then
|
||||
if E_RX_DV = '1' or rec_cnt /= "000" then
|
||||
if rec_cnt = "111" then
|
||||
rec_store <= rec_data & E_RXD;
|
||||
rec_dma(0) <= '1'; --request DMA
|
||||
end if;
|
||||
rec_data <= rec_data(23 downto 0) & E_RXD;
|
||||
rec_cnt <= rec_cnt + 1;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
--Set transmit count or clear receive interrupt
|
||||
if select_eth = '1' then
|
||||
if mem_byte_we /= "0000" then
|
||||
send_cnt <= "000";
|
||||
send_words <= ZERO(8 downto 0);
|
||||
send_level <= data_w(8 downto 0);
|
||||
send_dma(0) <= '1';
|
||||
else
|
||||
rec_done <= '0';
|
||||
end if;
|
||||
end if;
|
||||
|
||||
--Transmit nibble on low->high E_TX_CLK. Get 32 bits from DDR.
|
||||
send_clk <= send_clk(0) & E_TX_CLK;
|
||||
if send_clk = "01" then
|
||||
if send_cnt = "111" then
|
||||
if send_words /= send_level then
|
||||
send_data <= send_read;
|
||||
send_dma(0) <= '1';
|
||||
send_enable <= '1';
|
||||
else
|
||||
send_enable <= '0';
|
||||
end if;
|
||||
else
|
||||
send_data(31 downto 4) <= send_data(27 downto 0);
|
||||
end if;
|
||||
send_cnt <= send_cnt + 1;
|
||||
end if;
|
||||
|
||||
--Pick which type of DMA operation: bit0 = request; bit1 = active
|
||||
if pause_in = '0' then
|
||||
if rec_dma(1) = '1' then
|
||||
rec_dma <= "00"; --DMA done
|
||||
rec_words <= rec_words + 1;
|
||||
if E_RX_DV = '0' then
|
||||
rec_done <= '1';
|
||||
end if;
|
||||
elsif send_dma(1) = '1' then
|
||||
send_dma <= "00";
|
||||
send_words <= send_words + 1;
|
||||
send_read <= data_read;
|
||||
elsif rec_dma(0) = '1' then
|
||||
rec_dma(1) <= '1'; --start DMA
|
||||
elsif send_dma(0) = '1' then
|
||||
send_dma(1) <= '1'; --start DMA
|
||||
end if;
|
||||
end if;
|
||||
|
||||
end if; --rising_edge(clk)
|
||||
|
||||
E_TXD <= send_data(31 downto 28);
|
||||
E_TX_EN <= send_enable;
|
||||
rec_isr <= rec_done;
|
||||
if send_words = send_level then
|
||||
send_isr <= '1';
|
||||
else
|
||||
send_isr <= '0';
|
||||
end if;
|
||||
|
||||
if rec_dma(1) = '1' then
|
||||
address <= "0001001111111111" & rec_words; --0x13ff0000
|
||||
byte_we <= "1111";
|
||||
data_write <= rec_store;
|
||||
pause_out <= '1'; --to CPU
|
||||
elsif send_dma(1) = '1' then
|
||||
address <= "000100111111111000000" & send_words; --0x13fe0000
|
||||
byte_we <= "0000";
|
||||
data_write <= data_w;
|
||||
pause_out <= '1';
|
||||
else
|
||||
address <= mem_address; --Send request from CPU to DDR
|
||||
byte_we <= mem_byte_we;
|
||||
data_write <= data_w;
|
||||
pause_out <= '0';
|
||||
end if;
|
||||
|
||||
end process;
|
||||
|
||||
end; --architecture logic
|
196
plasma/logic/mem_ctrl.vhd
Normal file
196
plasma/logic/mem_ctrl.vhd
Normal file
@ -0,0 +1,196 @@
|
||||
---------------------------------------------------------------------
|
||||
-- TITLE: Memory Controller
|
||||
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
|
||||
-- DATE CREATED: 1/31/01
|
||||
-- FILENAME: mem_ctrl.vhd
|
||||
-- PROJECT: Plasma CPU core
|
||||
-- COPYRIGHT: Software placed into the public domain by the author.
|
||||
-- Software 'as is' without warranty. Author liable for nothing.
|
||||
-- DESCRIPTION:
|
||||
-- Memory controller for the Plasma CPU.
|
||||
-- Supports Big or Little Endian mode.
|
||||
---------------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use work.mlite_pack.all;
|
||||
|
||||
entity mem_ctrl is
|
||||
port(clk : in std_logic;
|
||||
reset_in : in std_logic;
|
||||
pause_in : in std_logic;
|
||||
nullify_op : in std_logic;
|
||||
address_pc : in std_logic_vector(31 downto 2);
|
||||
opcode_out : out std_logic_vector(31 downto 0);
|
||||
|
||||
address_in : in std_logic_vector(31 downto 0);
|
||||
mem_source : in mem_source_type;
|
||||
data_write : in std_logic_vector(31 downto 0);
|
||||
data_read : out std_logic_vector(31 downto 0);
|
||||
pause_out : out std_logic;
|
||||
|
||||
address_next : out std_logic_vector(31 downto 2);
|
||||
byte_we_next : out std_logic_vector(3 downto 0);
|
||||
|
||||
address : out std_logic_vector(31 downto 2);
|
||||
byte_we : out std_logic_vector(3 downto 0);
|
||||
data_w : out std_logic_vector(31 downto 0);
|
||||
data_r : in std_logic_vector(31 downto 0));
|
||||
end; --entity mem_ctrl
|
||||
|
||||
architecture logic of mem_ctrl is
|
||||
--"00" = big_endian; "11" = little_endian
|
||||
constant ENDIAN_MODE : std_logic_vector(1 downto 0) := "00";
|
||||
signal opcode_reg : std_logic_vector(31 downto 0);
|
||||
signal next_opcode_reg : std_logic_vector(31 downto 0);
|
||||
signal address_reg : std_logic_vector(31 downto 2);
|
||||
signal byte_we_reg : std_logic_vector(3 downto 0);
|
||||
|
||||
signal mem_state_reg : std_logic;
|
||||
constant STATE_ADDR : std_logic := '0';
|
||||
constant STATE_ACCESS : std_logic := '1';
|
||||
|
||||
begin
|
||||
|
||||
mem_proc: process(clk, reset_in, pause_in, nullify_op,
|
||||
address_pc, address_in, mem_source, data_write,
|
||||
data_r, opcode_reg, next_opcode_reg, mem_state_reg,
|
||||
address_reg, byte_we_reg)
|
||||
variable address_var : std_logic_vector(31 downto 2);
|
||||
variable data_read_var : std_logic_vector(31 downto 0);
|
||||
variable data_write_var : std_logic_vector(31 downto 0);
|
||||
variable opcode_next : std_logic_vector(31 downto 0);
|
||||
variable byte_we_var : std_logic_vector(3 downto 0);
|
||||
variable mem_state_next : std_logic;
|
||||
variable pause_var : std_logic;
|
||||
variable bits : std_logic_vector(1 downto 0);
|
||||
begin
|
||||
byte_we_var := "0000";
|
||||
pause_var := '0';
|
||||
data_read_var := ZERO;
|
||||
data_write_var := ZERO;
|
||||
mem_state_next := mem_state_reg;
|
||||
opcode_next := opcode_reg;
|
||||
|
||||
case mem_source is
|
||||
when MEM_READ32 =>
|
||||
data_read_var := data_r;
|
||||
|
||||
when MEM_READ16 | MEM_READ16S =>
|
||||
if address_in(1) = ENDIAN_MODE(1) then
|
||||
data_read_var(15 downto 0) := data_r(31 downto 16);
|
||||
else
|
||||
data_read_var(15 downto 0) := data_r(15 downto 0);
|
||||
end if;
|
||||
if mem_source = MEM_READ16 or data_read_var(15) = '0' then
|
||||
data_read_var(31 downto 16) := ZERO(31 downto 16);
|
||||
else
|
||||
data_read_var(31 downto 16) := ONES(31 downto 16);
|
||||
end if;
|
||||
|
||||
when MEM_READ8 | MEM_READ8S =>
|
||||
bits := address_in(1 downto 0) xor ENDIAN_MODE;
|
||||
case bits is
|
||||
when "00" => data_read_var(7 downto 0) := data_r(31 downto 24);
|
||||
when "01" => data_read_var(7 downto 0) := data_r(23 downto 16);
|
||||
when "10" => data_read_var(7 downto 0) := data_r(15 downto 8);
|
||||
when others => data_read_var(7 downto 0) := data_r(7 downto 0);
|
||||
end case;
|
||||
if mem_source = MEM_READ8 or data_read_var(7) = '0' then
|
||||
data_read_var(31 downto 8) := ZERO(31 downto 8);
|
||||
else
|
||||
data_read_var(31 downto 8) := ONES(31 downto 8);
|
||||
end if;
|
||||
|
||||
when MEM_WRITE32 =>
|
||||
data_write_var := data_write;
|
||||
byte_we_var := "1111";
|
||||
|
||||
when MEM_WRITE16 =>
|
||||
data_write_var := data_write(15 downto 0) & data_write(15 downto 0);
|
||||
if address_in(1) = ENDIAN_MODE(1) then
|
||||
byte_we_var := "1100";
|
||||
else
|
||||
byte_we_var := "0011";
|
||||
end if;
|
||||
|
||||
when MEM_WRITE8 =>
|
||||
data_write_var := data_write(7 downto 0) & data_write(7 downto 0) &
|
||||
data_write(7 downto 0) & data_write(7 downto 0);
|
||||
bits := address_in(1 downto 0) xor ENDIAN_MODE;
|
||||
case bits is
|
||||
when "00" =>
|
||||
byte_we_var := "1000";
|
||||
when "01" =>
|
||||
byte_we_var := "0100";
|
||||
when "10" =>
|
||||
byte_we_var := "0010";
|
||||
when others =>
|
||||
byte_we_var := "0001";
|
||||
end case;
|
||||
|
||||
when others =>
|
||||
end case;
|
||||
|
||||
if mem_source = MEM_FETCH then --opcode fetch
|
||||
address_var := address_pc;
|
||||
opcode_next := data_r;
|
||||
mem_state_next := STATE_ADDR;
|
||||
else
|
||||
if mem_state_reg = STATE_ADDR then
|
||||
if pause_in = '0' then
|
||||
address_var := address_in(31 downto 2);
|
||||
mem_state_next := STATE_ACCESS;
|
||||
pause_var := '1';
|
||||
else
|
||||
address_var := address_pc;
|
||||
byte_we_var := "0000";
|
||||
end if;
|
||||
else --STATE_ACCESS
|
||||
if pause_in = '0' then
|
||||
address_var := address_pc;
|
||||
opcode_next := next_opcode_reg;
|
||||
mem_state_next := STATE_ADDR;
|
||||
byte_we_var := "0000";
|
||||
else
|
||||
address_var := address_in(31 downto 2);
|
||||
byte_we_var := "0000";
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
if nullify_op = '1' and pause_in = '0' then
|
||||
opcode_next := ZERO; --NOP after beql
|
||||
end if;
|
||||
|
||||
if reset_in = '1' then
|
||||
mem_state_reg <= STATE_ADDR;
|
||||
opcode_reg <= ZERO;
|
||||
next_opcode_reg <= ZERO;
|
||||
address_reg <= ZERO(31 downto 2);
|
||||
byte_we_reg <= "0000";
|
||||
elsif rising_edge(clk) then
|
||||
if pause_in = '0' then
|
||||
address_reg <= address_var;
|
||||
byte_we_reg <= byte_we_var;
|
||||
mem_state_reg <= mem_state_next;
|
||||
opcode_reg <= opcode_next;
|
||||
if mem_state_reg = STATE_ADDR then
|
||||
next_opcode_reg <= data_r;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
opcode_out <= opcode_reg;
|
||||
data_read <= data_read_var;
|
||||
pause_out <= pause_var;
|
||||
|
||||
address_next <= address_var;
|
||||
byte_we_next <= byte_we_var;
|
||||
|
||||
address <= address_reg;
|
||||
byte_we <= byte_we_reg;
|
||||
data_w <= data_write_var;
|
||||
|
||||
end process; --data_proc
|
||||
|
||||
end; --architecture logic
|
342
plasma/logic/mlite_cpu.vhd
Normal file
342
plasma/logic/mlite_cpu.vhd
Normal file
@ -0,0 +1,342 @@
|
||||
---------------------------------------------------------------------
|
||||
-- TITLE: Plasma CPU core
|
||||
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
|
||||
-- DATE CREATED: 2/15/01
|
||||
-- FILENAME: mlite_cpu.vhd
|
||||
-- PROJECT: Plasma CPU core
|
||||
-- COPYRIGHT: Software placed into the public domain by the author.
|
||||
-- Software 'as is' without warranty. Author liable for nothing.
|
||||
-- NOTE: MIPS(tm) and MIPS I(tm) are registered trademarks of MIPS
|
||||
-- Technologies. MIPS Technologies does not endorse and is not
|
||||
-- associated with this project.
|
||||
-- DESCRIPTION:
|
||||
-- Top level VHDL document that ties the nine other entities together.
|
||||
--
|
||||
-- Executes all MIPS I(tm) opcodes but exceptions and non-aligned
|
||||
-- memory accesses. Based on information found in:
|
||||
-- "MIPS RISC Architecture" by Gerry Kane and Joe Heinrich
|
||||
-- and "The Designer's Guide to VHDL" by Peter J. Ashenden
|
||||
--
|
||||
-- The CPU is implemented as a two or three stage pipeline.
|
||||
-- An add instruction would take the following steps (see cpu.gif):
|
||||
-- Stage #0:
|
||||
-- 1. The "pc_next" entity passes the program counter (PC) to the
|
||||
-- "mem_ctrl" entity which fetches the opcode from memory.
|
||||
-- Stage #1:
|
||||
-- 2. The memory returns the opcode.
|
||||
-- Stage #2:
|
||||
-- 3. "Mem_ctrl" passes the opcode to the "control" entity.
|
||||
-- 4. "Control" converts the 32-bit opcode to a 60-bit VLWI opcode
|
||||
-- and sends control signals to the other entities.
|
||||
-- 5. Based on the rs_index and rt_index control signals, "reg_bank"
|
||||
-- sends the 32-bit reg_source and reg_target to "bus_mux".
|
||||
-- 6. Based on the a_source and b_source control signals, "bus_mux"
|
||||
-- multiplexes reg_source onto a_bus and reg_target onto b_bus.
|
||||
-- Stage #3 (part of stage #2 if using two stage pipeline):
|
||||
-- 7. Based on the alu_func control signals, "alu" adds the values
|
||||
-- from a_bus and b_bus and places the result on c_bus.
|
||||
-- 8. Based on the c_source control signals, "bus_bux" multiplexes
|
||||
-- c_bus onto reg_dest.
|
||||
-- 9. Based on the rd_index control signal, "reg_bank" saves
|
||||
-- reg_dest into the correct register.
|
||||
-- Stage #3b:
|
||||
-- 10. Read or write memory if needed.
|
||||
--
|
||||
-- All signals are active high.
|
||||
-- Here are the signals for writing a character to address 0xffff
|
||||
-- when using a two stage pipeline:
|
||||
--
|
||||
-- Program:
|
||||
-- addr value opcode
|
||||
-- =============================
|
||||
-- 3c: 00000000 nop
|
||||
-- 40: 34040041 li $a0,0x41
|
||||
-- 44: 3405ffff li $a1,0xffff
|
||||
-- 48: a0a40000 sb $a0,0($a1)
|
||||
-- 4c: 00000000 nop
|
||||
-- 50: 00000000 nop
|
||||
--
|
||||
-- intr_in mem_pause
|
||||
-- reset_in byte_we Stages
|
||||
-- ns address data_w data_r 40 44 48 4c 50
|
||||
-- 3600 0 0 00000040 00000000 34040041 0 0 1
|
||||
-- 3700 0 0 00000044 00000000 3405FFFF 0 0 2 1
|
||||
-- 3800 0 0 00000048 00000000 A0A40000 0 0 2 1
|
||||
-- 3900 0 0 0000004C 41414141 00000000 0 0 2 1
|
||||
-- 4000 0 0 0000FFFC 41414141 XXXXXX41 1 0 3 2
|
||||
-- 4100 0 0 00000050 00000000 00000000 0 0 1
|
||||
---------------------------------------------------------------------
|
||||
library ieee;
|
||||
use work.mlite_pack.all;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity mlite_cpu is
|
||||
generic(memory_type : string := "XILINX_16X"; --ALTERA_LPM, or DUAL_PORT_
|
||||
mult_type : string := "DEFAULT"; --AREA_OPTIMIZED
|
||||
shifter_type : string := "DEFAULT"; --AREA_OPTIMIZED
|
||||
alu_type : string := "DEFAULT"; --AREA_OPTIMIZED
|
||||
pipeline_stages : natural := 2); --2 or 3
|
||||
port(clk : in std_logic;
|
||||
reset_in : in std_logic;
|
||||
intr_in : in std_logic;
|
||||
|
||||
address_next : out std_logic_vector(31 downto 2); --for synch ram
|
||||
byte_we_next : out std_logic_vector(3 downto 0);
|
||||
|
||||
address : out std_logic_vector(31 downto 2);
|
||||
byte_we : out std_logic_vector(3 downto 0);
|
||||
data_w : out std_logic_vector(31 downto 0);
|
||||
data_r : in std_logic_vector(31 downto 0);
|
||||
mem_pause : in std_logic);
|
||||
end; --entity mlite_cpu
|
||||
|
||||
architecture logic of mlite_cpu is
|
||||
--When using a two stage pipeline "sigD <= sig".
|
||||
--When using a three stage pipeline "sigD <= sig when rising_edge(clk)",
|
||||
-- so sigD is delayed by one clock cycle.
|
||||
signal opcode : std_logic_vector(31 downto 0);
|
||||
signal rs_index : std_logic_vector(5 downto 0);
|
||||
signal rt_index : std_logic_vector(5 downto 0);
|
||||
signal rd_index : std_logic_vector(5 downto 0);
|
||||
signal rd_indexD : std_logic_vector(5 downto 0);
|
||||
signal reg_source : std_logic_vector(31 downto 0);
|
||||
signal reg_target : std_logic_vector(31 downto 0);
|
||||
signal reg_dest : std_logic_vector(31 downto 0);
|
||||
signal reg_destD : std_logic_vector(31 downto 0);
|
||||
signal a_bus : std_logic_vector(31 downto 0);
|
||||
signal a_busD : std_logic_vector(31 downto 0);
|
||||
signal b_bus : std_logic_vector(31 downto 0);
|
||||
signal b_busD : std_logic_vector(31 downto 0);
|
||||
signal c_bus : std_logic_vector(31 downto 0);
|
||||
signal c_alu : std_logic_vector(31 downto 0);
|
||||
signal c_shift : std_logic_vector(31 downto 0);
|
||||
signal c_mult : std_logic_vector(31 downto 0);
|
||||
signal c_memory : std_logic_vector(31 downto 0);
|
||||
signal imm : std_logic_vector(15 downto 0);
|
||||
signal pc_future : std_logic_vector(31 downto 2);
|
||||
signal pc_current : std_logic_vector(31 downto 2);
|
||||
signal pc_plus4 : std_logic_vector(31 downto 2);
|
||||
signal alu_func : alu_function_type;
|
||||
signal alu_funcD : alu_function_type;
|
||||
signal shift_func : shift_function_type;
|
||||
signal shift_funcD : shift_function_type;
|
||||
signal mult_func : mult_function_type;
|
||||
signal mult_funcD : mult_function_type;
|
||||
signal branch_func : branch_function_type;
|
||||
signal take_branch : std_logic;
|
||||
signal a_source : a_source_type;
|
||||
signal b_source : b_source_type;
|
||||
signal c_source : c_source_type;
|
||||
signal pc_source : pc_source_type;
|
||||
signal mem_source : mem_source_type;
|
||||
signal pause_mult : std_logic;
|
||||
signal pause_ctrl : std_logic;
|
||||
signal pause_pipeline : std_logic;
|
||||
signal pause_any : std_logic;
|
||||
signal pause_non_ctrl : std_logic;
|
||||
signal pause_bank : std_logic;
|
||||
signal nullify_op : std_logic;
|
||||
signal intr_enable : std_logic;
|
||||
signal intr_signal : std_logic;
|
||||
signal exception_sig : std_logic;
|
||||
signal reset_reg : std_logic_vector(3 downto 0);
|
||||
signal reset : std_logic;
|
||||
begin --architecture
|
||||
|
||||
pause_any <= (mem_pause or pause_ctrl) or (pause_mult or pause_pipeline);
|
||||
pause_non_ctrl <= (mem_pause or pause_mult) or pause_pipeline;
|
||||
pause_bank <= (mem_pause or pause_ctrl or pause_mult) and not pause_pipeline;
|
||||
nullify_op <= '1' when (pc_source = FROM_LBRANCH and take_branch = '0')
|
||||
or intr_signal = '1' or exception_sig = '1'
|
||||
else '0';
|
||||
c_bus <= c_alu or c_shift or c_mult;
|
||||
reset <= '1' when reset_in = '1' or reset_reg /= "1111" else '0';
|
||||
|
||||
--synchronize reset and interrupt pins
|
||||
intr_proc: process(clk, reset_in, reset_reg, intr_in, intr_enable,
|
||||
pc_source, pc_current, pause_any)
|
||||
begin
|
||||
if reset_in = '1' then
|
||||
reset_reg <= "0000";
|
||||
intr_signal <= '0';
|
||||
elsif rising_edge(clk) then
|
||||
if reset_reg /= "1111" then
|
||||
reset_reg <= reset_reg + 1;
|
||||
end if;
|
||||
|
||||
--don't try to interrupt a multi-cycle instruction
|
||||
if pause_any = '0' then
|
||||
if intr_in = '1' and intr_enable = '1' and
|
||||
pc_source = FROM_INC4 then
|
||||
--the epc will contain pc+4
|
||||
intr_signal <= '1';
|
||||
else
|
||||
intr_signal <= '0';
|
||||
end if;
|
||||
end if;
|
||||
|
||||
end if;
|
||||
end process;
|
||||
|
||||
u1_pc_next: pc_next PORT MAP (
|
||||
clk => clk,
|
||||
reset_in => reset,
|
||||
take_branch => take_branch,
|
||||
pause_in => pause_any,
|
||||
pc_new => c_bus(31 downto 2),
|
||||
opcode25_0 => opcode(25 downto 0),
|
||||
pc_source => pc_source,
|
||||
pc_future => pc_future,
|
||||
pc_current => pc_current,
|
||||
pc_plus4 => pc_plus4);
|
||||
|
||||
u2_mem_ctrl: mem_ctrl
|
||||
PORT MAP (
|
||||
clk => clk,
|
||||
reset_in => reset,
|
||||
pause_in => pause_non_ctrl,
|
||||
nullify_op => nullify_op,
|
||||
address_pc => pc_future,
|
||||
opcode_out => opcode,
|
||||
|
||||
address_in => c_bus,
|
||||
mem_source => mem_source,
|
||||
data_write => reg_target,
|
||||
data_read => c_memory,
|
||||
pause_out => pause_ctrl,
|
||||
|
||||
address_next => address_next,
|
||||
byte_we_next => byte_we_next,
|
||||
|
||||
address => address,
|
||||
byte_we => byte_we,
|
||||
data_w => data_w,
|
||||
data_r => data_r);
|
||||
|
||||
u3_control: control PORT MAP (
|
||||
opcode => opcode,
|
||||
intr_signal => intr_signal,
|
||||
rs_index => rs_index,
|
||||
rt_index => rt_index,
|
||||
rd_index => rd_index,
|
||||
imm_out => imm,
|
||||
alu_func => alu_func,
|
||||
shift_func => shift_func,
|
||||
mult_func => mult_func,
|
||||
branch_func => branch_func,
|
||||
a_source_out => a_source,
|
||||
b_source_out => b_source,
|
||||
c_source_out => c_source,
|
||||
pc_source_out=> pc_source,
|
||||
mem_source_out=> mem_source,
|
||||
exception_out=> exception_sig);
|
||||
|
||||
u4_reg_bank: reg_bank
|
||||
generic map(memory_type => memory_type)
|
||||
port map (
|
||||
clk => clk,
|
||||
reset_in => reset,
|
||||
pause => pause_bank,
|
||||
rs_index => rs_index,
|
||||
rt_index => rt_index,
|
||||
rd_index => rd_indexD,
|
||||
reg_source_out => reg_source,
|
||||
reg_target_out => reg_target,
|
||||
reg_dest_new => reg_destD,
|
||||
intr_enable => intr_enable);
|
||||
|
||||
u5_bus_mux: bus_mux port map (
|
||||
imm_in => imm,
|
||||
reg_source => reg_source,
|
||||
a_mux => a_source,
|
||||
a_out => a_bus,
|
||||
|
||||
reg_target => reg_target,
|
||||
b_mux => b_source,
|
||||
b_out => b_bus,
|
||||
|
||||
c_bus => c_bus,
|
||||
c_memory => c_memory,
|
||||
c_pc => pc_current,
|
||||
c_pc_plus4 => pc_plus4,
|
||||
c_mux => c_source,
|
||||
reg_dest_out => reg_dest,
|
||||
|
||||
branch_func => branch_func,
|
||||
take_branch => take_branch);
|
||||
|
||||
u6_alu: alu
|
||||
generic map (alu_type => alu_type)
|
||||
port map (
|
||||
a_in => a_busD,
|
||||
b_in => b_busD,
|
||||
alu_function => alu_funcD,
|
||||
c_alu => c_alu);
|
||||
|
||||
u7_shifter: shifter
|
||||
generic map (shifter_type => shifter_type)
|
||||
port map (
|
||||
value => b_busD,
|
||||
shift_amount => a_busD(4 downto 0),
|
||||
shift_func => shift_funcD,
|
||||
c_shift => c_shift);
|
||||
|
||||
u8_mult: mult
|
||||
generic map (mult_type => mult_type)
|
||||
port map (
|
||||
clk => clk,
|
||||
reset_in => reset,
|
||||
a => a_busD,
|
||||
b => b_busD,
|
||||
mult_func => mult_funcD,
|
||||
c_mult => c_mult,
|
||||
pause_out => pause_mult);
|
||||
|
||||
pipeline2: if pipeline_stages <= 2 generate
|
||||
a_busD <= a_bus;
|
||||
b_busD <= b_bus;
|
||||
alu_funcD <= alu_func;
|
||||
shift_funcD <= shift_func;
|
||||
mult_funcD <= mult_func;
|
||||
rd_indexD <= rd_index;
|
||||
reg_destD <= reg_dest;
|
||||
pause_pipeline <= '0';
|
||||
end generate; --pipeline2
|
||||
|
||||
pipeline3: if pipeline_stages > 2 generate
|
||||
--When operating in three stage pipeline mode, the following signals
|
||||
--are delayed by one clock cycle: a_bus, b_bus, alu/shift/mult_func,
|
||||
--c_source, and rd_index.
|
||||
u9_pipeline: pipeline port map (
|
||||
clk => clk,
|
||||
reset => reset,
|
||||
a_bus => a_bus,
|
||||
a_busD => a_busD,
|
||||
b_bus => b_bus,
|
||||
b_busD => b_busD,
|
||||
alu_func => alu_func,
|
||||
alu_funcD => alu_funcD,
|
||||
shift_func => shift_func,
|
||||
shift_funcD => shift_funcD,
|
||||
mult_func => mult_func,
|
||||
mult_funcD => mult_funcD,
|
||||
reg_dest => reg_dest,
|
||||
reg_destD => reg_destD,
|
||||
rd_index => rd_index,
|
||||
rd_indexD => rd_indexD,
|
||||
|
||||
rs_index => rs_index,
|
||||
rt_index => rt_index,
|
||||
pc_source => pc_source,
|
||||
mem_source => mem_source,
|
||||
a_source => a_source,
|
||||
b_source => b_source,
|
||||
c_source => c_source,
|
||||
c_bus => c_bus,
|
||||
pause_any => pause_any,
|
||||
pause_pipeline => pause_pipeline);
|
||||
|
||||
end generate; --pipeline3
|
||||
|
||||
end; --architecture logic
|
542
plasma/logic/mlite_pack.vhd
Normal file
542
plasma/logic/mlite_pack.vhd
Normal file
@ -0,0 +1,542 @@
|
||||
---------------------------------------------------------------------
|
||||
-- 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;
|
||||
|
||||
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_check : out std_logic; --Stage1: address_next in first 2MB DDR
|
||||
cache_checking : out std_logic; --Stage2: cache checking
|
||||
cache_miss : out std_logic); --Stage2-3: 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
|
||||
|
||||
|
208
plasma/logic/mult.vhd
Normal file
208
plasma/logic/mult.vhd
Normal file
@ -0,0 +1,208 @@
|
||||
---------------------------------------------------------------------
|
||||
-- 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;
|
||||
sign_reg <= a(31);
|
||||
else
|
||||
aa_reg <= a_neg;
|
||||
bb_reg <= b_neg;
|
||||
sign_reg <= a_neg(31);
|
||||
end if;
|
||||
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
|
71
plasma/logic/pc_next.vhd
Normal file
71
plasma/logic/pc_next.vhd
Normal file
@ -0,0 +1,71 @@
|
||||
---------------------------------------------------------------------
|
||||
-- TITLE: Program Counter Next
|
||||
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
|
||||
-- DATE CREATED: 2/8/01
|
||||
-- FILENAME: pc_next.vhd
|
||||
-- PROJECT: Plasma CPU core
|
||||
-- COPYRIGHT: Software placed into the public domain by the author.
|
||||
-- Software 'as is' without warranty. Author liable for nothing.
|
||||
-- DESCRIPTION:
|
||||
-- Implements the Program Counter logic.
|
||||
---------------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use work.mlite_pack.all;
|
||||
|
||||
entity pc_next is
|
||||
port(clk : in std_logic;
|
||||
reset_in : in std_logic;
|
||||
pc_new : in std_logic_vector(31 downto 2);
|
||||
take_branch : in std_logic;
|
||||
pause_in : in std_logic;
|
||||
opcode25_0 : in std_logic_vector(25 downto 0);
|
||||
pc_source : in pc_source_type;
|
||||
pc_future : out std_logic_vector(31 downto 2);
|
||||
pc_current : out std_logic_vector(31 downto 2);
|
||||
pc_plus4 : out std_logic_vector(31 downto 2));
|
||||
end; --pc_next
|
||||
|
||||
architecture logic of pc_next is
|
||||
signal pc_reg : std_logic_vector(31 downto 2);
|
||||
begin
|
||||
|
||||
pc_select: process(clk, reset_in, pc_new, take_branch, pause_in,
|
||||
opcode25_0, pc_source, pc_reg)
|
||||
variable pc_inc : std_logic_vector(31 downto 2);
|
||||
variable pc_next : std_logic_vector(31 downto 2);
|
||||
begin
|
||||
pc_inc := bv_increment(pc_reg); --pc_reg+1
|
||||
|
||||
case pc_source is
|
||||
when FROM_INC4 =>
|
||||
pc_next := pc_inc;
|
||||
when FROM_OPCODE25_0 =>
|
||||
pc_next := pc_reg(31 downto 28) & opcode25_0;
|
||||
when FROM_BRANCH | FROM_LBRANCH =>
|
||||
if take_branch = '1' then
|
||||
pc_next := pc_new;
|
||||
else
|
||||
pc_next := pc_inc;
|
||||
end if;
|
||||
when others =>
|
||||
pc_next := pc_inc;
|
||||
end case;
|
||||
|
||||
if pause_in = '1' then
|
||||
pc_next := pc_reg;
|
||||
end if;
|
||||
|
||||
if reset_in = '1' then
|
||||
pc_reg <= ZERO(31 downto 2);
|
||||
pc_next := pc_reg;
|
||||
elsif rising_edge(clk) then
|
||||
pc_reg <= pc_next;
|
||||
end if;
|
||||
|
||||
pc_future <= pc_next;
|
||||
pc_current <= pc_reg;
|
||||
pc_plus4 <= pc_inc;
|
||||
end process;
|
||||
|
||||
end; --logic
|
139
plasma/logic/pipeline.vhd
Normal file
139
plasma/logic/pipeline.vhd
Normal file
@ -0,0 +1,139 @@
|
||||
---------------------------------------------------------------------
|
||||
-- TITLE: Pipeline
|
||||
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
|
||||
-- DATE CREATED: 6/24/02
|
||||
-- FILENAME: pipeline.vhd
|
||||
-- PROJECT: Plasma CPU core
|
||||
-- COPYRIGHT: Software placed into the public domain by the author.
|
||||
-- Software 'as is' without warranty. Author liable for nothing.
|
||||
-- DESCRIPTION:
|
||||
-- Controls the three stage pipeline by delaying the signals:
|
||||
-- a_bus, b_bus, alu/shift/mult_func, c_source, and rs_index.
|
||||
---------------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use work.mlite_pack.all;
|
||||
|
||||
--Note: sigD <= sig after rising_edge(clk)
|
||||
entity pipeline is
|
||||
port(clk : in std_logic;
|
||||
reset : in std_logic;
|
||||
a_bus : in std_logic_vector(31 downto 0);
|
||||
a_busD : out std_logic_vector(31 downto 0);
|
||||
b_bus : in std_logic_vector(31 downto 0);
|
||||
b_busD : out std_logic_vector(31 downto 0);
|
||||
alu_func : in alu_function_type;
|
||||
alu_funcD : out alu_function_type;
|
||||
shift_func : in shift_function_type;
|
||||
shift_funcD : out shift_function_type;
|
||||
mult_func : in mult_function_type;
|
||||
mult_funcD : out mult_function_type;
|
||||
reg_dest : in std_logic_vector(31 downto 0);
|
||||
reg_destD : out std_logic_vector(31 downto 0);
|
||||
rd_index : in std_logic_vector(5 downto 0);
|
||||
rd_indexD : out std_logic_vector(5 downto 0);
|
||||
|
||||
rs_index : in std_logic_vector(5 downto 0);
|
||||
rt_index : in std_logic_vector(5 downto 0);
|
||||
pc_source : in pc_source_type;
|
||||
mem_source : in mem_source_type;
|
||||
a_source : in a_source_type;
|
||||
b_source : in b_source_type;
|
||||
c_source : in c_source_type;
|
||||
c_bus : in std_logic_vector(31 downto 0);
|
||||
pause_any : in std_logic;
|
||||
pause_pipeline : out std_logic);
|
||||
end; --entity pipeline
|
||||
|
||||
architecture logic of pipeline is
|
||||
signal rd_index_reg : std_logic_vector(5 downto 0);
|
||||
signal reg_dest_reg : std_logic_vector(31 downto 0);
|
||||
signal reg_dest_delay : std_logic_vector(31 downto 0);
|
||||
signal c_source_reg : c_source_type;
|
||||
signal pause_enable_reg : std_logic;
|
||||
begin
|
||||
|
||||
--When operating in three stage pipeline mode, the following signals
|
||||
--are delayed by one clock cycle: a_bus, b_bus, alu/shift/mult_func,
|
||||
--c_source, and rd_index.
|
||||
pipeline3: process(clk, reset, a_bus, b_bus, alu_func, shift_func, mult_func,
|
||||
rd_index, rd_index_reg, pause_any, pause_enable_reg,
|
||||
rs_index, rt_index,
|
||||
pc_source, mem_source, a_source, b_source, c_source, c_source_reg,
|
||||
reg_dest, reg_dest_reg, reg_dest_delay, c_bus)
|
||||
variable pause_mult_clock : std_logic;
|
||||
variable freeze_pipeline : std_logic;
|
||||
begin
|
||||
if (pc_source /= FROM_INC4 and pc_source /= FROM_OPCODE25_0) or
|
||||
mem_source /= MEM_FETCH or
|
||||
(mult_func = MULT_READ_LO or mult_func = MULT_READ_HI) then
|
||||
pause_mult_clock := '1';
|
||||
else
|
||||
pause_mult_clock := '0';
|
||||
end if;
|
||||
|
||||
freeze_pipeline := not (pause_mult_clock and pause_enable_reg) and pause_any;
|
||||
pause_pipeline <= pause_mult_clock and pause_enable_reg;
|
||||
rd_indexD <= rd_index_reg;
|
||||
|
||||
-- The value written back into the register bank, signal reg_dest is tricky.
|
||||
-- If reg_dest comes from the ALU via the signal c_bus, it is already delayed
|
||||
-- into stage #3, because a_busD and b_busD are delayed. If reg_dest comes from
|
||||
-- c_memory, pc_current, or pc_plus4 then reg_dest hasn't yet been delayed into
|
||||
-- stage #3.
|
||||
-- Instead of delaying c_memory, pc_current, and pc_plus4, these signals
|
||||
-- are multiplexed into reg_dest which is then delayed. The decision to use
|
||||
-- the already delayed c_bus or the delayed value of reg_dest (reg_dest_reg) is
|
||||
-- based on a delayed value of c_source (c_source_reg).
|
||||
|
||||
if c_source_reg = C_FROM_ALU then
|
||||
reg_dest_delay <= c_bus; --delayed by 1 clock cycle via a_busD & b_busD
|
||||
else
|
||||
reg_dest_delay <= reg_dest_reg; --need to delay 1 clock cycle from reg_dest
|
||||
end if;
|
||||
reg_destD <= reg_dest_delay;
|
||||
|
||||
if reset = '1' then
|
||||
a_busD <= ZERO;
|
||||
b_busD <= ZERO;
|
||||
alu_funcD <= ALU_NOTHING;
|
||||
shift_funcD <= SHIFT_NOTHING;
|
||||
mult_funcD <= MULT_NOTHING;
|
||||
reg_dest_reg <= ZERO;
|
||||
c_source_reg <= "000";
|
||||
rd_index_reg <= "000000";
|
||||
pause_enable_reg <= '0';
|
||||
elsif rising_edge(clk) then
|
||||
if freeze_pipeline = '0' then
|
||||
if (rs_index = "000000" or rs_index /= rd_index_reg) or
|
||||
(a_source /= A_FROM_REG_SOURCE or pause_enable_reg = '0') then
|
||||
a_busD <= a_bus;
|
||||
else
|
||||
a_busD <= reg_dest_delay; --rs from previous operation (bypass stage)
|
||||
end if;
|
||||
|
||||
if (rt_index = "000000" or rt_index /= rd_index_reg) or
|
||||
(b_source /= B_FROM_REG_TARGET or pause_enable_reg = '0') then
|
||||
b_busD <= b_bus;
|
||||
else
|
||||
b_busD <= reg_dest_delay; --rt from previous operation
|
||||
end if;
|
||||
|
||||
alu_funcD <= alu_func;
|
||||
shift_funcD <= shift_func;
|
||||
mult_funcD <= mult_func;
|
||||
reg_dest_reg <= reg_dest;
|
||||
c_source_reg <= c_source;
|
||||
rd_index_reg <= rd_index;
|
||||
end if;
|
||||
|
||||
if pause_enable_reg = '0' and pause_any = '0' then
|
||||
pause_enable_reg <= '1'; --enable pause_pipeline
|
||||
elsif pause_mult_clock = '1' then
|
||||
pause_enable_reg <= '0'; --disable pause_pipeline
|
||||
end if;
|
||||
end if;
|
||||
|
||||
end process; --pipeline3
|
||||
|
||||
end; --logic
|
301
plasma/logic/plasma.vhd
Normal file
301
plasma/logic/plasma.vhd
Normal file
@ -0,0 +1,301 @@
|
||||
---------------------------------------------------------------------
|
||||
-- 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_check : 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 --DDR in use
|
||||
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_check <= '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_check => cache_check, --Stage1: address_next in first 2MB DDR
|
||||
cache_checking => cache_checking, --Stage2
|
||||
cache_miss => cache_miss); --Stage3
|
||||
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_enable <= '1' when address_next(30 downto 28) = "000" or
|
||||
cache_check = '1' or cache_miss = '1' else '0';
|
||||
ram_byte_we <= byte_we_next when cache_miss = '0' else "1111";
|
||||
ram_address(31 downto 13) <= ZERO(31 downto 13);
|
||||
ram_address(12 downto 2) <= (address_next(12) or cache_check) & address_next(11 downto 2)
|
||||
when cache_miss = '0' else
|
||||
'1' & cpu_address(11 downto 2); --Update cache after cache miss
|
||||
ram_data_w <= cpu_data_w when cache_miss = '0' else data_read;
|
||||
|
||||
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
|
||||
|
279
plasma/logic/plasma_3e.ucf
Normal file
279
plasma/logic/plasma_3e.ucf
Normal file
@ -0,0 +1,279 @@
|
||||
#####################################################
|
||||
### SPARTAN-3E STARTER KIT BOARD CONSTRAINTS FILE
|
||||
#####################################################
|
||||
# ==== Analog-to-Digital Converter (ADC) ====
|
||||
# some connections shared with SPI Flash, DAC, ADC, and AMP
|
||||
#NET "AD_CONV" LOC = "P11" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 6 ;
|
||||
# ==== Programmable Gain Amplifier (AMP) ====
|
||||
# some connections shared with SPI Flash, DAC, ADC, and AMP
|
||||
#NET "AMP_CS" LOC = "N7" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 6 ;
|
||||
#NET "AMP_DOUT" LOC = "E18" | IOSTANDARD = LVCMOS33 ;
|
||||
#NET "AMP_SHDN" LOC = "P7" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 6 ;
|
||||
# ==== Pushbuttons (BTN) ====
|
||||
NET "BTN_EAST" LOC = "H13" | IOSTANDARD = LVTTL | PULLDOWN ;
|
||||
NET "BTN_NORTH" LOC = "V4" | IOSTANDARD = LVTTL | PULLDOWN ;
|
||||
NET "BTN_SOUTH" LOC = "K17" | IOSTANDARD = LVTTL | PULLDOWN ;
|
||||
NET "BTN_WEST" LOC = "D18" | IOSTANDARD = LVTTL | PULLDOWN ;
|
||||
# ==== Clock inputs (CLK) ====
|
||||
NET "CLK_50MHZ" LOC = "C9" | IOSTANDARD = LVCMOS33 ;
|
||||
# Define clock period for 50 MHz oscillator (40%/60% duty-cycle)
|
||||
NET "CLK_50MHZ" PERIOD = 20 ns HIGH 40 %;
|
||||
#NET "CLK_AUX" LOC = "B8" | IOSTANDARD = LVCMOS33 ;
|
||||
#NET "CLK_SMA" LOC = "A10" | IOSTANDARD = LVCMOS33 ;
|
||||
# ==== Digital-to-Analog Converter (DAC) ====
|
||||
# some connections shared with SPI Flash, DAC, ADC, and AMP
|
||||
#NET "DAC_CLR" LOC = "P8" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ;
|
||||
#NET "DAC_CS" LOC = "N8" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ;
|
||||
# ==== 1-Wire Secure EEPROM (DS)
|
||||
#NET "DS_WIRE" LOC = "U4" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 ;
|
||||
# ==== Ethernet PHY (E) ====
|
||||
#NET "E_COL" LOC = "U6" | IOSTANDARD = LVCMOS33 ;
|
||||
#NET "E_CRS" LOC = "U13" | IOSTANDARD = LVCMOS33 ;
|
||||
NET "E_MDC" LOC = "P9" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ;
|
||||
NET "E_MDIO" LOC = "U5" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ;
|
||||
NET "E_RX_CLK" LOC = "V3" | IOSTANDARD = LVCMOS33 ;
|
||||
NET "E_RX_DV" LOC = "V2" | IOSTANDARD = LVCMOS33 ;
|
||||
NET "E_RXD<0>" LOC = "V8" | IOSTANDARD = LVCMOS33 ;
|
||||
NET "E_RXD<1>" LOC = "T11" | IOSTANDARD = LVCMOS33 ;
|
||||
NET "E_RXD<2>" LOC = "U11" | IOSTANDARD = LVCMOS33 ;
|
||||
NET "E_RXD<3>" LOC = "V14" | IOSTANDARD = LVCMOS33 ;
|
||||
#NET "E_RXD<4>" LOC = "U14" | IOSTANDARD = LVCMOS33 ;
|
||||
NET "E_TX_CLK" LOC = "T7" | IOSTANDARD = LVCMOS33 ;
|
||||
NET "E_TX_EN" LOC = "P15" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ;
|
||||
NET "E_TXD<0>" LOC = "R11" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ;
|
||||
NET "E_TXD<1>" LOC = "T15" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ;
|
||||
NET "E_TXD<2>" LOC = "R5" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ;
|
||||
NET "E_TXD<3>" LOC = "T5" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ;
|
||||
#NET "E_TXD<4>" LOC = "R6" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ;
|
||||
# ==== FPGA Configuration Mode, INIT_B Pins (FPGA) ====
|
||||
#NET "FPGA_M0" LOC = "M10" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ;
|
||||
#NET "FPGA_M1" LOC = "V11" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ;
|
||||
#NET "FPGA_M2" LOC = "T10" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ;
|
||||
#NET "FPGA_INIT_B" LOC = "T3" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 4 ;
|
||||
#NET "FPGA_RDWR_B" LOC = "U10" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 4 ;
|
||||
#NET "FPGA_HSWAP" LOC = "B3" | IOSTANDARD = LVCMOS33 ;
|
||||
# ==== FX2 Connector (FX2) ====
|
||||
#NET "FX2_CLKIN" LOC = "E10" | IOSTANDARD = LVCMOS33 ;
|
||||
#NET "FX2_CLKIO" LOC = "D9" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
|
||||
#NET "FX2_CLKOUT" LOC = "D10" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
|
||||
# These four connections are shared with the J1 6-pin accessory header
|
||||
#NET "FX2_IO<1>" LOC = "B4" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
|
||||
#NET "FX2_IO<2>" LOC = "A4" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
|
||||
#NET "FX2_IO<3>" LOC = "D5" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
|
||||
#NET "FX2_IO<4>" LOC = "C5" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
|
||||
# These four connections are shared with the J2 6-pin accessory header
|
||||
#NET "FX2_IO<5>" LOC = "A6" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
|
||||
#NET "FX2_IO<6>" LOC = "B6" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
|
||||
#NET "FX2_IO<7>" LOC = "E7" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
|
||||
#NET "FX2_IO<8>" LOC = "F7" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
|
||||
# These four connections are shared with the J4 6-pin accessory header
|
||||
#NET "FX2_IO<9>" LOC = "D7" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
|
||||
#NET "FX2_IO<10>" LOC = "C7" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
|
||||
#NET "FX2_IO<11>" LOC = "F8" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
|
||||
#NET "FX2_IO<12>" LOC = "E8" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
|
||||
# The discrete LEDs are shared with the following 8 FX2 connections
|
||||
#NET "FX2_IO<13>" LOC = "F9" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
|
||||
#NET "FX2_IO<14>" LOC = "E9" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
|
||||
#NET "FX2_IO<15>" LOC = "D11" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
|
||||
#NET "FX2_IO<16>" LOC = "C11" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
|
||||
#NET "FX2_IO<17>" LOC = "F11" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
|
||||
#NET "FX2_IO<18>" LOC = "E11" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
|
||||
#NET "FX2_IO<19>" LOC = "E12" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
|
||||
#NET "FX2_IO<20>" LOC = "F12" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
|
||||
#NET "FX2_IO<21>" LOC = "A13" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
|
||||
#NET "FX2_IO<22>" LOC = "B13" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
|
||||
#NET "FX2_IO<23>" LOC = "A14" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
|
||||
#NET "FX2_IO<24>" LOC = "B14" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
|
||||
#NET "FX2_IO<25>" LOC = "C14" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
|
||||
#NET "FX2_IO<26>" LOC = "D14" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
|
||||
#NET "FX2_IO<27>" LOC = "A16" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
|
||||
#NET "FX2_IO<28>" LOC = "B16" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
|
||||
#NET "FX2_IO<29>" LOC = "E13" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
|
||||
#NET "FX2_IO<30>" LOC = "C4" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
|
||||
#NET "FX2_IO<31>" LOC = "B11" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
|
||||
#NET "FX2_IO<32>" LOC = "A11" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
|
||||
#NET "FX2_IO<33>" LOC = "A8" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
|
||||
#NET "FX2_IO<34>" LOC = "G9" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
|
||||
#NET "FX2_IP<35>" LOC = "D12" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
|
||||
#NET "FX2_IP<36>" LOC = "C12" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
|
||||
#NET "FX2_IP<37>" LOC = "A15" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
|
||||
#NET "FX2_IP<38>" LOC = "B15" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
|
||||
#NET "FX2_IO<39>" LOC = "C3" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
|
||||
#NET "FX2_IP<40>" LOC = "C15" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
|
||||
# ==== 6-pin header J1 ====
|
||||
# These are shared connections with the FX2 connector
|
||||
#NET "J1<0>" LOC = "B4" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 6 ;
|
||||
#NET "J1<1>" LOC = "A4" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 6 ;
|
||||
#NET "J1<2>" LOC = "D5" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 6 ;
|
||||
#NET "J1<3>" LOC = "C5" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 6 ;
|
||||
# ==== 6-pin header J2 ====
|
||||
# These are shared connections with the FX2 connector
|
||||
#NET "J2<0>" LOC = "A6" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 6 ;
|
||||
#NET "J2<1>" LOC = "B6" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 6 ;
|
||||
#NET "J2<2>" LOC = "E7" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 6 ;
|
||||
#NET "J2<3>" LOC = "F7" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 6 ;
|
||||
# ==== 6-pin header J4 ====
|
||||
# These are shared connections with the FX2 connector
|
||||
#NET "J4<0>" LOC = "D7" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 6 ;
|
||||
#NET "J4<1>" LOC = "C7" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 6 ;
|
||||
#NET "J4<2>" LOC = "F8" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 6 ;
|
||||
#NET "J4<3>" LOC = "E8" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 6 ;
|
||||
# ==== Character LCD (LCD) ====
|
||||
#NET "LCD_E" LOC = "M18" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
|
||||
#NET "LCD_RS" LOC = "L18" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
|
||||
#NET "LCD_RW" LOC = "L17" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
|
||||
# LCD data connections are shared with StrataFlash connections SF_D<11:8>
|
||||
#NET "SF_D<8>" LOC = "R15" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
|
||||
#NET "SF_D<9>" LOC = "R16" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
|
||||
#NET "SF_D<10>" LOC = "P17" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
|
||||
#NET "SF_D<11>" LOC = "M15" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
|
||||
# ==== Discrete LEDs (LED) ====
|
||||
# These are shared connections with the FX2 connector
|
||||
NET "LED<0>" LOC = "F12" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 ;
|
||||
NET "LED<1>" LOC = "E12" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 ;
|
||||
NET "LED<2>" LOC = "E11" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 ;
|
||||
NET "LED<3>" LOC = "F11" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 ;
|
||||
NET "LED<4>" LOC = "C11" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 ;
|
||||
NET "LED<5>" LOC = "D11" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 ;
|
||||
NET "LED<6>" LOC = "E9" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 ;
|
||||
NET "LED<7>" LOC = "F9" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 ;
|
||||
# ==== PS/2 Mouse/Keyboard Port (PS2) ====
|
||||
NET "PS2_CLK" LOC = "G14" | IOSTANDARD = LVCMOS33 ;
|
||||
NET "PS2_DATA" LOC = "G13" | IOSTANDARD = LVCMOS33 ;
|
||||
# ==== Rotary Pushbutton Switch (ROT) ====
|
||||
NET "ROT_A" LOC = "K18" | IOSTANDARD = LVTTL | PULLUP ;
|
||||
NET "ROT_B" LOC = "G18" | IOSTANDARD = LVTTL | PULLUP ;
|
||||
NET "ROT_CENTER" LOC = "V16" | IOSTANDARD = LVTTL | PULLDOWN ;
|
||||
# ==== RS-232 Serial Ports (RS232) ====
|
||||
NET "RS232_DCE_RXD" LOC = "R7" | IOSTANDARD = LVTTL ;
|
||||
NET "RS232_DCE_TXD" LOC = "M14" | IOSTANDARD = LVTTL | DRIVE = 8 | SLEW = SLOW ;
|
||||
#NET "RS232_DTE_RXD" LOC = "U8" | IOSTANDARD = LVTTL ;
|
||||
#NET "RS232_DTE_TXD" LOC = "M13" | IOSTANDARD = LVTTL | DRIVE = 8 | SLEW = SLOW ;
|
||||
# ==== DDR SDRAM (SD) ==== (I/O Bank 3, VCCO=2.5V)
|
||||
NET "SD_A<0>" LOC = "T1" | IOSTANDARD = SSTL2_I ;
|
||||
NET "SD_A<1>" LOC = "R3" | IOSTANDARD = SSTL2_I ;
|
||||
NET "SD_A<2>" LOC = "R2" | IOSTANDARD = SSTL2_I ;
|
||||
NET "SD_A<3>" LOC = "P1" | IOSTANDARD = SSTL2_I ;
|
||||
NET "SD_A<4>" LOC = "F4" | IOSTANDARD = SSTL2_I ;
|
||||
NET "SD_A<5>" LOC = "H4" | IOSTANDARD = SSTL2_I ;
|
||||
NET "SD_A<6>" LOC = "H3" | IOSTANDARD = SSTL2_I ;
|
||||
NET "SD_A<7>" LOC = "H1" | IOSTANDARD = SSTL2_I ;
|
||||
NET "SD_A<8>" LOC = "H2" | IOSTANDARD = SSTL2_I ;
|
||||
NET "SD_A<9>" LOC = "N4" | IOSTANDARD = SSTL2_I ;
|
||||
NET "SD_A<10>" LOC = "T2" | IOSTANDARD = SSTL2_I ;
|
||||
NET "SD_A<11>" LOC = "N5" | IOSTANDARD = SSTL2_I ;
|
||||
NET "SD_A<12>" LOC = "P2" | IOSTANDARD = SSTL2_I ;
|
||||
NET "SD_BA<0>" LOC = "K5" | IOSTANDARD = SSTL2_I ;
|
||||
NET "SD_BA<1>" LOC = "K6" | IOSTANDARD = SSTL2_I ;
|
||||
NET "SD_CAS" LOC = "C2" | IOSTANDARD = SSTL2_I ;
|
||||
NET "SD_CK_N" LOC = "J4" | IOSTANDARD = SSTL2_I ;
|
||||
NET "SD_CK_P" LOC = "J5" | IOSTANDARD = SSTL2_I ;
|
||||
NET "SD_CKE" LOC = "K3" | IOSTANDARD = SSTL2_I ;
|
||||
NET "SD_CS" LOC = "K4" | IOSTANDARD = SSTL2_I ;
|
||||
NET "SD_DQ<0>" LOC = "L2" | IOSTANDARD = SSTL2_I ;
|
||||
NET "SD_DQ<1>" LOC = "L1" | IOSTANDARD = SSTL2_I ;
|
||||
NET "SD_DQ<2>" LOC = "L3" | IOSTANDARD = SSTL2_I ;
|
||||
NET "SD_DQ<3>" LOC = "L4" | IOSTANDARD = SSTL2_I ;
|
||||
NET "SD_DQ<4>" LOC = "M3" | IOSTANDARD = SSTL2_I ;
|
||||
NET "SD_DQ<5>" LOC = "M4" | IOSTANDARD = SSTL2_I ;
|
||||
NET "SD_DQ<6>" LOC = "M5" | IOSTANDARD = SSTL2_I ;
|
||||
NET "SD_DQ<7>" LOC = "M6" | IOSTANDARD = SSTL2_I ;
|
||||
NET "SD_DQ<8>" LOC = "E2" | IOSTANDARD = SSTL2_I ;
|
||||
NET "SD_DQ<9>" LOC = "E1" | IOSTANDARD = SSTL2_I ;
|
||||
NET "SD_DQ<10>" LOC = "F1" | IOSTANDARD = SSTL2_I ;
|
||||
NET "SD_DQ<11>" LOC = "F2" | IOSTANDARD = SSTL2_I ;
|
||||
NET "SD_DQ<12>" LOC = "G6" | IOSTANDARD = SSTL2_I ;
|
||||
NET "SD_DQ<13>" LOC = "G5" | IOSTANDARD = SSTL2_I ;
|
||||
NET "SD_DQ<14>" LOC = "H6" | IOSTANDARD = SSTL2_I ;
|
||||
NET "SD_DQ<15>" LOC = "H5" | IOSTANDARD = SSTL2_I ;
|
||||
NET "SD_LDM" LOC = "J2" | IOSTANDARD = SSTL2_I ;
|
||||
NET "SD_LDQS" LOC = "L6" | IOSTANDARD = SSTL2_I ;
|
||||
NET "SD_RAS" LOC = "C1" | IOSTANDARD = SSTL2_I ;
|
||||
NET "SD_UDM" LOC = "J1" | IOSTANDARD = SSTL2_I ;
|
||||
NET "SD_UDQS" LOC = "G3" | IOSTANDARD = SSTL2_I ;
|
||||
NET "SD_WE" LOC = "D1" | IOSTANDARD = SSTL2_I ;
|
||||
# Path to allow connection to top DCM connection
|
||||
#NET "SD_CK_FB" LOC = "B9" | IOSTANDARD = LVCMOS33 ;
|
||||
# Prohibit VREF pins
|
||||
CONFIG PROHIBIT = D2;
|
||||
CONFIG PROHIBIT = G4;
|
||||
CONFIG PROHIBIT = J6;
|
||||
CONFIG PROHIBIT = L5;
|
||||
CONFIG PROHIBIT = R4;
|
||||
# ==== Intel StrataFlash Parallel NOR Flash (SF) ====
|
||||
NET "SF_A<0>" LOC = "H17" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
|
||||
NET "SF_A<1>" LOC = "J13" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
|
||||
NET "SF_A<2>" LOC = "J12" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
|
||||
NET "SF_A<3>" LOC = "J14" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
|
||||
NET "SF_A<4>" LOC = "J15" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
|
||||
NET "SF_A<5>" LOC = "J16" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
|
||||
NET "SF_A<6>" LOC = "J17" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
|
||||
NET "SF_A<7>" LOC = "K14" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
|
||||
NET "SF_A<8>" LOC = "K15" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
|
||||
NET "SF_A<9>" LOC = "K12" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
|
||||
NET "SF_A<10>" LOC = "K13" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
|
||||
NET "SF_A<11>" LOC = "L15" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
|
||||
NET "SF_A<12>" LOC = "L16" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
|
||||
NET "SF_A<13>" LOC = "T18" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
|
||||
NET "SF_A<14>" LOC = "R18" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
|
||||
NET "SF_A<15>" LOC = "T17" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
|
||||
NET "SF_A<16>" LOC = "U18" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
|
||||
NET "SF_A<17>" LOC = "T16" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
|
||||
NET "SF_A<18>" LOC = "U15" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
|
||||
NET "SF_A<19>" LOC = "V15" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
|
||||
NET "SF_A<20>" LOC = "T12" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
|
||||
NET "SF_A<21>" LOC = "V13" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
|
||||
NET "SF_A<22>" LOC = "V12" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
|
||||
NET "SF_A<23>" LOC = "N11" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
|
||||
NET "SF_A<24>" LOC = "A11" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
|
||||
NET "SF_BYTE" LOC = "C17" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
|
||||
NET "SF_CE0" LOC = "D16" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
|
||||
NET "SF_D<1>" LOC = "P10" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
|
||||
NET "SF_D<2>" LOC = "R10" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
|
||||
NET "SF_D<3>" LOC = "V9" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
|
||||
NET "SF_D<4>" LOC = "U9" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
|
||||
NET "SF_D<5>" LOC = "R9" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
|
||||
NET "SF_D<6>" LOC = "M9" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
|
||||
NET "SF_D<7>" LOC = "N9" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
|
||||
NET "SF_D<8>" LOC = "R15" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
|
||||
NET "SF_D<9>" LOC = "R16" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
|
||||
NET "SF_D<10>" LOC = "P17" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
|
||||
NET "SF_D<11>" LOC = "M15" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
|
||||
NET "SF_D<12>" LOC = "M16" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
|
||||
NET "SF_D<13>" LOC = "P6" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
|
||||
NET "SF_D<14>" LOC = "R8" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
|
||||
NET "SF_D<15>" LOC = "T8" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
|
||||
NET "SF_OE" LOC = "C18" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
|
||||
NET "SF_STS" LOC = "B18" | IOSTANDARD = LVCMOS33 ;
|
||||
NET "SF_WE" LOC = "D17" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
|
||||
# ==== STMicro SPI serial Flash (SPI) ====
|
||||
# some connections shared with SPI Flash, DAC, ADC, and AMP
|
||||
NET "SPI_MISO" LOC = "N10" | IOSTANDARD = LVCMOS33 ;
|
||||
#NET "SPI_MOSI" LOC = "T4" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 6 ;
|
||||
#NET "SPI_SCK" LOC = "U16" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 6 ;
|
||||
#NET "SPI_SS_B" LOC = "U3" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 6 ;
|
||||
#NET "SPI_ALT_CS_JP11" LOC = "R12" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 6 ;
|
||||
# ==== Slide Switches (SW) ====
|
||||
NET "SW<0>" LOC = "L13" | IOSTANDARD = LVTTL | PULLUP ;
|
||||
NET "SW<1>" LOC = "L14" | IOSTANDARD = LVTTL | PULLUP ;
|
||||
NET "SW<2>" LOC = "H18" | IOSTANDARD = LVTTL | PULLUP ;
|
||||
NET "SW<3>" LOC = "N17" | IOSTANDARD = LVTTL | PULLUP ;
|
||||
# ==== VGA Port (VGA) ====
|
||||
NET "VGA_BLUE" LOC = "G15" | IOSTANDARD = LVTTL | DRIVE = 8 | SLEW = FAST ;
|
||||
NET "VGA_GREEN" LOC = "H15" | IOSTANDARD = LVTTL | DRIVE = 8 | SLEW = FAST ;
|
||||
NET "VGA_HSYNC" LOC = "F15" | IOSTANDARD = LVTTL | DRIVE = 8 | SLEW = FAST ;
|
||||
NET "VGA_RED" LOC = "H14" | IOSTANDARD = LVTTL | DRIVE = 8 | SLEW = FAST ;
|
||||
NET "VGA_VSYNC" LOC = "F14" | IOSTANDARD = LVTTL | DRIVE = 8 | SLEW = FAST ;
|
||||
# ==== Xilinx CPLD (XC) ====
|
||||
#NET "XC_CMD<0>" LOC = "P18" | IOSTANDARD = LVTTL | DRIVE = 4 | SLEW = SLOW ;
|
||||
#NET "XC_CMD<1>" LOC = "N18" | IOSTANDARD = LVTTL | DRIVE = 4 | SLEW = SLOW ;
|
||||
#NET "XC_CPLD_EN" LOC = "B10" | IOSTANDARD = LVTTL ;
|
||||
#NET "XC_D<0>" LOC = "G16" | IOSTANDARD = LVTTL | DRIVE = 4 | SLEW = SLOW ;
|
||||
#NET "XC_D<1>" LOC = "F18" | IOSTANDARD = LVTTL | DRIVE = 4 | SLEW = SLOW ;
|
||||
#NET "XC_D<2>" LOC = "F17" | IOSTANDARD = LVTTL | DRIVE = 4 | SLEW = SLOW ;
|
||||
#NET "XC_TRIG" LOC = "R17" | IOSTANDARD = LVCMOS33 ;
|
||||
#NET "XC_GCK0" LOC = "H16" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
|
||||
#NET "GCLK10" LOC = "C9" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
|
||||
NET "CLK_50MHZ" TNM_NET = "CLK_50MHZ";
|
||||
NET "clk_reg1" TNM_NET = "clk_reg1";
|
||||
TIMESPEC "TS_clk_reg1" = PERIOD "clk_reg1" 40 ns HIGH 50 %;
|
277
plasma/logic/plasma_3e.vhd
Normal file
277
plasma/logic/plasma_3e.vhd
Normal file
@ -0,0 +1,277 @@
|
||||
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
|
||||
|
111
plasma/logic/plasma_if.ucf
Normal file
111
plasma/logic/plasma_if.ucf
Normal file
@ -0,0 +1,111 @@
|
||||
NET "clk_in" TNM_NET = "clk_in";
|
||||
TIMESPEC "TS_clk_in" = PERIOD "clk_in" 20 ns HIGH 50 %;
|
||||
#NET "clk_reg1" TNM_NET = "clk_reg1";
|
||||
#TIMESPEC "TS_clk_reg1" = PERIOD "clk_reg1" 40 ns HIGH 50 %;
|
||||
NET "clk_reg1" TNM_NET = "clk_reg1";
|
||||
TIMESPEC "TS_clk_reg1" = PERIOD "clk_reg1" 39.9 ns HIGH 50 %;
|
||||
#PACE: Start of Constraints generated by PACE
|
||||
#PACE: Start of PACE I/O Pin Assignments
|
||||
NET "clk_in" LOC = "T9";
|
||||
NET "gpio0_out<0>" LOC = "K12";
|
||||
NET "gpio0_out<10>" LOC = "N15";
|
||||
NET "gpio0_out<11>" LOC = "P15";
|
||||
NET "gpio0_out<12>" LOC = "R16";
|
||||
NET "gpio0_out<13>" LOC = "F13";
|
||||
NET "gpio0_out<14>" LOC = "N16";
|
||||
NET "gpio0_out<15>" LOC = "P16";
|
||||
NET "gpio0_out<16>" LOC = "E13";
|
||||
NET "gpio0_out<17>" LOC = "F14";
|
||||
NET "gpio0_out<18>" LOC = "G14";
|
||||
NET "gpio0_out<19>" LOC = "D14";
|
||||
NET "gpio0_out<1>" LOC = "P14";
|
||||
NET "gpio0_out<24>" LOC = "R12";
|
||||
NET "gpio0_out<25>" LOC = "T12";
|
||||
NET "gpio0_out<26>" LOC = "R11";
|
||||
NET "gpio0_out<27>" LOC = "R9";
|
||||
NET "gpio0_out<28>" LOC = "T10";
|
||||
NET "gpio0_out<2>" LOC = "L12";
|
||||
NET "gpio0_out<3>" LOC = "N14";
|
||||
NET "gpio0_out<4>" LOC = "P13";
|
||||
NET "gpio0_out<5>" LOC = "N12";
|
||||
NET "gpio0_out<6>" LOC = "P12";
|
||||
NET "gpio0_out<7>" LOC = "P11";
|
||||
NET "gpio0_out<8>" LOC = "E14";
|
||||
NET "gpio0_out<9>" LOC = "G13";
|
||||
NET "gpioA_in<0>" LOC = "F12";
|
||||
NET "gpioA_in<10>" LOC = "L13";
|
||||
NET "gpioA_in<1>" LOC = "G12";
|
||||
NET "gpioA_in<2>" LOC = "H14";
|
||||
NET "gpioA_in<30>" LOC = "M15";
|
||||
NET "gpioA_in<31>" LOC = "M16";
|
||||
NET "gpioA_in<3>" LOC = "H13";
|
||||
NET "gpioA_in<4>" LOC = "J14";
|
||||
NET "gpioA_in<5>" LOC = "J13";
|
||||
NET "gpioA_in<6>" LOC = "K14";
|
||||
NET "gpioA_in<7>" LOC = "K13";
|
||||
NET "gpioA_in<8>" LOC = "M13";
|
||||
NET "gpioA_in<9>" LOC = "M14";
|
||||
NET "ram_address<10>" LOC = "E3";
|
||||
NET "ram_address<11>" LOC = "E4";
|
||||
NET "ram_address<12>" LOC = "G5";
|
||||
NET "ram_address<13>" LOC = "H3";
|
||||
NET "ram_address<14>" LOC = "H4";
|
||||
NET "ram_address<15>" LOC = "J4";
|
||||
NET "ram_address<16>" LOC = "J3";
|
||||
NET "ram_address<17>" LOC = "K3";
|
||||
NET "ram_address<18>" LOC = "K5";
|
||||
NET "ram_address<19>" LOC = "L3";
|
||||
NET "ram_address<2>" LOC = "L5";
|
||||
NET "ram_address<3>" LOC = "N3";
|
||||
NET "ram_address<4>" LOC = "M4";
|
||||
NET "ram_address<5>" LOC = "M3";
|
||||
NET "ram_address<6>" LOC = "L4";
|
||||
NET "ram_address<7>" LOC = "G4";
|
||||
NET "ram_address<8>" LOC = "F3";
|
||||
NET "ram_address<9>" LOC = "F4";
|
||||
NET "ram_ce1_n" LOC = "P7";
|
||||
NET "ram_ce2_n" LOC = "N5";
|
||||
NET "ram_data<0>" LOC = "P2";
|
||||
NET "ram_data<10>" LOC = "G1";
|
||||
NET "ram_data<11>" LOC = "F5";
|
||||
NET "ram_data<12>" LOC = "C3";
|
||||
NET "ram_data<13>" LOC = "K2";
|
||||
NET "ram_data<14>" LOC = "M1";
|
||||
NET "ram_data<15>" LOC = "N1";
|
||||
NET "ram_data<16>" LOC = "N7";
|
||||
NET "ram_data<17>" LOC = "T8";
|
||||
NET "ram_data<18>" LOC = "R6";
|
||||
NET "ram_data<19>" LOC = "T5";
|
||||
NET "ram_data<1>" LOC = "N2";
|
||||
NET "ram_data<20>" LOC = "R5";
|
||||
NET "ram_data<21>" LOC = "C2";
|
||||
NET "ram_data<22>" LOC = "C1";
|
||||
NET "ram_data<23>" LOC = "B1";
|
||||
NET "ram_data<24>" LOC = "D3";
|
||||
NET "ram_data<25>" LOC = "P8";
|
||||
NET "ram_data<26>" LOC = "F2";
|
||||
NET "ram_data<27>" LOC = "H1";
|
||||
NET "ram_data<28>" LOC = "J2";
|
||||
NET "ram_data<29>" LOC = "L2";
|
||||
NET "ram_data<2>" LOC = "M2";
|
||||
NET "ram_data<30>" LOC = "P1";
|
||||
NET "ram_data<31>" LOC = "R1";
|
||||
NET "ram_data<3>" LOC = "K1";
|
||||
NET "ram_data<4>" LOC = "J1";
|
||||
NET "ram_data<5>" LOC = "G2";
|
||||
NET "ram_data<6>" LOC = "E1";
|
||||
NET "ram_data<7>" LOC = "D1";
|
||||
NET "ram_data<8>" LOC = "D2";
|
||||
NET "ram_data<9>" LOC = "E2";
|
||||
NET "ram_lb1_n" LOC = "P6";
|
||||
NET "ram_lb2_n" LOC = "P5";
|
||||
NET "ram_oe_n" LOC = "K4";
|
||||
NET "ram_ub1_n" LOC = "T4";
|
||||
NET "ram_ub2_n" LOC = "R4";
|
||||
NET "ram_we_n" LOC = "G3";
|
||||
NET "reset" LOC = "L14";
|
||||
NET "uart_read" LOC = "T13";
|
||||
NET "uart_write" LOC = "R13";
|
||||
#PACE: Start of PACE Area Constraints
|
||||
#PACE: Start of PACE Prohibit Constraints
|
||||
#PACE: End of Constraints generated by PACE
|
152
plasma/logic/plasma_if.vhd
Normal file
152
plasma/logic/plasma_if.vhd
Normal file
@ -0,0 +1,152 @@
|
||||
---------------------------------------------------------------------
|
||||
-- TITLE: Plamsa Interface (clock divider and interface to FPGA board)
|
||||
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
|
||||
-- DATE CREATED: 6/6/02
|
||||
-- FILENAME: plasma_if.vhd
|
||||
-- PROJECT: Plasma CPU core
|
||||
-- COPYRIGHT: Software placed into the public domain by the author.
|
||||
-- Software 'as is' without warranty. Author liable for nothing.
|
||||
-- DESCRIPTION:
|
||||
-- This entity divides the clock by two and interfaces to the
|
||||
-- Altera EP20K200EFC484-2X FPGA board.
|
||||
-- Xilinx Spartan-3 XC3S200FT256-4 FPGA.
|
||||
---------------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
--use work.mlite_pack.all;
|
||||
|
||||
entity plasma_if is
|
||||
port(clk_in : in std_logic;
|
||||
reset : in std_logic;
|
||||
uart_read : in std_logic;
|
||||
uart_write : out std_logic;
|
||||
|
||||
ram_address : out std_logic_vector(31 downto 2);
|
||||
ram_data : inout std_logic_vector(31 downto 0);
|
||||
ram_ce1_n : out std_logic;
|
||||
ram_ub1_n : out std_logic;
|
||||
ram_lb1_n : out std_logic;
|
||||
ram_ce2_n : out std_logic;
|
||||
ram_ub2_n : out std_logic;
|
||||
ram_lb2_n : out std_logic;
|
||||
ram_we_n : out std_logic;
|
||||
ram_oe_n : out std_logic;
|
||||
|
||||
gpio0_out : out std_logic_vector(31 downto 0);
|
||||
gpioA_in : in std_logic_vector(31 downto 0));
|
||||
end; --entity plasma_if
|
||||
|
||||
|
||||
architecture logic of plasma_if is
|
||||
|
||||
component plasma
|
||||
generic(memory_type : string := "XILINX_16X"; --"DUAL_PORT_" "ALTERA_LPM";
|
||||
log_file : string := "UNUSED");
|
||||
port(clk : in std_logic;
|
||||
reset : in std_logic;
|
||||
uart_write : out std_logic;
|
||||
uart_read : in std_logic;
|
||||
|
||||
address : out std_logic_vector(31 downto 2);
|
||||
byte_we : out std_logic_vector(3 downto 0);
|
||||
data_write : out std_logic_vector(31 downto 0);
|
||||
data_read : in std_logic_vector(31 downto 0);
|
||||
mem_pause_in : in std_logic;
|
||||
|
||||
gpio0_out : out std_logic_vector(31 downto 0);
|
||||
gpioA_in : in std_logic_vector(31 downto 0));
|
||||
end component; --plasma
|
||||
|
||||
signal clk_reg : std_logic;
|
||||
signal we_n_next : std_logic;
|
||||
signal we_n_reg : std_logic;
|
||||
signal mem_address : std_logic_vector(31 downto 2);
|
||||
signal data_write : std_logic_vector(31 downto 0);
|
||||
signal data_reg : std_logic_vector(31 downto 0);
|
||||
signal byte_we : std_logic_vector(3 downto 0);
|
||||
signal mem_pause_in : std_logic;
|
||||
|
||||
begin --architecture
|
||||
--Divide 50 MHz clock by two
|
||||
clk_div: process(reset, clk_in, clk_reg, we_n_next)
|
||||
begin
|
||||
if reset = '1' then
|
||||
clk_reg <= '0';
|
||||
elsif rising_edge(clk_in) then
|
||||
clk_reg <= not clk_reg;
|
||||
end if;
|
||||
|
||||
if reset = '1' then
|
||||
we_n_reg <= '1';
|
||||
data_reg <= (others => '0');
|
||||
elsif falling_edge(clk_in) then
|
||||
we_n_reg <= we_n_next or not clk_reg;
|
||||
data_reg <= ram_data;
|
||||
end if;
|
||||
end process; --clk_div
|
||||
|
||||
mem_pause_in <= '0';
|
||||
ram_address <= mem_address(31 downto 2);
|
||||
ram_we_n <= we_n_reg;
|
||||
|
||||
--For Xilinx Spartan-3 Starter Kit
|
||||
ram_control:
|
||||
process(clk_reg, mem_address, byte_we, data_write)
|
||||
begin
|
||||
if mem_address(30 downto 28) = "001" then --RAM
|
||||
ram_ce1_n <= '0';
|
||||
ram_ce2_n <= '0';
|
||||
if byte_we = "0000" then --read
|
||||
ram_data <= (others => 'Z');
|
||||
ram_ub1_n <= '0';
|
||||
ram_lb1_n <= '0';
|
||||
ram_ub2_n <= '0';
|
||||
ram_lb2_n <= '0';
|
||||
we_n_next <= '1';
|
||||
ram_oe_n <= '0';
|
||||
else --write
|
||||
if clk_reg = '1' then
|
||||
ram_data <= (others => 'Z');
|
||||
else
|
||||
ram_data <= data_write;
|
||||
end if;
|
||||
ram_ub1_n <= not byte_we(3);
|
||||
ram_lb1_n <= not byte_we(2);
|
||||
ram_ub2_n <= not byte_we(1);
|
||||
ram_lb2_n <= not byte_we(0);
|
||||
we_n_next <= '0';
|
||||
ram_oe_n <= '1';
|
||||
end if;
|
||||
else
|
||||
ram_data <= (others => 'Z');
|
||||
ram_ce1_n <= '1';
|
||||
ram_ub1_n <= '1';
|
||||
ram_lb1_n <= '1';
|
||||
ram_ce2_n <= '1';
|
||||
ram_ub2_n <= '1';
|
||||
ram_lb2_n <= '1';
|
||||
we_n_next <= '1';
|
||||
ram_oe_n <= '1';
|
||||
end if;
|
||||
end process; --ram_control
|
||||
|
||||
u1_plama: plasma
|
||||
generic map (memory_type => "XILINX_16X",
|
||||
log_file => "UNUSED")
|
||||
PORT MAP (
|
||||
clk => clk_reg,
|
||||
reset => reset,
|
||||
uart_write => uart_write,
|
||||
uart_read => uart_read,
|
||||
|
||||
address => mem_address,
|
||||
byte_we => byte_we,
|
||||
data_write => data_write,
|
||||
data_read => data_reg,
|
||||
mem_pause_in => mem_pause_in,
|
||||
|
||||
gpio0_out => gpio0_out,
|
||||
gpioA_in => gpioA_in);
|
||||
|
||||
end; --architecture logic
|
||||
|
6
plasma/logic/prog.cmd
Normal file
6
plasma/logic/prog.cmd
Normal file
@ -0,0 +1,6 @@
|
||||
setmode -bscan
|
||||
setcable -p auto
|
||||
identify
|
||||
assignfile -p 1 -file plasma_3e.bit
|
||||
program -p 1
|
||||
quit
|
176
plasma/logic/ram.vhd
Normal file
176
plasma/logic/ram.vhd
Normal file
@ -0,0 +1,176 @@
|
||||
---------------------------------------------------------------------
|
||||
-- TITLE: Random Access Memory
|
||||
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
|
||||
-- DATE CREATED: 4/21/01
|
||||
-- FILENAME: ram.vhd
|
||||
-- PROJECT: Plasma CPU core
|
||||
-- COPYRIGHT: Software placed into the public domain by the author.
|
||||
-- Software 'as is' without warranty. Author liable for nothing.
|
||||
-- DESCRIPTION:
|
||||
-- Implements the RAM, reads the executable from either "code.txt",
|
||||
-- or for Altera "code[0-3].hex".
|
||||
-- Modified from "The Designer's Guide to VHDL" by Peter J. Ashenden
|
||||
---------------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_misc.all;
|
||||
use ieee.std_logic_arith.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
use ieee.std_logic_textio.all;
|
||||
use std.textio.all;
|
||||
use work.mlite_pack.all;
|
||||
|
||||
entity ram is
|
||||
generic(memory_type : string := "DEFAULT");
|
||||
port(clk : in std_logic;
|
||||
enable : in std_logic;
|
||||
write_byte_enable : in std_logic_vector(3 downto 0);
|
||||
address : in std_logic_vector(31 downto 2);
|
||||
data_write : in std_logic_vector(31 downto 0);
|
||||
data_read : out std_logic_vector(31 downto 0));
|
||||
end; --entity ram
|
||||
|
||||
architecture logic of ram is
|
||||
constant ADDRESS_WIDTH : natural := 13;
|
||||
begin
|
||||
|
||||
generic_ram:
|
||||
if memory_type /= "ALTERA_LPM" generate
|
||||
begin
|
||||
--Simulate a synchronous RAM
|
||||
ram_proc: process(clk, enable, write_byte_enable,
|
||||
address, data_write) --mem_write, mem_sel
|
||||
variable mem_size : natural := 2 ** ADDRESS_WIDTH;
|
||||
variable data : std_logic_vector(31 downto 0);
|
||||
subtype word is std_logic_vector(data_write'length-1 downto 0);
|
||||
type storage_array is
|
||||
array(natural range 0 to mem_size/4 - 1) of word;
|
||||
variable storage : storage_array;
|
||||
variable index : natural := 0;
|
||||
file load_file : text open read_mode is "code.txt";
|
||||
variable hex_file_line : line;
|
||||
begin
|
||||
|
||||
--Load in the ram executable image
|
||||
if index = 0 then
|
||||
while not endfile(load_file) loop
|
||||
--The following two lines had to be commented out for synthesis
|
||||
readline(load_file, hex_file_line);
|
||||
hread(hex_file_line, data);
|
||||
storage(index) := data;
|
||||
index := index + 1;
|
||||
end loop;
|
||||
end if;
|
||||
|
||||
if rising_edge(clk) then
|
||||
index := conv_integer(address(ADDRESS_WIDTH-1 downto 2));
|
||||
data := storage(index);
|
||||
|
||||
if enable = '1' then
|
||||
if write_byte_enable(0) = '1' then
|
||||
data(7 downto 0) := data_write(7 downto 0);
|
||||
end if;
|
||||
if write_byte_enable(1) = '1' then
|
||||
data(15 downto 8) := data_write(15 downto 8);
|
||||
end if;
|
||||
if write_byte_enable(2) = '1' then
|
||||
data(23 downto 16) := data_write(23 downto 16);
|
||||
end if;
|
||||
if write_byte_enable(3) = '1' then
|
||||
data(31 downto 24) := data_write(31 downto 24);
|
||||
end if;
|
||||
end if;
|
||||
|
||||
if write_byte_enable /= "0000" then
|
||||
storage(index) := data;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
data_read <= data;
|
||||
end process;
|
||||
end generate; --generic_ram
|
||||
|
||||
|
||||
altera_ram:
|
||||
if memory_type = "ALTERA_LPM" generate
|
||||
signal byte_we : std_logic_vector(3 downto 0);
|
||||
begin
|
||||
byte_we <= write_byte_enable when enable = '1' else "0000";
|
||||
lpm_ram_io_component0 : lpm_ram_dq
|
||||
GENERIC MAP (
|
||||
intended_device_family => "UNUSED",
|
||||
lpm_width => 8,
|
||||
lpm_widthad => ADDRESS_WIDTH-2,
|
||||
lpm_indata => "REGISTERED",
|
||||
lpm_address_control => "REGISTERED",
|
||||
lpm_outdata => "UNREGISTERED",
|
||||
lpm_file => "code0.hex",
|
||||
use_eab => "ON",
|
||||
lpm_type => "LPM_RAM_DQ")
|
||||
PORT MAP (
|
||||
data => data_write(31 downto 24),
|
||||
address => address(ADDRESS_WIDTH-1 downto 2),
|
||||
inclock => clk,
|
||||
we => byte_we(3),
|
||||
q => data_read(31 downto 24));
|
||||
|
||||
lpm_ram_io_component1 : lpm_ram_dq
|
||||
GENERIC MAP (
|
||||
intended_device_family => "UNUSED",
|
||||
lpm_width => 8,
|
||||
lpm_widthad => ADDRESS_WIDTH-2,
|
||||
lpm_indata => "REGISTERED",
|
||||
lpm_address_control => "REGISTERED",
|
||||
lpm_outdata => "UNREGISTERED",
|
||||
lpm_file => "code1.hex",
|
||||
use_eab => "ON",
|
||||
lpm_type => "LPM_RAM_DQ")
|
||||
PORT MAP (
|
||||
data => data_write(23 downto 16),
|
||||
address => address(ADDRESS_WIDTH-1 downto 2),
|
||||
inclock => clk,
|
||||
we => byte_we(2),
|
||||
q => data_read(23 downto 16));
|
||||
|
||||
lpm_ram_io_component2 : lpm_ram_dq
|
||||
GENERIC MAP (
|
||||
intended_device_family => "UNUSED",
|
||||
lpm_width => 8,
|
||||
lpm_widthad => ADDRESS_WIDTH-2,
|
||||
lpm_indata => "REGISTERED",
|
||||
lpm_address_control => "REGISTERED",
|
||||
lpm_outdata => "UNREGISTERED",
|
||||
lpm_file => "code2.hex",
|
||||
use_eab => "ON",
|
||||
lpm_type => "LPM_RAM_DQ")
|
||||
PORT MAP (
|
||||
data => data_write(15 downto 8),
|
||||
address => address(ADDRESS_WIDTH-1 downto 2),
|
||||
inclock => clk,
|
||||
we => byte_we(1),
|
||||
q => data_read(15 downto 8));
|
||||
|
||||
lpm_ram_io_component3 : lpm_ram_dq
|
||||
GENERIC MAP (
|
||||
intended_device_family => "UNUSED",
|
||||
lpm_width => 8,
|
||||
lpm_widthad => ADDRESS_WIDTH-2,
|
||||
lpm_indata => "REGISTERED",
|
||||
lpm_address_control => "REGISTERED",
|
||||
lpm_outdata => "UNREGISTERED",
|
||||
lpm_file => "code3.hex",
|
||||
use_eab => "ON",
|
||||
lpm_type => "LPM_RAM_DQ")
|
||||
PORT MAP (
|
||||
data => data_write(7 downto 0),
|
||||
address => address(ADDRESS_WIDTH-1 downto 2),
|
||||
inclock => clk,
|
||||
we => byte_we(0),
|
||||
q => data_read(7 downto 0));
|
||||
|
||||
end generate; --altera_ram
|
||||
|
||||
|
||||
--For XILINX see ram_xilinx.vhd
|
||||
|
||||
end; --architecture logic
|
350
plasma/logic/ram_image.vhd
Normal file
350
plasma/logic/ram_image.vhd
Normal file
@ -0,0 +1,350 @@
|
||||
---------------------------------------------------------------------
|
||||
-- TITLE: Random Access Memory for Xilinx
|
||||
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
|
||||
-- DATE CREATED: 11/06/05
|
||||
-- FILENAME: ram_xilinx.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 for Spartan 3 Xilinx FPGA
|
||||
--
|
||||
-- Compile the MIPS C and assembly code into "test.axf".
|
||||
-- Run convert.exe to change "test.axf" to "code.txt" which
|
||||
-- will contain the hex values of the opcodes.
|
||||
-- Next run "ram_image ram_xilinx.vhd code.txt ram_image.vhd",
|
||||
-- to create the "ram_image.vhd" file that will have the opcodes
|
||||
-- correctly placed inside the INIT_00 => strings.
|
||||
-- Then include ram_image.vhd in the simulation/synthesis.
|
||||
---------------------------------------------------------------------
|
||||
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 work.mlite_pack.all;
|
||||
library UNISIM;
|
||||
use UNISIM.vcomponents.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
|
||||
begin
|
||||
|
||||
RAMB16_S9_inst0 : RAMB16_S9
|
||||
generic map (
|
||||
INIT_00 => X"afafafafafafafafafafafafafafafaf2308000c241400ac273c243c243c273c",
|
||||
INIT_01 => X"8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f230c008c8c3caf00af00af2340afaf",
|
||||
INIT_02 => X"acacacac0003373cac038cac8cac8cac8c243c40034040033423038f038f8f8f",
|
||||
INIT_03 => X"000300ac0300000034038c8c8c8c8c8c8c8c8c8c8c8c3403acacacacacacacac",
|
||||
INIT_04 => X"1c24001030008c24ac24ac9424003c00180003241c24a4248c0018ac2400003c",
|
||||
INIT_05 => X"a00024241028302400a03c24243c3c0003001030008cacac242400003c000300",
|
||||
INIT_06 => X"100010000c00102a0200260c24af08af2424240000afafafafaf270103001424",
|
||||
INIT_07 => X"240c001a001427038f8f8f8f8f8f8f02240c240c000824102c24142c24142e24",
|
||||
INIT_08 => X"3c240c3c240c3c240c3c240c3caf0cafafafafafafafafaf270008260c24240c",
|
||||
INIT_09 => X"3c3c3c3c3c3c003c3c0c003c240c3c3c1430248c3c1030008c34ac3c3c24240c",
|
||||
INIT_0A => X"0c3c240c3c270c260c260c260c260c240c3c240c3c240c3c240c3c240c3c240c",
|
||||
INIT_0B => X"3c3c08240c3c000c000c8e0000008c0024003c3c102c260000142c2400000c24",
|
||||
INIT_0C => X"3c3c080002a208000c000c00000c240c3c0008923c08ae000c000c00000c240c",
|
||||
INIT_0D => X"080216a002260c00000010000c240c3c3c080216260c900200000010000c240c",
|
||||
INIT_0E => X"0010000c240c3c3c08240c000c000c0014002490020000000010000c240c3c3c",
|
||||
INIT_0F => X"240c3c021402240c000c260c8c021032021002240c000c260c8c02240c3c0000",
|
||||
INIT_10 => X"14343c000c240c3c3c0800003c0016260c262610000c3c120008a23c243c3c08",
|
||||
INIT_11 => X"0c000c2608240c3c000c020c240c3c00000c240c3c020c3c083c0c003c000c00",
|
||||
INIT_12 => X"00100082260c00240800100080afafaf270003ac001030008c343c3c08240c00",
|
||||
INIT_13 => X"2424142c3002242400afafafaf272703008f8f8f00140082000c2682000c2414",
|
||||
INIT_14 => X"24243c3c2703008f8c3c10000caf2730038c343c240827038f8f8f8f0216260c",
|
||||
INIT_15 => X"740a00616d20423a003531303241656c62747267650a24038c0014ac00248c3c",
|
||||
INIT_16 => X"617965330a7769796532006f61796531006e706e724f303030206e6569612020",
|
||||
INIT_17 => X"4600753900736838006979656137617965613673647475350a62697965340079",
|
||||
INIT_18 => X"37336820660a0d786e6e0a786e750a3d6541206820720a3e00616f446f42316f",
|
||||
INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000")
|
||||
port map (
|
||||
DO => data_read(31 downto 24),
|
||||
DOP => open,
|
||||
ADDR => address(12 downto 2),
|
||||
CLK => clk,
|
||||
DI => data_write(31 downto 24),
|
||||
DIP => ZERO(0 downto 0),
|
||||
EN => enable,
|
||||
SSR => ZERO(0),
|
||||
WE => write_byte_enable(3));
|
||||
|
||||
RAMB16_S9_inst1 : RAMB16_S9
|
||||
generic map (
|
||||
INIT_00 => X"b8afaeadacabaaa9a8a7a6a5a4a3a2a1bd000000a560a4a0bd1d8404a5059c1c",
|
||||
INIT_01 => X"b9b8afaeadacabaaa9a8a7a6a5a4a3a2a1a50086c6c406bb00bb00ba5a1abfb9",
|
||||
INIT_02 => X"9392919000405a1a06e0a606a606a606a6a50584e0029b401bbd60bb60bbbabf",
|
||||
INIT_03 => X"00e000c4e0000085a2e09f9d9c9e979695949392919002e09f9d9c9e97969594",
|
||||
INIT_04 => X"c0c60040420062636284658205620205c000e084c0a582c6a200c0a202a20502",
|
||||
INIT_05 => X"c2e5070740a285634040036642020300e000404200828283020382040200e000",
|
||||
INIT_06 => X"54405300000040220312310090b000bf1514130000b1b2b3b4b5bd00e004c3c6",
|
||||
INIT_07 => X"040000208095bde0b0b1b2b3b4b5bf4004000400000090404282404282400250",
|
||||
INIT_08 => X"04840004840004840004840004b000b1b2b3b4b5b6b7bebfbd12003100040400",
|
||||
INIT_09 => X"021e171615144002060000048400041543420382146063004342830204038400",
|
||||
INIT_0A => X"0002440002c400e400c400a40084004400024400024400024400024400024400",
|
||||
INIT_0B => X"0202004400024000000044008000444383030402406203000040424240000044",
|
||||
INIT_0C => X"0202000040500040004000400000440002000044020050400040004000004400",
|
||||
INIT_0D => X"0000136251100000004040000044000202000011100044420000404000004400",
|
||||
INIT_0E => X"404000004400020200040040000000a0a683a543420000004040000044000202",
|
||||
INIT_0F => X"4400020060130400400030004450400200601304004000300044504400020000",
|
||||
INIT_10 => X"4363030000440002020000400240535200101040000002110000501311120200",
|
||||
INIT_11 => X"0000000300440002400040004400024000004400020000020006000004000000",
|
||||
INIT_12 => X"00400002100040110080400082b1bfb0bd00e0a40040420062a3050200040040",
|
||||
INIT_13 => X"646440624312111080bfb0b1b2bdbde000b0b1bf004000024000100200000451",
|
||||
INIT_14 => X"63440302bde000bf6203400000bfbd42e06263030400bde0b0b1b2bf12111000",
|
||||
INIT_15 => X"6957007320666f0a003a39313170726f6f686f73744742e0a200834045848205",
|
||||
INIT_16 => X"64206d2e006f74206d2e007264206d2e007374752074303078616b206d726266",
|
||||
INIT_17 => X"2e006d2e0075652e0074206d772e64206d772e73646f6d2e007974206d2e0074",
|
||||
INIT_18 => X"3834207769430a3e2074433e206556207364006569654120007320526d203270",
|
||||
INIT_19 => X"0004000080240080000000000000000000000000000000000000000000000000",
|
||||
INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000")
|
||||
port map (
|
||||
DO => data_read(23 downto 16),
|
||||
DOP => open,
|
||||
ADDR => address(12 downto 2),
|
||||
CLK => clk,
|
||||
DI => data_write(23 downto 16),
|
||||
DIP => ZERO(0 downto 0),
|
||||
EN => enable,
|
||||
SSR => ZERO(0),
|
||||
WE => write_byte_enable(2));
|
||||
|
||||
RAMB16_S9_inst2 : RAMB16_S9
|
||||
generic map (
|
||||
INIT_00 => X"00000000000000000000000000000000ff00000100ff18000e000f000c008c00",
|
||||
INIT_01 => X"000000000000000000000000000000000000022000002000d800d800ff700000",
|
||||
INIT_02 => X"0000000000000010000000000000000000010060006060000000000000000000",
|
||||
INIT_03 => X"0000000000201000000000000000000000000000000000000000000000000000",
|
||||
INIT_04 => X"ffff00ff00000000000000000018301800000000ff0000ff0000000000282830",
|
||||
INIT_05 => X"001000000000000c4000000d0d0000000000ff00000000000000202030000000",
|
||||
INIT_06 => X"002000000200000090190002ff00000000000088900000000000ff100021ffff",
|
||||
INIT_07 => X"0002000080ff00000000000000000010000200020000ff0000ffff00ffff00ff",
|
||||
INIT_08 => X"000a02000c02000a02000a02000002000000000000000000ff9100ff02000002",
|
||||
INIT_09 => X"000000000000f810000028100a02000000ff3c00000000000000002030000a02",
|
||||
INIT_0A => X"02000b02000b020b020b020b020b020b02000b02000b02000b02000b02000a02",
|
||||
INIT_0B => X"0000010b0200200200000000000000100c100000ff00ff90000000ff8000020c",
|
||||
INIT_0C => X"00000100f80001200280002000000c0200000100000100200280002000000c02",
|
||||
INIT_0D => X"0188ff00180002888098ff00000c0200000110ff00020010108088ff00000c02",
|
||||
INIT_0E => X"980000000c0200000100022002000010ff20000010102028300000000c020000",
|
||||
INIT_0F => X"0c020088ff180002200200000010ff0088001800022002000000100c02008880",
|
||||
INIT_10 => X"ff561200000c0200000100f81080ff0002ff00ff000210008002001027100001",
|
||||
INIT_11 => X"022000ff010b0200200220000c02009000000c02002002000100002810200000",
|
||||
INIT_12 => X"00000000000220000280000000000000ff00000010ff00000000200001000220",
|
||||
INIT_13 => X"000000000010ff009000000000ff00001000000000ff000020020000000200ff",
|
||||
INIT_14 => X"0c0c0000000000000020ff000200ff0000000020000200000000000010ffff02",
|
||||
INIT_15 => X"6e61006866726f0000343a30207220616f656d20697200000000ff0010000010",
|
||||
INIT_16 => X"20726f20007265776f20006420726f20003a69204d680a303174656c6179696f",
|
||||
INIT_17 => X"20007020006d63200065776f20200a726f20200a72207020007465776f200065",
|
||||
INIT_18 => X"3e353169726f002068206f2068206100736400786e7364000068662020663879",
|
||||
INIT_19 => X"0020000000202800000804040404040404040408040407070606060606050500",
|
||||
INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000")
|
||||
port map (
|
||||
DO => data_read(15 downto 8),
|
||||
DOP => open,
|
||||
ADDR => address(12 downto 2),
|
||||
CLK => clk,
|
||||
DI => data_write(15 downto 8),
|
||||
DIP => ZERO(0 downto 0),
|
||||
EN => enable,
|
||||
SSR => ZERO(0),
|
||||
WE => write_byte_enable(1));
|
||||
|
||||
RAMB16_S9_inst3 : RAMB16_S9
|
||||
generic map (
|
||||
INIT_00 => X"4c4844403c3834302c2824201c181410980e000704fd2a00f8001000fc00f001",
|
||||
INIT_01 => X"504c4844403c3834302c2824201c181410008a2410200060125c1058fc005450",
|
||||
INIT_02 => X"0c08040000083c0048080c440840043c006000000800000801681360115c5854",
|
||||
INIT_03 => X"00080c000810121900082c2824201c1814100c08040000082c2824201c181410",
|
||||
INIT_04 => X"f4fe00fc80000004000200004021004011000802fb0400fe00000700ff214000",
|
||||
INIT_05 => X"00213037020a0fff21080007000000000800fc8000000000d020214000000800",
|
||||
INIT_06 => X"0c210e009100121021000145c910db28080d0a212114181c2024d0210802f7ff",
|
||||
INIT_07 => X"0845000821d930081014181c202428210a450d4500d4a9111a9fed1abff10ad0",
|
||||
INIT_08 => X"00d44f00344f00c84f00a84f00109c14181c2024282c3034c802d8ff45082045",
|
||||
INIT_09 => X"000000000000090002802100e44f00000cff1c00001001000050000000ffe04f",
|
||||
INIT_0A => X"4f00fc4f00f04fe04fc84fb44fa04f884f00704f00584f00404f00284f00f84f",
|
||||
INIT_0B => X"0000406c4f00214f00b100000800002184800000d416cf2100c20ad021009120",
|
||||
INIT_0C => X"0000400009003f214f21b12100c5444f00007600004000214f21b12100c5444f",
|
||||
INIT_0D => X"4021fb002101912121218900c5544f00004021fb014500212121219a00c5544f",
|
||||
INIT_0E => X"211e00c5544f0000400a45214f00b121fb21010021212121217600c5544f0000",
|
||||
INIT_0F => X"644f0021f42b2045214f04b10021f00f210e2b2045214f04b10021644f002121",
|
||||
INIT_10 => X"1f783400c5684f00004000090021f30191ff01fb008c000b210a001010000040",
|
||||
INIT_11 => X"4f21b1cf6a6c4f00214f21b1384f002100c5244f0021450040028f210021a300",
|
||||
INIT_12 => X"000d00000145210a6021160000141810e000080021fc020000200000400a4521",
|
||||
INIT_13 => X"5730020a0f06fc1c211c101418e020082110141800f500002145010000450df8",
|
||||
INIT_14 => X"fcdc0000180800100000fd008c10e80108002000494520081014181c06f8fc45",
|
||||
INIT_15 => X"6769000a6c6f74000038300032200064742020666e6584080000fb0021040000",
|
||||
INIT_16 => X"6265724d00642072724d000a7765724d000a6f4f656500303020646967206e72",
|
||||
INIT_17 => X"43000a44000a6b43000a72726d520065726d52006561204a00652072724d000a",
|
||||
INIT_18 => X"203632746d6e00006569750065696c002072003e20736400000a6c7444724b20",
|
||||
INIT_19 => X"00001010200000207060fcfcfcfcfcfcfcfcfc08fcfc6404c07c6c3c30fcd400",
|
||||
INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000")
|
||||
port map (
|
||||
DO => data_read(7 downto 0),
|
||||
DOP => open,
|
||||
ADDR => address(12 downto 2),
|
||||
CLK => clk,
|
||||
DI => data_write(7 downto 0),
|
||||
DIP => ZERO(0 downto 0),
|
||||
EN => enable,
|
||||
SSR => ZERO(0),
|
||||
WE => write_byte_enable(0));
|
||||
|
||||
end; --architecture logic
|
350
plasma/logic/ram_xilinx.vhd
Normal file
350
plasma/logic/ram_xilinx.vhd
Normal file
@ -0,0 +1,350 @@
|
||||
---------------------------------------------------------------------
|
||||
-- TITLE: Random Access Memory for Xilinx
|
||||
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
|
||||
-- DATE CREATED: 11/06/05
|
||||
-- FILENAME: ram_xilinx.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 for Spartan 3 Xilinx FPGA
|
||||
--
|
||||
-- Compile the MIPS C and assembly code into "test.axf".
|
||||
-- Run convert.exe to change "test.axf" to "code.txt" which
|
||||
-- will contain the hex values of the opcodes.
|
||||
-- Next run "ram_image ram_xilinx.vhd code.txt ram_image.vhd",
|
||||
-- to create the "ram_image.vhd" file that will have the opcodes
|
||||
-- correctly placed inside the INIT_00 => strings.
|
||||
-- Then include ram_image.vhd in the simulation/synthesis.
|
||||
---------------------------------------------------------------------
|
||||
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 work.mlite_pack.all;
|
||||
library UNISIM;
|
||||
use UNISIM.vcomponents.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
|
||||
begin
|
||||
|
||||
RAMB16_S9_inst0 : RAMB16_S9
|
||||
generic map (
|
||||
INIT_00 => X"000000000000000000000000000000000000000000000000000000000c080400",
|
||||
INIT_01 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_02 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_03 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_04 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_05 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_06 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_07 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_08 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_09 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_0B => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_11 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_12 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_13 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_14 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_15 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_16 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_17 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_18 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000")
|
||||
port map (
|
||||
DO => data_read(31 downto 24),
|
||||
DOP => open,
|
||||
ADDR => address(12 downto 2),
|
||||
CLK => clk,
|
||||
DI => data_write(31 downto 24),
|
||||
DIP => ZERO(0 downto 0),
|
||||
EN => enable,
|
||||
SSR => ZERO(0),
|
||||
WE => write_byte_enable(3));
|
||||
|
||||
RAMB16_S9_inst1 : RAMB16_S9
|
||||
generic map (
|
||||
INIT_00 => X"000000000000000000000000000000000000000000000000000000000d090501",
|
||||
INIT_01 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_02 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_03 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_04 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_05 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_06 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_07 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_08 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_09 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_0B => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_11 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_12 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_13 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_14 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_15 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_16 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_17 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_18 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000")
|
||||
port map (
|
||||
DO => data_read(23 downto 16),
|
||||
DOP => open,
|
||||
ADDR => address(12 downto 2),
|
||||
CLK => clk,
|
||||
DI => data_write(23 downto 16),
|
||||
DIP => ZERO(0 downto 0),
|
||||
EN => enable,
|
||||
SSR => ZERO(0),
|
||||
WE => write_byte_enable(2));
|
||||
|
||||
RAMB16_S9_inst2 : RAMB16_S9
|
||||
generic map (
|
||||
INIT_00 => X"000000000000000000000000000000000000000000000000000000000e0a0602",
|
||||
INIT_01 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_02 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_03 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_04 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_05 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_06 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_07 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_08 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_09 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_0B => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_11 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_12 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_13 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_14 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_15 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_16 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_17 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_18 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000")
|
||||
port map (
|
||||
DO => data_read(15 downto 8),
|
||||
DOP => open,
|
||||
ADDR => address(12 downto 2),
|
||||
CLK => clk,
|
||||
DI => data_write(15 downto 8),
|
||||
DIP => ZERO(0 downto 0),
|
||||
EN => enable,
|
||||
SSR => ZERO(0),
|
||||
WE => write_byte_enable(1));
|
||||
|
||||
RAMB16_S9_inst3 : RAMB16_S9
|
||||
generic map (
|
||||
INIT_00 => X"000000000000000000000000000000000000000000000000000000000f0b0703",
|
||||
INIT_01 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_02 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_03 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_04 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_05 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_06 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_07 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_08 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_09 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_0B => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_11 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_12 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_13 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_14 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_15 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_16 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_17 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_18 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000")
|
||||
port map (
|
||||
DO => data_read(7 downto 0),
|
||||
DOP => open,
|
||||
ADDR => address(12 downto 2),
|
||||
CLK => clk,
|
||||
DI => data_write(7 downto 0),
|
||||
DIP => ZERO(0 downto 0),
|
||||
EN => enable,
|
||||
SSR => ZERO(0),
|
||||
WE => write_byte_enable(0));
|
||||
|
||||
end; --architecture logic
|
323
plasma/logic/reg_bank.vhd
Normal file
323
plasma/logic/reg_bank.vhd
Normal file
@ -0,0 +1,323 @@
|
||||
---------------------------------------------------------------------
|
||||
-- TITLE: Register Bank
|
||||
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
|
||||
-- DATE CREATED: 2/2/01
|
||||
-- FILENAME: reg_bank.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 a register bank with 32 registers that are 32-bits wide.
|
||||
-- There are two read-ports and one write port.
|
||||
---------------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
use work.mlite_pack.all;
|
||||
--library UNISIM; --May need to uncomment for ModelSim
|
||||
--use UNISIM.vcomponents.all; --May need to uncomment for ModelSim
|
||||
|
||||
entity reg_bank is
|
||||
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; --entity reg_bank
|
||||
|
||||
|
||||
--------------------------------------------------------------------
|
||||
-- The ram_block architecture attempts to use TWO dual-port memories.
|
||||
-- Different FPGAs and ASICs need different implementations.
|
||||
-- Choose one of the RAM implementations below.
|
||||
-- I need feedback on this section!
|
||||
--------------------------------------------------------------------
|
||||
architecture ram_block of reg_bank is
|
||||
signal intr_enable_reg : std_logic;
|
||||
type ram_type is array(31 downto 0) of std_logic_vector(31 downto 0);
|
||||
|
||||
--controls access to dual-port memories
|
||||
signal addr_read1, addr_read2 : std_logic_vector(4 downto 0);
|
||||
signal addr_write : std_logic_vector(4 downto 0);
|
||||
signal data_out1, data_out2 : std_logic_vector(31 downto 0);
|
||||
signal write_enable : std_logic;
|
||||
|
||||
begin
|
||||
|
||||
reg_proc: process(clk, rs_index, rt_index, rd_index, reg_dest_new,
|
||||
intr_enable_reg, data_out1, data_out2, reset_in, pause)
|
||||
begin
|
||||
--setup for first dual-port memory
|
||||
if rs_index = "101110" then --reg_epc CP0 14
|
||||
addr_read1 <= "00000";
|
||||
else
|
||||
addr_read1 <= rs_index(4 downto 0);
|
||||
end if;
|
||||
case rs_index is
|
||||
when "000000" => reg_source_out <= ZERO;
|
||||
when "101100" => reg_source_out <= ZERO(31 downto 1) & intr_enable_reg;
|
||||
--interrupt vector address = 0x3c
|
||||
when "111111" => reg_source_out <= ZERO(31 downto 8) & "00111100";
|
||||
when others => reg_source_out <= data_out1;
|
||||
end case;
|
||||
|
||||
--setup for second dual-port memory
|
||||
addr_read2 <= rt_index(4 downto 0);
|
||||
case rt_index is
|
||||
when "000000" => reg_target_out <= ZERO;
|
||||
when others => reg_target_out <= data_out2;
|
||||
end case;
|
||||
|
||||
--setup write port for both dual-port memories
|
||||
if rd_index /= "000000" and rd_index /= "101100" and pause = '0' then
|
||||
write_enable <= '1';
|
||||
else
|
||||
write_enable <= '0';
|
||||
end if;
|
||||
if rd_index = "101110" then --reg_epc CP0 14
|
||||
addr_write <= "00000";
|
||||
else
|
||||
addr_write <= rd_index(4 downto 0);
|
||||
end if;
|
||||
|
||||
if reset_in = '1' then
|
||||
intr_enable_reg <= '0';
|
||||
elsif rising_edge(clk) then
|
||||
if rd_index = "101110" then --reg_epc CP0 14
|
||||
intr_enable_reg <= '0'; --disable interrupts
|
||||
elsif rd_index = "101100" then
|
||||
intr_enable_reg <= reg_dest_new(0);
|
||||
end if;
|
||||
end if;
|
||||
|
||||
intr_enable <= intr_enable_reg;
|
||||
end process;
|
||||
|
||||
|
||||
--------------------------------------------------------------
|
||||
---- Pick only ONE of the dual-port RAM implementations below!
|
||||
--------------------------------------------------------------
|
||||
|
||||
-- Option #1
|
||||
-- One tri-port RAM, two read-ports, one write-port
|
||||
-- 32 registers 32-bits wide
|
||||
tri_port_mem:
|
||||
if memory_type = "TRI_PORT_X" generate
|
||||
ram_proc: process(clk, addr_read1, addr_read2,
|
||||
addr_write, reg_dest_new, write_enable)
|
||||
variable tri_port_ram : ram_type := (others => ZERO);
|
||||
begin
|
||||
data_out1 <= tri_port_ram(conv_integer(addr_read1));
|
||||
data_out2 <= tri_port_ram(conv_integer(addr_read2));
|
||||
if rising_edge(clk) then
|
||||
if write_enable = '1' then
|
||||
tri_port_ram(conv_integer(addr_write)) := reg_dest_new;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
end generate; --tri_port_mem
|
||||
|
||||
|
||||
-- Option #2
|
||||
-- Two dual-port RAMs, each with one read-port and one write-port
|
||||
dual_port_mem:
|
||||
if memory_type = "DUAL_PORT_" generate
|
||||
ram_proc2: process(clk, addr_read1, addr_read2,
|
||||
addr_write, reg_dest_new, write_enable)
|
||||
variable dual_port_ram1 : ram_type := (others => ZERO);
|
||||
variable dual_port_ram2 : ram_type := (others => ZERO);
|
||||
begin
|
||||
data_out1 <= dual_port_ram1(conv_integer(addr_read1));
|
||||
data_out2 <= dual_port_ram2(conv_integer(addr_read2));
|
||||
if rising_edge(clk) then
|
||||
if write_enable = '1' then
|
||||
dual_port_ram1(conv_integer(addr_write)) := reg_dest_new;
|
||||
dual_port_ram2(conv_integer(addr_write)) := reg_dest_new;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
end generate; --dual_port_mem
|
||||
|
||||
|
||||
-- Option #3
|
||||
-- RAM16X1D: 16 x 1 positive edge write, asynchronous read dual-port
|
||||
-- distributed RAM for all Xilinx FPGAs
|
||||
-- From library UNISIM; use UNISIM.vcomponents.all;
|
||||
xilinx_16x1d:
|
||||
if memory_type = "XILINX_16X" generate
|
||||
signal data_out1A, data_out1B : std_logic_vector(31 downto 0);
|
||||
signal data_out2A, data_out2B : std_logic_vector(31 downto 0);
|
||||
signal weA, weB : std_logic;
|
||||
signal no_connect : std_logic_vector(127 downto 0);
|
||||
begin
|
||||
weA <= write_enable and not addr_write(4); --lower 16 registers
|
||||
weB <= write_enable and addr_write(4); --upper 16 registers
|
||||
|
||||
reg_loop: for i in 0 to 31 generate
|
||||
begin
|
||||
--Read port 1 lower 16 registers
|
||||
reg_bit1a : RAM16X1D
|
||||
port map (
|
||||
WCLK => clk, -- Port A write clock input
|
||||
WE => weA, -- Port A write enable input
|
||||
A0 => addr_write(0), -- Port A address[0] input bit
|
||||
A1 => addr_write(1), -- Port A address[1] input bit
|
||||
A2 => addr_write(2), -- Port A address[2] input bit
|
||||
A3 => addr_write(3), -- Port A address[3] input bit
|
||||
D => reg_dest_new(i), -- Port A 1-bit data input
|
||||
DPRA0 => addr_read1(0), -- Port B address[0] input bit
|
||||
DPRA1 => addr_read1(1), -- Port B address[1] input bit
|
||||
DPRA2 => addr_read1(2), -- Port B address[2] input bit
|
||||
DPRA3 => addr_read1(3), -- Port B address[3] input bit
|
||||
DPO => data_out1A(i), -- Port B 1-bit data output
|
||||
SPO => no_connect(i) -- Port A 1-bit data output
|
||||
);
|
||||
--Read port 1 upper 16 registers
|
||||
reg_bit1b : RAM16X1D
|
||||
port map (
|
||||
WCLK => clk, -- Port A write clock input
|
||||
WE => weB, -- Port A write enable input
|
||||
A0 => addr_write(0), -- Port A address[0] input bit
|
||||
A1 => addr_write(1), -- Port A address[1] input bit
|
||||
A2 => addr_write(2), -- Port A address[2] input bit
|
||||
A3 => addr_write(3), -- Port A address[3] input bit
|
||||
D => reg_dest_new(i), -- Port A 1-bit data input
|
||||
DPRA0 => addr_read1(0), -- Port B address[0] input bit
|
||||
DPRA1 => addr_read1(1), -- Port B address[1] input bit
|
||||
DPRA2 => addr_read1(2), -- Port B address[2] input bit
|
||||
DPRA3 => addr_read1(3), -- Port B address[3] input bit
|
||||
DPO => data_out1B(i), -- Port B 1-bit data output
|
||||
SPO => no_connect(32+i) -- Port A 1-bit data output
|
||||
);
|
||||
--Read port 2 lower 16 registers
|
||||
reg_bit2a : RAM16X1D
|
||||
port map (
|
||||
WCLK => clk, -- Port A write clock input
|
||||
WE => weA, -- Port A write enable input
|
||||
A0 => addr_write(0), -- Port A address[0] input bit
|
||||
A1 => addr_write(1), -- Port A address[1] input bit
|
||||
A2 => addr_write(2), -- Port A address[2] input bit
|
||||
A3 => addr_write(3), -- Port A address[3] input bit
|
||||
D => reg_dest_new(i), -- Port A 1-bit data input
|
||||
DPRA0 => addr_read2(0), -- Port B address[0] input bit
|
||||
DPRA1 => addr_read2(1), -- Port B address[1] input bit
|
||||
DPRA2 => addr_read2(2), -- Port B address[2] input bit
|
||||
DPRA3 => addr_read2(3), -- Port B address[3] input bit
|
||||
DPO => data_out2A(i), -- Port B 1-bit data output
|
||||
SPO => no_connect(64+i) -- Port A 1-bit data output
|
||||
);
|
||||
--Read port 2 upper 16 registers
|
||||
reg_bit2b : RAM16X1D
|
||||
port map (
|
||||
WCLK => clk, -- Port A write clock input
|
||||
WE => weB, -- Port A write enable input
|
||||
A0 => addr_write(0), -- Port A address[0] input bit
|
||||
A1 => addr_write(1), -- Port A address[1] input bit
|
||||
A2 => addr_write(2), -- Port A address[2] input bit
|
||||
A3 => addr_write(3), -- Port A address[3] input bit
|
||||
D => reg_dest_new(i), -- Port A 1-bit data input
|
||||
DPRA0 => addr_read2(0), -- Port B address[0] input bit
|
||||
DPRA1 => addr_read2(1), -- Port B address[1] input bit
|
||||
DPRA2 => addr_read2(2), -- Port B address[2] input bit
|
||||
DPRA3 => addr_read2(3), -- Port B address[3] input bit
|
||||
DPO => data_out2B(i), -- Port B 1-bit data output
|
||||
SPO => no_connect(96+i) -- Port A 1-bit data output
|
||||
);
|
||||
end generate; --reg_loop
|
||||
|
||||
data_out1 <= data_out1A when addr_read1(4)='0' else data_out1B;
|
||||
data_out2 <= data_out2A when addr_read2(4)='0' else data_out2B;
|
||||
end generate; --xilinx_16x1d
|
||||
|
||||
|
||||
-- Option #4
|
||||
-- Altera LPM_RAM_DP
|
||||
altera_mem:
|
||||
if memory_type = "ALTERA_LPM" generate
|
||||
signal clk_delayed : std_logic;
|
||||
signal addr_reg : std_logic_vector(4 downto 0);
|
||||
signal data_reg : std_logic_vector(31 downto 0);
|
||||
signal q1 : std_logic_vector(31 downto 0);
|
||||
signal q2 : std_logic_vector(31 downto 0);
|
||||
begin
|
||||
-- Altera dual port RAMs must have the addresses registered (sampled
|
||||
-- at the rising edge). This is very unfortunate.
|
||||
-- Therefore, the dual port RAM read clock must delayed so that
|
||||
-- the read address signal can be sent from the mem_ctrl block.
|
||||
-- This solution also delays the how fast the registers are read so the
|
||||
-- maximum clock speed is cut in half (12.5 MHz instead of 25 MHz).
|
||||
|
||||
clk_delayed <= not clk; --Could be delayed by 1/4 clock cycle instead
|
||||
dpram_bypass: process(clk, addr_write, reg_dest_new)
|
||||
begin
|
||||
if rising_edge(clk) and write_enable = '1' then
|
||||
addr_reg <= addr_write;
|
||||
data_reg <= reg_dest_new;
|
||||
end if;
|
||||
end process; --dpram_bypass
|
||||
|
||||
-- Bypass dpram if reading what was just written (Altera limitation)
|
||||
data_out1 <= q1 when addr_read1 /= addr_reg else data_reg;
|
||||
data_out2 <= q2 when addr_read2 /= addr_reg else data_reg;
|
||||
|
||||
lpm_ram_dp_component1 : lpm_ram_dp
|
||||
generic map (
|
||||
LPM_WIDTH => 32,
|
||||
LPM_WIDTHAD => 5,
|
||||
--LPM_NUMWORDS => 0,
|
||||
LPM_INDATA => "REGISTERED",
|
||||
LPM_OUTDATA => "UNREGISTERED",
|
||||
LPM_RDADDRESS_CONTROL => "REGISTERED",
|
||||
LPM_WRADDRESS_CONTROL => "REGISTERED",
|
||||
LPM_FILE => "UNUSED",
|
||||
LPM_TYPE => "LPM_RAM_DP",
|
||||
USE_EAB => "ON",
|
||||
INTENDED_DEVICE_FAMILY => "UNUSED",
|
||||
RDEN_USED => "FALSE",
|
||||
LPM_HINT => "UNUSED")
|
||||
port map (
|
||||
RDCLOCK => clk_delayed,
|
||||
RDCLKEN => '1',
|
||||
RDADDRESS => addr_read1,
|
||||
RDEN => '1',
|
||||
DATA => reg_dest_new,
|
||||
WRADDRESS => addr_write,
|
||||
WREN => write_enable,
|
||||
WRCLOCK => clk,
|
||||
WRCLKEN => '1',
|
||||
Q => q1);
|
||||
lpm_ram_dp_component2 : lpm_ram_dp
|
||||
generic map (
|
||||
LPM_WIDTH => 32,
|
||||
LPM_WIDTHAD => 5,
|
||||
--LPM_NUMWORDS => 0,
|
||||
LPM_INDATA => "REGISTERED",
|
||||
LPM_OUTDATA => "UNREGISTERED",
|
||||
LPM_RDADDRESS_CONTROL => "REGISTERED",
|
||||
LPM_WRADDRESS_CONTROL => "REGISTERED",
|
||||
LPM_FILE => "UNUSED",
|
||||
LPM_TYPE => "LPM_RAM_DP",
|
||||
USE_EAB => "ON",
|
||||
INTENDED_DEVICE_FAMILY => "UNUSED",
|
||||
RDEN_USED => "FALSE",
|
||||
LPM_HINT => "UNUSED")
|
||||
port map (
|
||||
RDCLOCK => clk_delayed,
|
||||
RDCLKEN => '1',
|
||||
RDADDRESS => addr_read2,
|
||||
RDEN => '1',
|
||||
DATA => reg_dest_new,
|
||||
WRADDRESS => addr_write,
|
||||
WREN => write_enable,
|
||||
WRCLOCK => clk,
|
||||
WRCLKEN => '1',
|
||||
Q => q2);
|
||||
end generate; --altera_mem
|
||||
|
||||
end; --architecture ram_block
|
65
plasma/logic/shifter.vhd
Normal file
65
plasma/logic/shifter.vhd
Normal file
@ -0,0 +1,65 @@
|
||||
---------------------------------------------------------------------
|
||||
-- TITLE: Shifter Unit
|
||||
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
|
||||
-- Matthias Gruenewald
|
||||
-- DATE CREATED: 2/2/01
|
||||
-- FILENAME: shifter.vhd
|
||||
-- PROJECT: Plasma CPU core
|
||||
-- COPYRIGHT: Software placed into the public domain by the author.
|
||||
-- Software 'as is' without warranty. Author liable for nothing.
|
||||
-- DESCRIPTION:
|
||||
-- Implements the 32-bit shifter unit.
|
||||
---------------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use work.mlite_pack.all;
|
||||
|
||||
entity shifter is
|
||||
generic(shifter_type : string := "DEFAULT");
|
||||
port(value : in std_logic_vector(31 downto 0);
|
||||
shift_amount : in std_logic_vector(4 downto 0);
|
||||
shift_func : in shift_function_type;
|
||||
c_shift : out std_logic_vector(31 downto 0));
|
||||
end; --entity shifter
|
||||
|
||||
architecture logic of shifter is
|
||||
-- type shift_function_type is (
|
||||
-- shift_nothing, shift_left_unsigned,
|
||||
-- shift_right_signed, shift_right_unsigned);
|
||||
|
||||
signal shift1L, shift2L, shift4L, shift8L, shift16L : std_logic_vector(31 downto 0);
|
||||
signal shift1R, shift2R, shift4R, shift8R, shift16R : std_logic_vector(31 downto 0);
|
||||
signal fills : std_logic_vector(31 downto 16);
|
||||
|
||||
begin
|
||||
fills <= "1111111111111111" when shift_func = SHIFT_RIGHT_SIGNED
|
||||
and value(31) = '1'
|
||||
else "0000000000000000";
|
||||
shift1L <= value(30 downto 0) & '0' when shift_amount(0) = '1' else value;
|
||||
shift2L <= shift1L(29 downto 0) & "00" when shift_amount(1) = '1' else shift1L;
|
||||
shift4L <= shift2L(27 downto 0) & "0000" when shift_amount(2) = '1' else shift2L;
|
||||
shift8L <= shift4L(23 downto 0) & "00000000" when shift_amount(3) = '1' else shift4L;
|
||||
shift16L <= shift8L(15 downto 0) & ZERO(15 downto 0) when shift_amount(4) = '1' else shift8L;
|
||||
|
||||
shift1R <= fills(31) & value(31 downto 1) when shift_amount(0) = '1' else value;
|
||||
shift2R <= fills(31 downto 30) & shift1R(31 downto 2) when shift_amount(1) = '1' else shift1R;
|
||||
shift4R <= fills(31 downto 28) & shift2R(31 downto 4) when shift_amount(2) = '1' else shift2R;
|
||||
shift8R <= fills(31 downto 24) & shift4R(31 downto 8) when shift_amount(3) = '1' else shift4R;
|
||||
shift16R <= fills(31 downto 16) & shift8R(31 downto 16) when shift_amount(4) = '1' else shift8R;
|
||||
|
||||
GENERIC_SHIFTER: if shifter_type = "DEFAULT" generate
|
||||
c_shift <= shift16L when shift_func = SHIFT_LEFT_UNSIGNED else
|
||||
shift16R when shift_func = SHIFT_RIGHT_UNSIGNED or
|
||||
shift_func = SHIFT_RIGHT_SIGNED else
|
||||
ZERO;
|
||||
end generate;
|
||||
|
||||
AREA_OPTIMIZED_SHIFTER: if shifter_type /= "DEFAULT" generate
|
||||
c_shift <= shift16L when shift_func = SHIFT_LEFT_UNSIGNED else (others => 'Z');
|
||||
c_shift <= shift16R when shift_func = SHIFT_RIGHT_UNSIGNED or
|
||||
shift_func = SHIFT_RIGHT_SIGNED else (others => 'Z');
|
||||
c_shift <= ZERO when shift_func = SHIFT_NOTHING else (others => 'Z');
|
||||
end generate;
|
||||
|
||||
end; --architecture logic
|
||||
|
29
plasma/logic/simulation/output.txt
Normal file
29
plasma/logic/simulation/output.txt
Normal file
@ -0,0 +1,29 @@
|
||||
|
||||
Greetings from the bootloader Apr 21 2010 19:05:48:
|
||||
|
||||
Waiting for binary image linked at 0x10000000
|
||||
Other Menu Options:
|
||||
1. Memory read word
|
||||
2. Memory write word
|
||||
3. Memory read byte
|
||||
4. Memory write byte
|
||||
5. Jump to address
|
||||
6. Raw memory read
|
||||
7. Raw memory write
|
||||
8. Checksum
|
||||
9. Dump
|
||||
F. Copy 128KB from DDR to flash
|
||||
>
|
||||
Waiting for binary image linked at 0x10000000
|
||||
Other Menu Options:
|
||||
1. Memory read word
|
||||
2. Memory write word
|
||||
3. Memory read byte
|
||||
4. Memory write byte
|
||||
5. Jump to address
|
||||
6. Raw memory read
|
||||
7. Raw memory write
|
||||
8. Checksum
|
||||
9. Dump
|
||||
F. Copy 128KB from DDR to flash
|
||||
> 4
|
29
plasma/logic/simulation/plasma_3e_TB.do
Normal file
29
plasma/logic/simulation/plasma_3e_TB.do
Normal file
@ -0,0 +1,29 @@
|
||||
vlib work
|
||||
vmap work
|
||||
vcom -93 -work work ../mlite_pack.vhd
|
||||
vcom -93 -work work ../plasma.vhd
|
||||
vcom -93 -work work ../alu.vhd
|
||||
vcom -93 -work work ../control.vhd
|
||||
vcom -93 -work work ../mem_ctrl.vhd
|
||||
vcom -93 -work work ../mult.vhd
|
||||
vcom -93 -work work ../shifter.vhd
|
||||
vcom -93 -work work ../bus_mux.vhd
|
||||
vcom -93 -work work ../ddr_ctrl.vhd
|
||||
vcom -93 -work work ../mlite_cpu.vhd
|
||||
vcom -93 -work work ../pc_next.vhd
|
||||
vcom -93 -work work ../cache.vhd
|
||||
vcom -93 -work work ../eth_dma.vhd
|
||||
vcom -93 -work work ../pipeline.vhd
|
||||
vcom -93 -work work ../reg_bank.vhd
|
||||
vcom -93 -work work ../uart.vhd
|
||||
vcom -93 -work work ../plasma_3e.vhd
|
||||
vcom -93 -work work ../ram_image.vhd
|
||||
vcom -93 -work work ../tbench.vhd
|
||||
|
||||
vsim -t 1ps tbench
|
||||
view wave
|
||||
add wave *
|
||||
|
||||
view structure
|
||||
view signals
|
||||
run 15ms
|
283
plasma/logic/simulation/transcript
Normal file
283
plasma/logic/simulation/transcript
Normal file
@ -0,0 +1,283 @@
|
||||
# // ModelSim SE 6.0d Apr 25 2005 Linux 2.6.32-21-generic
|
||||
# //
|
||||
# // Copyright Mentor Graphics Corporation 2005
|
||||
# // All Rights Reserved.
|
||||
# //
|
||||
# // THIS WORK CONTAINS TRADE SECRET AND
|
||||
# // PROPRIETARY INFORMATION WHICH IS THE PROPERTY
|
||||
# // OF MENTOR GRAPHICS CORPORATION OR ITS LICENSORS
|
||||
# // AND IS SUBJECT TO LICENSE TERMS.
|
||||
# //
|
||||
# do plasma_3e_TB.do
|
||||
# Reading /home/opt/cad/modeltech/linux/../modelsim.ini
|
||||
# "work" maps to directory work. (Default mapping)
|
||||
# Model Technology ModelSim SE vcom 6.0d Compiler 2005.04 Apr 25 2005
|
||||
# -- Loading package standard
|
||||
# -- Loading package std_logic_1164
|
||||
# -- Compiling package mlite_pack
|
||||
# -- Compiling package body mlite_pack
|
||||
# -- Loading package mlite_pack
|
||||
# Model Technology ModelSim SE vcom 6.0d Compiler 2005.04 Apr 25 2005
|
||||
# -- Loading package standard
|
||||
# -- Loading package std_logic_1164
|
||||
# -- Loading package mlite_pack
|
||||
# -- Compiling entity plasma
|
||||
# -- Compiling architecture logic of plasma
|
||||
# Model Technology ModelSim SE vcom 6.0d Compiler 2005.04 Apr 25 2005
|
||||
# -- Loading package standard
|
||||
# -- Loading package std_logic_1164
|
||||
# -- Loading package mlite_pack
|
||||
# -- Compiling entity alu
|
||||
# -- Compiling architecture logic of alu
|
||||
# Model Technology ModelSim SE vcom 6.0d Compiler 2005.04 Apr 25 2005
|
||||
# -- Loading package standard
|
||||
# -- Loading package std_logic_1164
|
||||
# -- Loading package mlite_pack
|
||||
# -- Compiling entity control
|
||||
# -- Compiling architecture logic of control
|
||||
# Model Technology ModelSim SE vcom 6.0d Compiler 2005.04 Apr 25 2005
|
||||
# -- Loading package standard
|
||||
# -- Loading package std_logic_1164
|
||||
# -- Loading package mlite_pack
|
||||
# -- Compiling entity mem_ctrl
|
||||
# -- Compiling architecture logic of mem_ctrl
|
||||
# Model Technology ModelSim SE vcom 6.0d Compiler 2005.04 Apr 25 2005
|
||||
# -- Loading package standard
|
||||
# -- Loading package std_logic_1164
|
||||
# -- Loading package std_logic_arith
|
||||
# -- Loading package std_logic_unsigned
|
||||
# -- Loading package mlite_pack
|
||||
# -- Compiling entity mult
|
||||
# -- Compiling architecture logic of mult
|
||||
# Model Technology ModelSim SE vcom 6.0d Compiler 2005.04 Apr 25 2005
|
||||
# -- Loading package standard
|
||||
# -- Loading package std_logic_1164
|
||||
# -- Loading package mlite_pack
|
||||
# -- Compiling entity shifter
|
||||
# -- Compiling architecture logic of shifter
|
||||
# Model Technology ModelSim SE vcom 6.0d Compiler 2005.04 Apr 25 2005
|
||||
# -- Loading package standard
|
||||
# -- Loading package std_logic_1164
|
||||
# -- Loading package mlite_pack
|
||||
# -- Compiling entity bus_mux
|
||||
# -- Compiling architecture logic of bus_mux
|
||||
# Model Technology ModelSim SE vcom 6.0d Compiler 2005.04 Apr 25 2005
|
||||
# -- Loading package standard
|
||||
# -- Loading package std_logic_1164
|
||||
# -- Loading package std_logic_arith
|
||||
# -- Loading package std_logic_unsigned
|
||||
# -- Loading package mlite_pack
|
||||
# -- Compiling entity ddr_ctrl
|
||||
# -- Compiling architecture logic of ddr_ctrl
|
||||
# Model Technology ModelSim SE vcom 6.0d Compiler 2005.04 Apr 25 2005
|
||||
# -- Loading package standard
|
||||
# -- Loading package std_logic_1164
|
||||
# -- Loading package mlite_pack
|
||||
# -- Loading package std_logic_arith
|
||||
# -- Loading package std_logic_unsigned
|
||||
# -- Compiling entity mlite_cpu
|
||||
# -- Compiling architecture logic of mlite_cpu
|
||||
# Model Technology ModelSim SE vcom 6.0d Compiler 2005.04 Apr 25 2005
|
||||
# -- Loading package standard
|
||||
# -- Loading package std_logic_1164
|
||||
# -- Loading package mlite_pack
|
||||
# -- Compiling entity pc_next
|
||||
# -- Compiling architecture logic of pc_next
|
||||
# Model Technology ModelSim SE vcom 6.0d Compiler 2005.04 Apr 25 2005
|
||||
# -- Loading package standard
|
||||
# -- Loading package std_logic_1164
|
||||
# -- Loading package std_logic_arith
|
||||
# -- Loading package std_logic_unsigned
|
||||
# -- Loading package vcomponents
|
||||
# -- Loading package mlite_pack
|
||||
# -- Compiling entity cache
|
||||
# -- Compiling architecture logic of cache
|
||||
# Model Technology ModelSim SE vcom 6.0d Compiler 2005.04 Apr 25 2005
|
||||
# -- Loading package standard
|
||||
# -- Loading package std_logic_1164
|
||||
# -- Loading package std_logic_arith
|
||||
# -- Loading package std_logic_unsigned
|
||||
# -- Loading package mlite_pack
|
||||
# -- Compiling entity eth_dma
|
||||
# -- Compiling architecture logic of eth_dma
|
||||
# Model Technology ModelSim SE vcom 6.0d Compiler 2005.04 Apr 25 2005
|
||||
# -- Loading package standard
|
||||
# -- Loading package std_logic_1164
|
||||
# -- Loading package mlite_pack
|
||||
# -- Compiling entity pipeline
|
||||
# -- Compiling architecture logic of pipeline
|
||||
# Model Technology ModelSim SE vcom 6.0d Compiler 2005.04 Apr 25 2005
|
||||
# -- Loading package standard
|
||||
# -- Loading package std_logic_1164
|
||||
# -- Loading package std_logic_arith
|
||||
# -- Loading package std_logic_unsigned
|
||||
# -- Loading package mlite_pack
|
||||
# -- Compiling entity reg_bank
|
||||
# -- Compiling architecture ram_block of reg_bank
|
||||
# Model Technology ModelSim SE vcom 6.0d Compiler 2005.04 Apr 25 2005
|
||||
# -- Loading package standard
|
||||
# -- Loading package std_logic_1164
|
||||
# -- Loading package attributes
|
||||
# -- Loading package std_logic_misc
|
||||
# -- Loading package std_logic_arith
|
||||
# -- Loading package textio
|
||||
# -- Loading package std_logic_textio
|
||||
# -- Loading package std_logic_unsigned
|
||||
# -- Loading package mlite_pack
|
||||
# -- Compiling entity uart
|
||||
# -- Compiling architecture logic of uart
|
||||
# Model Technology ModelSim SE vcom 6.0d Compiler 2005.04 Apr 25 2005
|
||||
# -- Loading package standard
|
||||
# -- Loading package std_logic_1164
|
||||
# -- Loading package std_logic_arith
|
||||
# -- Loading package std_logic_unsigned
|
||||
# -- Compiling entity plasma_3e
|
||||
# -- Compiling architecture logic of plasma_3e
|
||||
# Model Technology ModelSim SE vcom 6.0d Compiler 2005.04 Apr 25 2005
|
||||
# -- Loading package standard
|
||||
# -- Loading package std_logic_1164
|
||||
# -- Loading package attributes
|
||||
# -- Loading package std_logic_misc
|
||||
# -- Loading package std_logic_arith
|
||||
# -- Loading package std_logic_unsigned
|
||||
# -- Loading package mlite_pack
|
||||
# -- Loading package vcomponents
|
||||
# -- Compiling entity ram
|
||||
# -- Compiling architecture logic of ram
|
||||
# Model Technology ModelSim SE vcom 6.0d Compiler 2005.04 Apr 25 2005
|
||||
# -- Loading package standard
|
||||
# -- Loading package std_logic_1164
|
||||
# -- Loading package mlite_pack
|
||||
# -- Loading package std_logic_arith
|
||||
# -- Loading package std_logic_unsigned
|
||||
# -- Compiling entity tbench
|
||||
# -- Compiling architecture logic of tbench
|
||||
# vsim -t 1ps tbench
|
||||
# Loading /home/opt/cad/modeltech/linux/../std.standard
|
||||
# Loading /home/opt/cad/modeltech/linux/../ieee.std_logic_1164(body)
|
||||
# Loading work.mlite_pack(body)
|
||||
# Loading /home/opt/cad/modeltech/linux/../ieee.std_logic_arith(body)
|
||||
# Loading /home/opt/cad/modeltech/linux/../ieee.std_logic_unsigned(body)
|
||||
# Loading work.tbench(logic)
|
||||
# Loading work.plasma(logic)
|
||||
# Loading work.mlite_cpu(logic)
|
||||
# Loading work.pc_next(logic)
|
||||
# Loading work.mem_ctrl(logic)
|
||||
# Loading work.control(logic)
|
||||
# Loading work.reg_bank(ram_block)
|
||||
# Loading work.bus_mux(logic)
|
||||
# Loading work.alu(logic)
|
||||
# Loading work.shifter(logic)
|
||||
# Loading work.mult(logic)
|
||||
# Loading /opt/cad/modeltech/xilinx/vhdl/unisim.vcomponents
|
||||
# Loading work.cache(logic)
|
||||
# Loading /home/opt/cad/modeltech/linux/../synopsys.attributes
|
||||
# Loading /home/opt/cad/modeltech/linux/../ieee.std_logic_misc(body)
|
||||
# Loading work.ram(logic)
|
||||
# Loading /home/opt/cad/modeltech/linux/../std.textio(body)
|
||||
# Loading /home/opt/cad/modeltech/linux/../ieee.vital_timing(body)
|
||||
# Loading /home/opt/cad/modeltech/linux/../ieee.vital_primitives(body)
|
||||
# Loading /opt/cad/modeltech/xilinx/vhdl/unisim.vpkg(body)
|
||||
# Loading /opt/cad/modeltech/xilinx/vhdl/unisim.ramb16_s9(ramb16_s9_v)
|
||||
# Loading /home/opt/cad/modeltech/linux/../ieee.std_logic_textio(body)
|
||||
# Loading work.uart(logic)
|
||||
# Loading work.eth_dma(logic)
|
||||
# .main_pane.mdi.interior.cs.vm.paneset.cli_0.wf.clip.cs
|
||||
# .main_pane.workspace
|
||||
# .main_pane.signals.interior.cs
|
||||
# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
|
||||
# Time: 0 ps Iteration: 0 Instance: /tbench
|
||||
# ** Warning: CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, and it has been converted to 0.
|
||||
# Time: 0 ps Iteration: 0 Instance: /tbench
|
||||
# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
|
||||
# Time: 0 ps Iteration: 0 Instance: /tbench/u1_plasma/dma_gen2/u4_eth
|
||||
# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
|
||||
# Time: 0 ps Iteration: 0 Instance: /tbench/u1_plasma/dma_gen2/u4_eth
|
||||
# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
|
||||
# Time: 0 ps Iteration: 0 Instance: /tbench/u1_plasma/u3_uart
|
||||
# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
|
||||
# Time: 0 ps Iteration: 0 Instance: /tbench/u1_plasma/opt_cache2/u_cache
|
||||
# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
|
||||
# Time: 0 ps Iteration: 0 Instance: /tbench/u1_plasma/opt_cache2/u_cache
|
||||
# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
|
||||
# Time: 0 ps Iteration: 0 Instance: /tbench/u1_plasma/opt_cache2/u_cache
|
||||
# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
|
||||
# Time: 0 ps Iteration: 0 Instance: /tbench/u1_plasma/u1_cpu/u8_mult
|
||||
# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
|
||||
# Time: 0 ps Iteration: 0 Instance: /tbench/u1_plasma/u1_cpu/u8_mult
|
||||
# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
|
||||
# Time: 0 ps Iteration: 0 Instance: /tbench/u1_plasma/u1_cpu/u8_mult
|
||||
# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
|
||||
# Time: 0 ps Iteration: 0 Instance: /tbench/u1_plasma/u1_cpu/u8_mult
|
||||
# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
|
||||
# Time: 0 ps Iteration: 0 Instance: /tbench/u1_plasma/u1_cpu/u8_mult
|
||||
# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
|
||||
# Time: 0 ps Iteration: 0 Instance: /tbench/u1_plasma/u1_cpu/u8_mult
|
||||
# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
|
||||
# Time: 0 ps Iteration: 0 Instance: /tbench/u1_plasma/u1_cpu/u4_reg_bank/tri_port_mem
|
||||
# ** Warning: CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, and it has been converted to 0.
|
||||
# Time: 0 ps Iteration: 0 Instance: /tbench/u1_plasma/u1_cpu/u4_reg_bank/tri_port_mem
|
||||
# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
|
||||
# Time: 0 ps Iteration: 0 Instance: /tbench/u1_plasma/u1_cpu/u4_reg_bank/tri_port_mem
|
||||
# ** Warning: CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, and it has been converted to 0.
|
||||
# Time: 0 ps Iteration: 0 Instance: /tbench/u1_plasma/u1_cpu/u4_reg_bank/tri_port_mem
|
||||
# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
|
||||
# Time: 0 ps Iteration: 0 Instance: /tbench/u1_plasma/u1_cpu/u4_reg_bank
|
||||
# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
|
||||
# Time: 0 ps Iteration: 0 Instance: /tbench/u1_plasma/u1_cpu/u4_reg_bank
|
||||
# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
|
||||
# Time: 0 ps Iteration: 0 Instance: /tbench/u1_plasma/u1_cpu/u4_reg_bank
|
||||
# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
|
||||
# Time: 0 ps Iteration: 0 Instance: /tbench/u1_plasma/u1_cpu/u4_reg_bank
|
||||
# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
|
||||
# Time: 0 ps Iteration: 0 Instance: /tbench/u1_plasma/u1_cpu
|
||||
# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
|
||||
# Time: 0 ps Iteration: 1 Instance: /tbench/u1_plasma/u1_cpu/u4_reg_bank/tri_port_mem
|
||||
# ** Warning: CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, and it has been converted to 0.
|
||||
# Time: 0 ps Iteration: 1 Instance: /tbench/u1_plasma/u1_cpu/u4_reg_bank/tri_port_mem
|
||||
# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
|
||||
# Time: 0 ps Iteration: 1 Instance: /tbench/u1_plasma/u1_cpu/u4_reg_bank/tri_port_mem
|
||||
# ** Warning: CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, and it has been converted to 0.
|
||||
# Time: 0 ps Iteration: 1 Instance: /tbench/u1_plasma/u1_cpu/u4_reg_bank/tri_port_mem
|
||||
# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
|
||||
# Time: 0 ps Iteration: 1 Instance: /tbench/u1_plasma/opt_cache2/u_cache
|
||||
# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
|
||||
# Time: 0 ps Iteration: 1 Instance: /tbench/u1_plasma/u1_cpu/u4_reg_bank
|
||||
# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
|
||||
# Time: 0 ps Iteration: 1 Instance: /tbench/u1_plasma/u1_cpu/u4_reg_bank
|
||||
# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
|
||||
# Time: 0 ps Iteration: 1 Instance: /tbench/u1_plasma/u1_cpu/u4_reg_bank
|
||||
# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
|
||||
# Time: 0 ps Iteration: 1 Instance: /tbench/u1_plasma/u1_cpu/u4_reg_bank
|
||||
# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
|
||||
# Time: 0 ps Iteration: 1 Instance: /tbench
|
||||
# ** Warning: CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, and it has been converted to 0.
|
||||
# Time: 0 ps Iteration: 1 Instance: /tbench
|
||||
# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
|
||||
# Time: 0 ps Iteration: 2 Instance: /tbench/u1_plasma/u1_cpu/u4_reg_bank
|
||||
# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
|
||||
# Time: 0 ps Iteration: 2 Instance: /tbench
|
||||
# ** Warning: CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, and it has been converted to 0.
|
||||
# Time: 0 ps Iteration: 2 Instance: /tbench
|
||||
# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
|
||||
# Time: 0 ps Iteration: 2 Instance: /tbench/u1_plasma/opt_cache2/u_cache
|
||||
# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
|
||||
# Time: 0 ps Iteration: 3 Instance: /tbench/u1_plasma/u1_cpu/u4_reg_bank/tri_port_mem
|
||||
# ** Warning: CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, and it has been converted to 0.
|
||||
# Time: 0 ps Iteration: 3 Instance: /tbench/u1_plasma/u1_cpu/u4_reg_bank/tri_port_mem
|
||||
# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
|
||||
# Time: 0 ps Iteration: 3 Instance: /tbench/u1_plasma/u1_cpu/u4_reg_bank/tri_port_mem
|
||||
# ** Warning: CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, and it has been converted to 0.
|
||||
# Time: 0 ps Iteration: 3 Instance: /tbench/u1_plasma/u1_cpu/u4_reg_bank/tri_port_mem
|
||||
# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
|
||||
# Time: 0 ps Iteration: 3 Instance: /tbench/u1_plasma/opt_cache2/u_cache
|
||||
# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
|
||||
# Time: 0 ps Iteration: 4 Instance: /tbench/u1_plasma/u1_cpu/u4_reg_bank/tri_port_mem
|
||||
# ** Warning: CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, and it has been converted to 0.
|
||||
# Time: 0 ps Iteration: 4 Instance: /tbench/u1_plasma/u1_cpu/u4_reg_bank/tri_port_mem
|
||||
# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
|
||||
# Time: 0 ps Iteration: 4 Instance: /tbench/u1_plasma/u1_cpu/u4_reg_bank/tri_port_mem
|
||||
# ** Warning: CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, and it has been converted to 0.
|
||||
# Time: 0 ps Iteration: 4 Instance: /tbench/u1_plasma/u1_cpu/u4_reg_bank/tri_port_mem
|
||||
# Break key hit
|
||||
# Simulation stop requested.
|
119
plasma/logic/tbench.vhd
Normal file
119
plasma/logic/tbench.vhd
Normal file
@ -0,0 +1,119 @@
|
||||
---------------------------------------------------------------------
|
||||
-- TITLE: Test Bench
|
||||
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
|
||||
-- DATE CREATED: 4/21/01
|
||||
-- FILENAME: tbench.vhd
|
||||
-- PROJECT: Plasma CPU core
|
||||
-- COPYRIGHT: Software placed into the public domain by the author.
|
||||
-- Software 'as is' without warranty. Author liable for nothing.
|
||||
-- DESCRIPTION:
|
||||
-- This entity provides a test bench for testing the Plasma CPU core.
|
||||
---------------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use work.mlite_pack.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity tbench is
|
||||
end; --entity tbench
|
||||
|
||||
architecture logic of tbench is
|
||||
constant memory_type : string :=
|
||||
"TRI_PORT_X";
|
||||
-- "DUAL_PORT_";
|
||||
-- "ALTERA_LPM";
|
||||
-- "XILINX_16X";
|
||||
|
||||
constant log_file : string :=
|
||||
-- "UNUSED";
|
||||
"output.txt";
|
||||
|
||||
signal clk : std_logic := '1';
|
||||
signal reset : std_logic := '1';
|
||||
signal interrupt : std_logic := '0';
|
||||
signal mem_write : std_logic;
|
||||
signal address : std_logic_vector(31 downto 2);
|
||||
signal data_write : std_logic_vector(31 downto 0);
|
||||
signal data_read : std_logic_vector(31 downto 0);
|
||||
signal pause1 : std_logic := '0';
|
||||
signal pause2 : std_logic := '0';
|
||||
signal pause : std_logic;
|
||||
signal no_ddr_start: std_logic;
|
||||
signal no_ddr_stop : std_logic;
|
||||
signal byte_we : std_logic_vector(3 downto 0);
|
||||
signal uart_write : std_logic;
|
||||
signal gpioA_in : std_logic_vector(31 downto 0) := (others => '0');
|
||||
begin --architecture
|
||||
--Uncomment the line below to test interrupts
|
||||
interrupt <= '1' after 20 us when interrupt = '0' else '0' after 445 ns;
|
||||
|
||||
clk <= not clk after 50 ns;
|
||||
reset <= '0' after 500 ns;
|
||||
pause1 <= '1' after 700 ns when pause1 = '0' else '0' after 200 ns;
|
||||
pause2 <= '1' after 300 ns when pause2 = '0' else '0' after 200 ns;
|
||||
pause <= pause1 or pause2;
|
||||
gpioA_in(20) <= not gpioA_in(20) after 200 ns; --E_RX_CLK
|
||||
gpioA_in(19) <= not gpioA_in(19) after 20 us; --E_RX_DV
|
||||
gpioA_in(18 downto 15) <= gpioA_in(18 downto 15) + 1 after 400 ns; --E_RX_RXD
|
||||
gpioA_in(14) <= not gpioA_in(14) after 200 ns; --E_TX_CLK
|
||||
|
||||
u1_plasma: plasma
|
||||
generic map (memory_type => memory_type,
|
||||
ethernet => '1',
|
||||
use_cache => '1',
|
||||
log_file => log_file)
|
||||
PORT MAP (
|
||||
clk => clk,
|
||||
reset => reset,
|
||||
uart_read => uart_write,
|
||||
uart_write => uart_write,
|
||||
|
||||
address => address,
|
||||
byte_we => byte_we,
|
||||
data_write => data_write,
|
||||
data_read => data_read,
|
||||
mem_pause_in => pause,
|
||||
no_ddr_start => no_ddr_start,
|
||||
no_ddr_stop => no_ddr_stop,
|
||||
|
||||
gpio0_out => open,
|
||||
gpioA_in => gpioA_in);
|
||||
|
||||
dram_proc: process(clk, address, byte_we, data_write, pause)
|
||||
constant ADDRESS_WIDTH : natural := 16;
|
||||
type storage_array is
|
||||
array(natural range 0 to (2 ** ADDRESS_WIDTH) / 4 - 1) of
|
||||
std_logic_vector(31 downto 0);
|
||||
variable storage : storage_array;
|
||||
variable data : std_logic_vector(31 downto 0);
|
||||
variable index : natural := 0;
|
||||
begin
|
||||
index := conv_integer(address(ADDRESS_WIDTH-1 downto 2));
|
||||
data := storage(index);
|
||||
|
||||
if byte_we(0) = '1' then
|
||||
data(7 downto 0) := data_write(7 downto 0);
|
||||
end if;
|
||||
if byte_we(1) = '1' then
|
||||
data(15 downto 8) := data_write(15 downto 8);
|
||||
end if;
|
||||
if byte_we(2) = '1' then
|
||||
data(23 downto 16) := data_write(23 downto 16);
|
||||
end if;
|
||||
if byte_we(3) = '1' then
|
||||
data(31 downto 24) := data_write(31 downto 24);
|
||||
end if;
|
||||
|
||||
if rising_edge(clk) then
|
||||
if address(30 downto 28) = "001" and byte_we /= "0000" then
|
||||
storage(index) := data;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
if pause = '0' then
|
||||
data_read <= data;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
|
||||
end; --architecture logic
|
181
plasma/logic/uart.vhd
Normal file
181
plasma/logic/uart.vhd
Normal file
@ -0,0 +1,181 @@
|
||||
---------------------------------------------------------------------
|
||||
-- TITLE: UART
|
||||
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
|
||||
-- DATE CREATED: 5/29/02
|
||||
-- FILENAME: uart.vhd
|
||||
-- PROJECT: Plasma CPU core
|
||||
-- COPYRIGHT: Software placed into the public domain by the author.
|
||||
-- Software 'as is' without warranty. Author liable for nothing.
|
||||
-- DESCRIPTION:
|
||||
-- Implements the UART.
|
||||
---------------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_misc.all;
|
||||
use ieee.std_logic_arith.all;
|
||||
use ieee.std_logic_textio.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
use std.textio.all;
|
||||
use work.mlite_pack.all;
|
||||
|
||||
entity uart is
|
||||
generic(log_file : string := "UNUSED");
|
||||
port(clk : in std_logic;
|
||||
reset : in std_logic;
|
||||
enable_read : in std_logic;
|
||||
enable_write : in std_logic;
|
||||
data_in : in std_logic_vector(7 downto 0);
|
||||
data_out : out std_logic_vector(7 downto 0);
|
||||
uart_read : in std_logic;
|
||||
uart_write : out std_logic;
|
||||
busy_write : out std_logic;
|
||||
data_avail : out std_logic);
|
||||
end; --entity uart
|
||||
|
||||
architecture logic of uart is
|
||||
signal delay_write_reg : std_logic_vector(9 downto 0);
|
||||
signal bits_write_reg : std_logic_vector(3 downto 0);
|
||||
signal data_write_reg : std_logic_vector(8 downto 0);
|
||||
signal delay_read_reg : std_logic_vector(9 downto 0);
|
||||
signal bits_read_reg : std_logic_vector(3 downto 0);
|
||||
signal data_read_reg : std_logic_vector(7 downto 0);
|
||||
signal data_save_reg : std_logic_vector(17 downto 0);
|
||||
signal busy_write_sig : std_logic;
|
||||
signal read_value_reg : std_logic_vector(6 downto 0);
|
||||
signal uart_read2 : std_logic;
|
||||
|
||||
begin
|
||||
|
||||
uart_proc: process(clk, reset, enable_read, enable_write, data_in,
|
||||
data_write_reg, bits_write_reg, delay_write_reg,
|
||||
data_read_reg, bits_read_reg, delay_read_reg,
|
||||
data_save_reg, read_value_reg, uart_read2,
|
||||
busy_write_sig, uart_read)
|
||||
constant COUNT_VALUE : std_logic_vector(9 downto 0) :=
|
||||
-- "0100011110"; --33MHz/2/57600Hz = 0x11e
|
||||
-- "1101100100"; --50MHz/57600Hz = 0x364
|
||||
"0110110010"; --25MHz/57600Hz = 0x1b2 -- Plasma IF uses div2
|
||||
-- "0011011001"; --12.5MHz/57600Hz = 0xd9
|
||||
-- "0000000100"; --for debug (shorten read_value_reg)
|
||||
begin
|
||||
uart_read2 <= read_value_reg(read_value_reg'length - 1);
|
||||
|
||||
if reset = '1' then
|
||||
data_write_reg <= ZERO(8 downto 1) & '1';
|
||||
bits_write_reg <= "0000";
|
||||
delay_write_reg <= ZERO(9 downto 0);
|
||||
read_value_reg <= ONES(read_value_reg'length-1 downto 0);
|
||||
data_read_reg <= ZERO(7 downto 0);
|
||||
bits_read_reg <= "0000";
|
||||
delay_read_reg <= ZERO(9 downto 0);
|
||||
data_save_reg <= ZERO(17 downto 0);
|
||||
elsif rising_edge(clk) then
|
||||
|
||||
--Write UART
|
||||
if bits_write_reg = "0000" then --nothing left to write?
|
||||
if enable_write = '1' then
|
||||
delay_write_reg <= ZERO(9 downto 0); --delay before next bit
|
||||
bits_write_reg <= "1010"; --number of bits to write
|
||||
data_write_reg <= data_in & '0'; --remember data & start bit
|
||||
end if;
|
||||
else
|
||||
if delay_write_reg /= COUNT_VALUE then
|
||||
delay_write_reg <= delay_write_reg + 1; --delay before next bit
|
||||
else
|
||||
delay_write_reg <= ZERO(9 downto 0); --reset delay
|
||||
bits_write_reg <= bits_write_reg - 1; --bits left to write
|
||||
data_write_reg <= '1' & data_write_reg(8 downto 1);
|
||||
end if;
|
||||
end if;
|
||||
|
||||
--Average uart_read signal
|
||||
if uart_read = '1' then
|
||||
if read_value_reg /= ONES(read_value_reg'length - 1 downto 0) then
|
||||
read_value_reg <= read_value_reg + 1;
|
||||
end if;
|
||||
else
|
||||
if read_value_reg /= ZERO(read_value_reg'length - 1 downto 0) then
|
||||
read_value_reg <= read_value_reg - 1;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
--Read UART
|
||||
if delay_read_reg = ZERO(9 downto 0) then --done delay for read?
|
||||
if bits_read_reg = "0000" then --nothing left to read?
|
||||
if uart_read2 = '0' then --wait for start bit
|
||||
delay_read_reg <= '0' & COUNT_VALUE(9 downto 1); --half period
|
||||
bits_read_reg <= "1001"; --bits left to read
|
||||
end if;
|
||||
else
|
||||
delay_read_reg <= COUNT_VALUE; --initialize delay
|
||||
bits_read_reg <= bits_read_reg - 1; --bits left to read
|
||||
data_read_reg <= uart_read2 & data_read_reg(7 downto 1);
|
||||
end if;
|
||||
else
|
||||
delay_read_reg <= delay_read_reg - 1; --delay
|
||||
end if;
|
||||
|
||||
--Control character buffer
|
||||
if bits_read_reg = "0000" and delay_read_reg = COUNT_VALUE then
|
||||
if data_save_reg(8) = '0' or
|
||||
(enable_read = '1' and data_save_reg(17) = '0') then
|
||||
--Empty buffer
|
||||
data_save_reg(8 downto 0) <= '1' & data_read_reg;
|
||||
else
|
||||
--Second character in buffer
|
||||
data_save_reg(17 downto 9) <= '1' & data_read_reg;
|
||||
if enable_read = '1' then
|
||||
data_save_reg(8 downto 0) <= data_save_reg(17 downto 9);
|
||||
end if;
|
||||
end if;
|
||||
elsif enable_read = '1' then
|
||||
data_save_reg(17) <= '0'; --data_available
|
||||
data_save_reg(8 downto 0) <= data_save_reg(17 downto 9);
|
||||
end if;
|
||||
end if; --rising_edge(clk)
|
||||
|
||||
uart_write <= data_write_reg(0);
|
||||
if bits_write_reg /= "0000"
|
||||
-- Comment out the following line for full UART simulation (much slower)
|
||||
and log_file = "UNUSED"
|
||||
then
|
||||
busy_write_sig <= '1';
|
||||
else
|
||||
busy_write_sig <= '0';
|
||||
end if;
|
||||
busy_write <= busy_write_sig;
|
||||
data_avail <= data_save_reg(8);
|
||||
data_out <= data_save_reg(7 downto 0);
|
||||
|
||||
end process; --uart_proc
|
||||
|
||||
-- synthesis_off
|
||||
uart_logger:
|
||||
if log_file /= "UNUSED" generate
|
||||
uart_proc: process(clk, enable_write, data_in)
|
||||
file store_file : text open write_mode is log_file;
|
||||
variable hex_file_line : line;
|
||||
variable c : character;
|
||||
variable index : natural;
|
||||
variable line_length : natural := 0;
|
||||
begin
|
||||
if rising_edge(clk) and busy_write_sig = '0' then
|
||||
if enable_write = '1' then
|
||||
index := conv_integer(data_in(6 downto 0));
|
||||
if index /= 10 then
|
||||
c := character'val(index);
|
||||
write(hex_file_line, c);
|
||||
line_length := line_length + 1;
|
||||
end if;
|
||||
if index = 10 or line_length >= 72 then
|
||||
--The following line may have to be commented out for synthesis
|
||||
writeline(store_file, hex_file_line);
|
||||
line_length := 0;
|
||||
end if;
|
||||
end if; --uart_sel
|
||||
end if; --rising_edge(clk)
|
||||
end process; --uart_proc
|
||||
end generate; --uart_logger
|
||||
-- synthesis_on
|
||||
|
||||
end; --architecture logic
|
43
plasma/src/Makefile
Normal file
43
plasma/src/Makefile
Normal file
@ -0,0 +1,43 @@
|
||||
VHDL_DIR = ../logic
|
||||
TOOLS_DIR = ../bin
|
||||
LIB_DIR = ../lib
|
||||
TARGET = bootldr
|
||||
CROSS = mips-elf
|
||||
GCC = $(CROSS)-gcc
|
||||
AS = $(CROSS)-as
|
||||
LD = $(CROSS)-ld
|
||||
DUMP = $(CROSS)-objdump
|
||||
OBJCOPY = $(CROSS)-objcopy
|
||||
INC_PATH = ../include
|
||||
CFLAGS = -O2 -I$(INC_PATH) -Wall -c -s
|
||||
ILDFLAGS = -Ttext 0 -eentry -Map $@.map -s -N
|
||||
LDFLAGS = -Ttext 0x10000000 -eentry -Map $@.map -s -N
|
||||
|
||||
#Internal RAM 0x00
|
||||
#External RAM 0x10000000
|
||||
|
||||
vpath %.c $(LIB_DIR)
|
||||
vpath %.S $(LIB_DIR)
|
||||
|
||||
.c.o:
|
||||
$(GCC) $(CFLAGS) $<
|
||||
.S.o:
|
||||
$(AS) -o $@ $<
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
clean:
|
||||
-rm -rf *.o *.txt *.map *.lst *.bin opcodes_iram opcodes_ram test bootldr
|
||||
|
||||
$(TARGET): crt0.o $(TARGET).o no_os.o ddr_init.o
|
||||
$(LD) $(ILDFLAGS) -o $@ $^
|
||||
$(OBJCOPY) -I elf32-big -O binary $@ $@.bin
|
||||
|
||||
vhdl_mem: $(TARGET)
|
||||
$(TOOLS_DIR)/ramimage $(VHDL_DIR)/ram_xilinx.vhd $@.bin $(VHDL_DIR)/ram_image.vhd
|
||||
|
||||
upload: $(TARGET)
|
||||
sudo cat $^.bin > /dev/ttyUSB0
|
||||
|
||||
run: $(TARGET)
|
||||
$(TOOLS_DIR)/mlite $^.bin
|
265
plasma/src/bootldr.c
Normal file
265
plasma/src/bootldr.c
Normal file
@ -0,0 +1,265 @@
|
||||
/*--------------------------------------------------------------------
|
||||
* TITLE: Plasma Bootloader
|
||||
* AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
|
||||
* DATE CREATED: 12/17/05
|
||||
* FILENAME: bootldr.c
|
||||
* PROJECT: Plasma CPU core
|
||||
* COPYRIGHT: Software placed into the public domain by the author.
|
||||
* Software 'as is' without warranty. Author liable for nothing.
|
||||
* DESCRIPTION:
|
||||
* Plasma bootloader.
|
||||
*--------------------------------------------------------------------*/
|
||||
#include "plasma.h"
|
||||
|
||||
#define MemoryRead(A) (*(volatile unsigned long*)(A))
|
||||
#define MemoryWrite(A,V) *(volatile unsigned long*)(A)=(V)
|
||||
|
||||
extern int putchar(int ch);
|
||||
extern int puts(const char *string);
|
||||
extern int getch(void);
|
||||
extern int kbhit(void);
|
||||
extern int DdrInit(void);
|
||||
|
||||
typedef void (*FuncPtr)(void);
|
||||
typedef unsigned long uint32;
|
||||
typedef unsigned short uint16;
|
||||
|
||||
|
||||
void FlashRead(uint16 *dst, uint32 byteOffset, int bytes)
|
||||
{
|
||||
volatile uint32 *ptr=(uint32*)(FLASH_BASE + (byteOffset << 1));
|
||||
*ptr = 0xff; //read mode
|
||||
while(bytes > 0)
|
||||
{
|
||||
*dst++ = (uint16)*ptr++;
|
||||
bytes -= 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FlashWrite(uint16 *src, uint32 byteOffset, int bytes)
|
||||
{
|
||||
volatile uint32 *ptr=(uint32*)(FLASH_BASE + (byteOffset << 1));
|
||||
while(bytes > 0)
|
||||
{
|
||||
*ptr = 0x40; //write mode
|
||||
*ptr++ = *src++; //write data
|
||||
while((*ptr & 0x80) == 0) //check status
|
||||
;
|
||||
bytes -= 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FlashErase(uint32 byteOffset)
|
||||
{
|
||||
volatile uint32 *ptr=(uint32*)(FLASH_BASE + (byteOffset << 1));
|
||||
*ptr = 0x20; //erase block
|
||||
*ptr = 0xd0; //confirm
|
||||
while((*ptr & 0x80) == 0) //check status
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
char *xtoa(unsigned long num)
|
||||
{
|
||||
static char buf[12];
|
||||
int i, digit;
|
||||
buf[8] = 0;
|
||||
for (i = 7; i >= 0; --i)
|
||||
{
|
||||
digit = num & 0xf;
|
||||
buf[i] = digit + (digit < 10 ? '0' : 'A' - 10);
|
||||
num >>= 4;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
unsigned long getnum(void)
|
||||
{
|
||||
int i;
|
||||
unsigned long ch, ch2, value=0;
|
||||
for(i = 0; i < 16; )
|
||||
{
|
||||
ch = ch2 = getch();
|
||||
if(ch == '\n' || ch == '\r')
|
||||
break;
|
||||
if('0' <= ch && ch <= '9')
|
||||
ch -= '0';
|
||||
else if('A' <= ch && ch <= 'Z')
|
||||
ch = ch - 'A' + 10;
|
||||
else if('a' <= ch && ch <= 'z')
|
||||
ch = ch - 'a' + 10;
|
||||
else if(ch == 8)
|
||||
{
|
||||
if(i > 0)
|
||||
{
|
||||
--i;
|
||||
putchar(ch);
|
||||
putchar(' ');
|
||||
putchar(ch);
|
||||
}
|
||||
value >>= 4;
|
||||
continue;
|
||||
}
|
||||
putchar(ch2);
|
||||
value = (value << 4) + ch;
|
||||
++i;
|
||||
}
|
||||
putchar('\r');
|
||||
putchar('\n');
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int i, j, ch;
|
||||
unsigned long address, value, count;
|
||||
FuncPtr funcPtr;
|
||||
unsigned char *ptr1;
|
||||
|
||||
DdrInit(); //Harmless if SDRAM instead of DDR
|
||||
|
||||
puts("\nGreetings from the bootloader ");
|
||||
puts(__DATE__);
|
||||
puts(" ");
|
||||
puts(__TIME__);
|
||||
puts(":\n");
|
||||
MemoryWrite(FLASH_BASE, 0xff); //read mode
|
||||
if((MemoryRead(GPIOA_IN) & 1) && (MemoryRead(FLASH_BASE) & 0xffff) == 0x3c1c)
|
||||
{
|
||||
puts("Boot from flash\n");
|
||||
FlashRead((uint16*)RAM_EXTERNAL_BASE, 0, 1024*128);
|
||||
funcPtr = (FuncPtr)RAM_EXTERNAL_BASE;
|
||||
funcPtr();
|
||||
}
|
||||
for(;;)
|
||||
{
|
||||
puts("\nWaiting for binary image linked at 0x10000000\n");
|
||||
puts("Other Menu Options:\n");
|
||||
puts("1. Memory read word\n");
|
||||
puts("2. Memory write word\n");
|
||||
puts("3. Memory read byte\n");
|
||||
puts("4. Memory write byte\n");
|
||||
puts("5. Jump to address\n");
|
||||
puts("6. Raw memory read\n");
|
||||
puts("7. Raw memory write\n");
|
||||
puts("8. Checksum\n");
|
||||
puts("9. Dump\n");
|
||||
puts("F. Copy 128KB from DDR to flash\n");
|
||||
puts("> ");
|
||||
ch = getch();
|
||||
address = 0;
|
||||
if('0' <= ch && ch <= '9')
|
||||
{
|
||||
putchar(ch);
|
||||
puts("\nAddress in hex> ");
|
||||
address = getnum();
|
||||
puts("Address = ");
|
||||
puts(xtoa(address));
|
||||
puts("\n");
|
||||
}
|
||||
switch(ch)
|
||||
{
|
||||
case '1':
|
||||
value = MemoryRead(address);
|
||||
puts(xtoa(value));
|
||||
puts("\n");
|
||||
break;
|
||||
case '2':
|
||||
puts("\nValue in hex> ");
|
||||
value = getnum();
|
||||
puts(xtoa(value));
|
||||
MemoryWrite(address, value);
|
||||
break;
|
||||
case '3':
|
||||
value = *(unsigned char*)address;
|
||||
puts(xtoa(value));
|
||||
puts("\n");
|
||||
break;
|
||||
case '4':
|
||||
puts("\nValue in hex> ");
|
||||
value = getnum();
|
||||
puts(xtoa(value));
|
||||
*(unsigned char*)address = value;
|
||||
break;
|
||||
case '5':
|
||||
funcPtr = (FuncPtr)address;
|
||||
funcPtr();
|
||||
break;
|
||||
case '6':
|
||||
puts("\nCount in hex> ");
|
||||
count = getnum();
|
||||
for(i = 0; i < count; ++i)
|
||||
{
|
||||
ch = *(unsigned char*)(address + i);
|
||||
putchar(ch);
|
||||
}
|
||||
break;
|
||||
case '7':
|
||||
puts("\nCount in hex> ");
|
||||
count = getnum();
|
||||
for(i = 0; i < count; ++i)
|
||||
{
|
||||
ch = getch();
|
||||
*(unsigned char*)(address+i) = ch;
|
||||
}
|
||||
break;
|
||||
case '8':
|
||||
puts("\nCount in hex> ");
|
||||
count = getnum();
|
||||
value = 0;
|
||||
for(i = 0; i < count; ++i)
|
||||
{
|
||||
value += *(unsigned char*)(address+i);
|
||||
}
|
||||
puts(xtoa(value));
|
||||
putchar('\n');
|
||||
break;
|
||||
case '9':
|
||||
puts("\nCount in hex> ");
|
||||
count = getnum();
|
||||
value = 0;
|
||||
for(i = 0; i < count; i += 4)
|
||||
{
|
||||
if((i & 15) == 0)
|
||||
puts("\r\n");
|
||||
value = *(unsigned long*)(address+i);
|
||||
puts(xtoa(value));
|
||||
putchar(' ');
|
||||
}
|
||||
puts("\r\n");
|
||||
break;
|
||||
case 'F':
|
||||
puts("\nConfirm with 12345678> ");
|
||||
value = getnum();
|
||||
if(value == 0x12345678)
|
||||
{
|
||||
FlashErase(0);
|
||||
FlashWrite((uint16*)RAM_EXTERNAL_BASE, 0, 1024*128);
|
||||
}
|
||||
break;
|
||||
case 0x3c: //raw test.bin file
|
||||
ptr1 = (unsigned char*)0x10000000;
|
||||
for(i = 0; i < 1024*1024; ++i)
|
||||
{
|
||||
ptr1[i] = (unsigned char)ch;
|
||||
for(j = 0; j < 10000; ++j)
|
||||
{
|
||||
if(kbhit())
|
||||
break;
|
||||
}
|
||||
if(j >= 10000)
|
||||
break; //assume end of file
|
||||
ch = getch();
|
||||
}
|
||||
funcPtr = (FuncPtr)0x10000000;
|
||||
funcPtr();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
24
plasma/tools/Makefile
Normal file
24
plasma/tools/Makefile
Normal file
@ -0,0 +1,24 @@
|
||||
CC_X86 = gcc -Wall -O -g
|
||||
CP = cp
|
||||
RM = rm -rf
|
||||
DWIN32 =
|
||||
BIN_MIPS =
|
||||
VHDL_DIR = ../logic
|
||||
LINUX_PWD = ./
|
||||
CONVERT_BIN = $(LINUX_PWD)convert_bin
|
||||
|
||||
CFLAGS = -O2 -Wall -c -s
|
||||
|
||||
all: ramimage mlite
|
||||
rm -rf ../bin
|
||||
mkdir ../bin; mv ramimage ../bin; mv mlite ../bin
|
||||
|
||||
clean:
|
||||
-$(RM) *.o *.obj *.map *.lst *.hex *.txt
|
||||
|
||||
ramimage: ramimage.c
|
||||
@$(CC_X86) -o ramimage ramimage.c
|
||||
|
||||
mlite: mlite.c
|
||||
@$(CC_X86) -o mlite mlite.c
|
||||
|
999
plasma/tools/mlite.c
Normal file
999
plasma/tools/mlite.c
Normal file
@ -0,0 +1,999 @@
|
||||
/*-------------------------------------------------------------------
|
||||
-- TITLE: Plasma CPU in software. Executes MIPS(tm) opcodes.
|
||||
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
|
||||
-- DATE CREATED: 1/31/01
|
||||
-- FILENAME: mlite.c
|
||||
-- PROJECT: Plasma CPU core
|
||||
-- COPYRIGHT: Software placed into the public domain by the author.
|
||||
-- Software 'as is' without warranty. Author liable for nothing.
|
||||
-- DESCRIPTION:
|
||||
-- Plasma CPU simulator in C code.
|
||||
-- This file served as the starting point for the VHDL code.
|
||||
-- Assumes running on a little endian PC.
|
||||
--------------------------------------------------------------------*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
|
||||
//#define ENABLE_CACHE
|
||||
#define SIMPLE_CACHE
|
||||
|
||||
#define MEM_SIZE (1024*1024*2)
|
||||
#define ntohs(A) ( ((A)>>8) | (((A)&0xff)<<8) )
|
||||
#define htons(A) ntohs(A)
|
||||
#define ntohl(A) ( ((A)>>24) | (((A)&0xff0000)>>8) | (((A)&0xff00)<<8) | ((A)<<24) )
|
||||
#define htonl(A) ntohl(A)
|
||||
|
||||
#ifndef WIN32
|
||||
//Support for Linux
|
||||
#define putch putchar
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void Sleep(unsigned int value)
|
||||
{
|
||||
usleep(value * 1000);
|
||||
}
|
||||
|
||||
int kbhit(void)
|
||||
{
|
||||
struct termios oldt, newt;
|
||||
struct timeval tv;
|
||||
fd_set read_fd;
|
||||
|
||||
tcgetattr(STDIN_FILENO, &oldt);
|
||||
newt = oldt;
|
||||
newt.c_lflag &= ~(ICANON | ECHO);
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
|
||||
tv.tv_sec=0;
|
||||
tv.tv_usec=0;
|
||||
FD_ZERO(&read_fd);
|
||||
FD_SET(0,&read_fd);
|
||||
if(select(1, &read_fd, NULL, NULL, &tv) == -1)
|
||||
return 0;
|
||||
//tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
|
||||
if(FD_ISSET(0,&read_fd))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int getch(void)
|
||||
{
|
||||
struct termios oldt, newt;
|
||||
int ch;
|
||||
|
||||
tcgetattr(STDIN_FILENO, &oldt);
|
||||
newt = oldt;
|
||||
newt.c_lflag &= ~(ICANON | ECHO);
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
|
||||
ch = getchar();
|
||||
//tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
|
||||
return ch;
|
||||
}
|
||||
#else
|
||||
//Support for Windows
|
||||
#include <conio.h>
|
||||
extern void __stdcall Sleep(unsigned long value);
|
||||
#endif
|
||||
|
||||
#define UART_WRITE 0x20000000
|
||||
#define UART_READ 0x20000000
|
||||
#define IRQ_MASK 0x20000010
|
||||
#define IRQ_STATUS 0x20000020
|
||||
#define CONFIG_REG 0x20000070
|
||||
#define MMU_PROCESS_ID 0x20000080
|
||||
#define MMU_FAULT_ADDR 0x20000090
|
||||
#define MMU_TLB 0x200000a0
|
||||
|
||||
#define IRQ_UART_READ_AVAILABLE 0x001
|
||||
#define IRQ_UART_WRITE_AVAILABLE 0x002
|
||||
#define IRQ_COUNTER18_NOT 0x004
|
||||
#define IRQ_COUNTER18 0x008
|
||||
#define IRQ_MMU 0x200
|
||||
|
||||
#define MMU_ENTRIES 4
|
||||
#define MMU_MASK (1024*4-1)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned int virtualAddress;
|
||||
unsigned int physicalAddress;
|
||||
} MmuEntry;
|
||||
|
||||
typedef struct {
|
||||
int r[32];
|
||||
int pc, pc_next, epc;
|
||||
unsigned int hi;
|
||||
unsigned int lo;
|
||||
int status;
|
||||
int userMode;
|
||||
int processId;
|
||||
int exceptionId;
|
||||
int faultAddr;
|
||||
int irqStatus;
|
||||
int skip;
|
||||
unsigned char *mem;
|
||||
int wakeup;
|
||||
int big_endian;
|
||||
MmuEntry mmuEntry[MMU_ENTRIES];
|
||||
} State;
|
||||
|
||||
static char *opcode_string[]={
|
||||
"SPECIAL","REGIMM","J","JAL","BEQ","BNE","BLEZ","BGTZ",
|
||||
"ADDI","ADDIU","SLTI","SLTIU","ANDI","ORI","XORI","LUI",
|
||||
"COP0","COP1","COP2","COP3","BEQL","BNEL","BLEZL","BGTZL",
|
||||
"?","?","?","?","?","?","?","?",
|
||||
"LB","LH","LWL","LW","LBU","LHU","LWR","?",
|
||||
"SB","SH","SWL","SW","?","?","SWR","CACHE",
|
||||
"LL","LWC1","LWC2","LWC3","?","LDC1","LDC2","LDC3"
|
||||
"SC","SWC1","SWC2","SWC3","?","SDC1","SDC2","SDC3"
|
||||
};
|
||||
|
||||
static char *special_string[]={
|
||||
"SLL","?","SRL","SRA","SLLV","?","SRLV","SRAV",
|
||||
"JR","JALR","MOVZ","MOVN","SYSCALL","BREAK","?","SYNC",
|
||||
"MFHI","MTHI","MFLO","MTLO","?","?","?","?",
|
||||
"MULT","MULTU","DIV","DIVU","?","?","?","?",
|
||||
"ADD","ADDU","SUB","SUBU","AND","OR","XOR","NOR",
|
||||
"?","?","SLT","SLTU","?","DADDU","?","?",
|
||||
"TGE","TGEU","TLT","TLTU","TEQ","?","TNE","?",
|
||||
"?","?","?","?","?","?","?","?"
|
||||
};
|
||||
|
||||
static char *regimm_string[]={
|
||||
"BLTZ","BGEZ","BLTZL","BGEZL","?","?","?","?",
|
||||
"TGEI","TGEIU","TLTI","TLTIU","TEQI","?","TNEI","?",
|
||||
"BLTZAL","BEQZAL","BLTZALL","BGEZALL","?","?","?","?",
|
||||
"?","?","?","?","?","?","?","?"
|
||||
};
|
||||
|
||||
static unsigned int HWMemory[8];
|
||||
|
||||
|
||||
static int mem_read(State *s, int size, unsigned int address)
|
||||
{
|
||||
unsigned int value=0, ptr;
|
||||
|
||||
s->irqStatus |= IRQ_UART_WRITE_AVAILABLE;
|
||||
switch(address)
|
||||
{
|
||||
case UART_READ:
|
||||
if(kbhit())
|
||||
HWMemory[0] = getch();
|
||||
s->irqStatus &= ~IRQ_UART_READ_AVAILABLE; //clear bit
|
||||
return HWMemory[0];
|
||||
case IRQ_MASK:
|
||||
return HWMemory[1];
|
||||
case IRQ_MASK + 4:
|
||||
Sleep(10);
|
||||
return 0;
|
||||
case IRQ_STATUS:
|
||||
if(kbhit())
|
||||
s->irqStatus |= IRQ_UART_READ_AVAILABLE;
|
||||
return s->irqStatus;
|
||||
case MMU_PROCESS_ID:
|
||||
return s->processId;
|
||||
case MMU_FAULT_ADDR:
|
||||
return s->faultAddr;
|
||||
}
|
||||
|
||||
ptr = (unsigned int)s->mem + (address % MEM_SIZE);
|
||||
|
||||
if(0x10000000 <= address && address < 0x10000000 + 1024*1024)
|
||||
ptr += 1024*1024;
|
||||
|
||||
switch(size)
|
||||
{
|
||||
case 4:
|
||||
if(address & 3)
|
||||
printf("Unaligned access PC=0x%x address=0x%x\n", (int)s->pc, (int)address);
|
||||
assert((address & 3) == 0);
|
||||
value = *(int*)ptr;
|
||||
if(s->big_endian)
|
||||
value = ntohl(value);
|
||||
break;
|
||||
case 2:
|
||||
assert((address & 1) == 0);
|
||||
value = *(unsigned short*)ptr;
|
||||
if(s->big_endian)
|
||||
value = ntohs((unsigned short)value);
|
||||
break;
|
||||
case 1:
|
||||
value = *(unsigned char*)ptr;
|
||||
break;
|
||||
default:
|
||||
printf("ERROR");
|
||||
}
|
||||
return(value);
|
||||
}
|
||||
|
||||
static void mem_write(State *s, int size, int unsigned address, unsigned int value)
|
||||
{
|
||||
unsigned int ptr;
|
||||
|
||||
switch(address)
|
||||
{
|
||||
case UART_WRITE:
|
||||
putch(value);
|
||||
fflush(stdout);
|
||||
return;
|
||||
case IRQ_MASK:
|
||||
HWMemory[1] = value;
|
||||
return;
|
||||
case IRQ_STATUS:
|
||||
s->irqStatus = value;
|
||||
return;
|
||||
case CONFIG_REG:
|
||||
return;
|
||||
case MMU_PROCESS_ID:
|
||||
//printf("processId=%d\n", value);
|
||||
s->processId = value;
|
||||
return;
|
||||
}
|
||||
|
||||
if(MMU_TLB <= address && address <= MMU_TLB+MMU_ENTRIES * 8)
|
||||
{
|
||||
//printf("TLB 0x%x 0x%x\n", address - MMU_TLB, value);
|
||||
ptr = (unsigned int)s->mmuEntry + address - MMU_TLB;
|
||||
*(int*)ptr = value;
|
||||
s->irqStatus &= ~IRQ_MMU;
|
||||
return;
|
||||
}
|
||||
|
||||
ptr = (unsigned int)s->mem + (address % MEM_SIZE);
|
||||
|
||||
if(0x10000000 <= address && address < 0x10000000 + 1024*1024)
|
||||
ptr += 1024*1024;
|
||||
|
||||
switch(size)
|
||||
{
|
||||
case 4:
|
||||
assert((address & 3) == 0);
|
||||
if(s->big_endian)
|
||||
value = htonl(value);
|
||||
*(int*)ptr = value;
|
||||
break;
|
||||
case 2:
|
||||
assert((address & 1) == 0);
|
||||
if(s->big_endian)
|
||||
value = htons((unsigned short)value);
|
||||
*(short*)ptr = (unsigned short)value;
|
||||
break;
|
||||
case 1:
|
||||
*(char*)ptr = (unsigned char)value;
|
||||
break;
|
||||
default:
|
||||
printf("ERROR");
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ENABLE_CACHE
|
||||
/************* Optional MMU and cache implementation *************/
|
||||
/* TAG = VirtualAddress | ProcessId | WriteableBit */
|
||||
unsigned int mmu_lookup(State *s, unsigned int processId,
|
||||
unsigned int address, int write)
|
||||
{
|
||||
int i;
|
||||
unsigned int compare, tag;
|
||||
|
||||
if(processId == 0 || s->userMode == 0)
|
||||
return address;
|
||||
//if(address < 0x30000000)
|
||||
// return address;
|
||||
compare = (address & ~MMU_MASK) | (processId << 1);
|
||||
for(i = 0; i < MMU_ENTRIES; ++i)
|
||||
{
|
||||
tag = s->mmuEntry[i].virtualAddress;
|
||||
if((tag & ~1) == compare && (write == 0 || (tag & 1)))
|
||||
return s->mmuEntry[i].physicalAddress | (address & MMU_MASK);
|
||||
}
|
||||
//printf("\nMMUTlbMiss 0x%x PC=0x%x w=%d pid=%d user=%d\n",
|
||||
// address, s->pc, write, processId, s->userMode);
|
||||
//printf("m");
|
||||
s->exceptionId = 1;
|
||||
s->faultAddr = address & ~MMU_MASK;
|
||||
s->irqStatus |= IRQ_MMU;
|
||||
return address;
|
||||
}
|
||||
|
||||
|
||||
#define CACHE_SET_ASSOC_LN2 0
|
||||
#define CACHE_SET_ASSOC (1 << CACHE_SET_ASSOC_LN2)
|
||||
#define CACHE_SIZE_LN2 (13 - CACHE_SET_ASSOC_LN2) //8 KB
|
||||
#define CACHE_SIZE (1 << CACHE_SIZE_LN2)
|
||||
#define CACHE_LINE_SIZE_LN2 2 //4 bytes
|
||||
#define CACHE_LINE_SIZE (1 << CACHE_LINE_SIZE_LN2)
|
||||
|
||||
static int cacheData[CACHE_SET_ASSOC][CACHE_SIZE/sizeof(int)];
|
||||
static int cacheAddr[CACHE_SET_ASSOC][CACHE_SIZE/CACHE_LINE_SIZE];
|
||||
static int cacheSetNext;
|
||||
static int cacheMiss, cacheWriteBack, cacheCount;
|
||||
|
||||
static void cache_init(void)
|
||||
{
|
||||
int set, i;
|
||||
for(set = 0; set < CACHE_SET_ASSOC; ++set)
|
||||
{
|
||||
for(i = 0; i < CACHE_SIZE/CACHE_LINE_SIZE; ++i)
|
||||
cacheAddr[set][i] = 0xffff0000;
|
||||
}
|
||||
}
|
||||
|
||||
/* Write-back cache memory tagged by virtual address and processId */
|
||||
/* TAG = virtualAddress | processId | dirtyBit */
|
||||
static int cache_load(State *s, unsigned int address, int write)
|
||||
{
|
||||
int set, i, pid, miss, offsetAddr, offsetData, offsetMem;
|
||||
unsigned int addrTagMatch, addrPrevMatch=0;
|
||||
unsigned int addrPrev;
|
||||
unsigned int addressPhysical, tag;
|
||||
|
||||
++cacheCount;
|
||||
addrTagMatch = address & ~(CACHE_SIZE-1);
|
||||
offsetAddr = (address & (CACHE_SIZE-1)) >> CACHE_LINE_SIZE_LN2;
|
||||
|
||||
/* Find match */
|
||||
miss = 1;
|
||||
for(set = 0; set < CACHE_SET_ASSOC; ++set)
|
||||
{
|
||||
addrPrevMatch = cacheAddr[set][offsetAddr] & ~(CACHE_SIZE-1);
|
||||
if(addrPrevMatch == addrTagMatch)
|
||||
{
|
||||
miss = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Cache miss? */
|
||||
if(miss)
|
||||
{
|
||||
++cacheMiss;
|
||||
set = cacheSetNext;
|
||||
cacheSetNext = (cacheSetNext + 1) & (CACHE_SET_ASSOC-1);
|
||||
}
|
||||
//else if(write || (address >> 28) != 0x1)
|
||||
//{
|
||||
// tag = cacheAddr[set][offsetAddr];
|
||||
// pid = (tag & (CACHE_SIZE-1)) >> 1;
|
||||
// if(pid != s->processId)
|
||||
// miss = 1;
|
||||
//}
|
||||
|
||||
if(miss)
|
||||
{
|
||||
offsetData = address & (CACHE_SIZE-1) & ~(CACHE_LINE_SIZE-1);
|
||||
|
||||
/* Cache line dirty? */
|
||||
if(cacheAddr[set][offsetAddr] & 1)
|
||||
{
|
||||
/* Write back cache line */
|
||||
tag = cacheAddr[set][offsetAddr];
|
||||
addrPrev = tag & ~(CACHE_SIZE-1);
|
||||
addrPrev |= address & (CACHE_SIZE-1);
|
||||
pid = (tag & (CACHE_SIZE-1)) >> 1;
|
||||
addressPhysical = mmu_lookup(s, pid, addrPrev, 1); //virtual->physical
|
||||
if(s->exceptionId)
|
||||
return 0;
|
||||
offsetMem = addressPhysical & ~(CACHE_LINE_SIZE-1);
|
||||
for(i = 0; i < CACHE_LINE_SIZE; i += 4)
|
||||
mem_write(s, 4, offsetMem + i, cacheData[set][(offsetData + i) >> 2]);
|
||||
++cacheWriteBack;
|
||||
}
|
||||
|
||||
/* Read cache line */
|
||||
addressPhysical = mmu_lookup(s, s->processId, address, write); //virtual->physical
|
||||
if(s->exceptionId)
|
||||
return 0;
|
||||
offsetMem = addressPhysical & ~(CACHE_LINE_SIZE-1);
|
||||
cacheAddr[set][offsetAddr] = addrTagMatch;
|
||||
for(i = 0; i < CACHE_LINE_SIZE; i += 4)
|
||||
cacheData[set][(offsetData + i) >> 2] = mem_read(s, 4, offsetMem + i);
|
||||
}
|
||||
cacheAddr[set][offsetAddr] |= write;
|
||||
return set;
|
||||
}
|
||||
|
||||
static int cache_read(State *s, int size, unsigned int address)
|
||||
{
|
||||
int set, offset;
|
||||
int value;
|
||||
|
||||
if((address & 0xfe000000) != 0x10000000)
|
||||
return mem_read(s, size, address);
|
||||
|
||||
set = cache_load(s, address, 0);
|
||||
if(s->exceptionId)
|
||||
return 0;
|
||||
offset = (address & (CACHE_SIZE-1)) >> 2;
|
||||
value = cacheData[set][offset];
|
||||
if(s->big_endian)
|
||||
address ^= 3;
|
||||
switch(size)
|
||||
{
|
||||
case 2:
|
||||
value = (value >> ((address & 2) << 3)) & 0xffff;
|
||||
break;
|
||||
case 1:
|
||||
value = (value >> ((address & 3) << 3)) & 0xff;
|
||||
break;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
static void cache_write(State *s, int size, int unsigned address, unsigned int value)
|
||||
{
|
||||
int set, offset;
|
||||
unsigned int mask;
|
||||
|
||||
if((address >> 28) != 0x1) // && (s->processId == 0 || s->userMode == 0))
|
||||
{
|
||||
mem_write(s, size, address, value);
|
||||
return;
|
||||
}
|
||||
|
||||
set = cache_load(s, address, 1);
|
||||
if(s->exceptionId)
|
||||
return;
|
||||
offset = (address & (CACHE_SIZE-1)) >> 2;
|
||||
if(s->big_endian)
|
||||
address ^= 3;
|
||||
switch(size)
|
||||
{
|
||||
case 2:
|
||||
value &= 0xffff;
|
||||
value |= value << 16;
|
||||
mask = 0xffff << ((address & 2) << 3);
|
||||
break;
|
||||
case 1:
|
||||
value &= 0xff;
|
||||
value |= (value << 8) | (value << 16) | (value << 24);
|
||||
mask = 0xff << ((address & 3) << 3);
|
||||
break;
|
||||
case 4:
|
||||
default:
|
||||
mask = 0xffffffff;
|
||||
break;
|
||||
}
|
||||
cacheData[set][offset] = (value & mask) | (cacheData[set][offset] & ~mask);
|
||||
}
|
||||
|
||||
#define mem_read cache_read
|
||||
#define mem_write cache_write
|
||||
|
||||
#else
|
||||
static void cache_init(void) {}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef SIMPLE_CACHE
|
||||
|
||||
//Write through direct mapped 4KB cache
|
||||
#define CACHE_MISS 0x1ff
|
||||
static unsigned int cacheData[1024];
|
||||
static unsigned int cacheAddr[1024]; //9-bit addresses
|
||||
static int cacheTry, cacheMiss, cacheInit;
|
||||
|
||||
static int cache_read(State *s, int size, unsigned int address)
|
||||
{
|
||||
int offset;
|
||||
unsigned int value, value2, address2=address;
|
||||
|
||||
if(cacheInit == 0)
|
||||
{
|
||||
cacheInit = 1;
|
||||
for(offset = 0; offset < 1024; ++offset)
|
||||
cacheAddr[offset] = CACHE_MISS;
|
||||
}
|
||||
|
||||
offset = address >> 20;
|
||||
if(offset != 0x100 && offset != 0x101)
|
||||
return mem_read(s, size, address);
|
||||
|
||||
++cacheTry;
|
||||
offset = (address >> 2) & 0x3ff;
|
||||
if(cacheAddr[offset] != (address >> 12) || cacheAddr[offset] == CACHE_MISS)
|
||||
{
|
||||
++cacheMiss;
|
||||
cacheAddr[offset] = address >> 12;
|
||||
cacheData[offset] = mem_read(s, 4, address & ~3);
|
||||
}
|
||||
value = cacheData[offset];
|
||||
if(s->big_endian)
|
||||
address ^= 3;
|
||||
switch(size)
|
||||
{
|
||||
case 2:
|
||||
value = (value >> ((address & 2) << 3)) & 0xffff;
|
||||
break;
|
||||
case 1:
|
||||
value = (value >> ((address & 3) << 3)) & 0xff;
|
||||
break;
|
||||
}
|
||||
|
||||
//Debug testing
|
||||
value2 = mem_read(s, size, address2);
|
||||
if(value != value2)
|
||||
printf("miss match\n");
|
||||
//if((cacheTry & 0xffff) == 0) printf("\n***cache(%d,%d)\n ", cacheMiss, cacheTry);
|
||||
return value;
|
||||
}
|
||||
|
||||
static void cache_write(State *s, int size, int unsigned address, unsigned int value)
|
||||
{
|
||||
int offset;
|
||||
|
||||
mem_write(s, size, address, value);
|
||||
|
||||
offset = address >> 20;
|
||||
if(offset != 0x100 && offset != 0x101)
|
||||
return;
|
||||
|
||||
offset = (address >> 2) & 0x3ff;
|
||||
if(size != 4)
|
||||
{
|
||||
cacheAddr[offset] = CACHE_MISS;
|
||||
return;
|
||||
}
|
||||
cacheAddr[offset] = address >> 12;
|
||||
cacheData[offset] = value;
|
||||
}
|
||||
|
||||
#define mem_read cache_read
|
||||
#define mem_write cache_write
|
||||
#endif //SIMPLE_CACHE
|
||||
/************* End optional cache implementation *************/
|
||||
|
||||
|
||||
void mult_big(unsigned int a,
|
||||
unsigned int b,
|
||||
unsigned int *hi,
|
||||
unsigned int *lo)
|
||||
{
|
||||
unsigned int ahi, alo, bhi, blo;
|
||||
unsigned int c0, c1, c2;
|
||||
unsigned int c1_a, c1_b;
|
||||
|
||||
ahi = a >> 16;
|
||||
alo = a & 0xffff;
|
||||
bhi = b >> 16;
|
||||
blo = b & 0xffff;
|
||||
|
||||
c0 = alo * blo;
|
||||
c1_a = ahi * blo;
|
||||
c1_b = alo * bhi;
|
||||
c2 = ahi * bhi;
|
||||
|
||||
c2 += (c1_a >> 16) + (c1_b >> 16);
|
||||
c1 = (c1_a & 0xffff) + (c1_b & 0xffff) + (c0 >> 16);
|
||||
c2 += (c1 >> 16);
|
||||
c0 = (c1 << 16) + (c0 & 0xffff);
|
||||
*hi = c2;
|
||||
*lo = c0;
|
||||
}
|
||||
|
||||
void mult_big_signed(int a,
|
||||
int b,
|
||||
unsigned int *hi,
|
||||
unsigned int *lo)
|
||||
{
|
||||
unsigned int ahi, alo, bhi, blo;
|
||||
unsigned int c0, c1, c2;
|
||||
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;
|
||||
}
|
||||
|
||||
//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);
|
||||
}
|
||||
|
112
plasma/tools/ramimage.c
Normal file
112
plasma/tools/ramimage.c
Normal file
@ -0,0 +1,112 @@
|
||||
/* ram_image.c by Steve Rhoads 11/7/05
|
||||
* This program take the ram_xilinx.vhd file as input
|
||||
* and the code.txt file as input.
|
||||
* It then creates ram_image.vhd as output with the
|
||||
* initialization vectors set to the contents of code.txt.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define BUF_SIZE (1024*1024)
|
||||
|
||||
unsigned int swap_int (unsigned int data)
|
||||
{
|
||||
unsigned char* b=(unsigned char*)&data;
|
||||
unsigned char t;
|
||||
t=b[3]; b[3]=b[0]; b[0]=t;
|
||||
t=b[2]; b[2]=b[1]; b[1]=t;
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
FILE *file;
|
||||
int i, j, index, size, count;
|
||||
char *buf, *ptr, *ptr_list[64*4], text[80];
|
||||
unsigned int *code;
|
||||
|
||||
if(argc < 4)
|
||||
{
|
||||
printf("Usage: ram_image <in.vhd> <file.bin> <out.vhd>\n");
|
||||
printf("Usage: ram_image ram_xilinx.vhd <file.bin> ram_image.vhd\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
buf = (char*)malloc(BUF_SIZE);
|
||||
code = (unsigned int*)malloc(BUF_SIZE);
|
||||
|
||||
//Read ram_xilinx.vhd
|
||||
file = fopen(argv[1], "rb");
|
||||
if(file == NULL)
|
||||
{
|
||||
printf("Can't open %s!\n", argv[1]);
|
||||
return -1;
|
||||
}
|
||||
size = fread(buf, 1, BUF_SIZE, file);
|
||||
fclose(file);
|
||||
|
||||
//Read binary file
|
||||
file = fopen(argv[2], "r");
|
||||
if(file == NULL)
|
||||
{
|
||||
printf("Can't open %s!\n", argv[2]);
|
||||
return -1;
|
||||
}
|
||||
for(count = 0; count < 16*1024; ++count)
|
||||
{
|
||||
if(feof(file))
|
||||
break;
|
||||
fread ( &code[count], 1, sizeof(unsigned int), file);
|
||||
}
|
||||
fclose(file);
|
||||
|
||||
//Find 'INIT_00 => X"'
|
||||
ptr = buf;
|
||||
for(i = 0; i < 64*4; ++i)
|
||||
{
|
||||
sprintf(text, "INIT_%2.2X => X\"", i % 64);
|
||||
ptr = strstr(ptr, text);
|
||||
if(ptr == NULL)
|
||||
{
|
||||
printf("ERROR: Can't find '%s' in file!\n", text);
|
||||
return -1;
|
||||
}
|
||||
ptr_list[i] = ptr + strlen(text);
|
||||
}
|
||||
|
||||
//Modify vhdl source code
|
||||
//ptr_list[64*4] four banks of 64 bytes: Bank0 D31-D24 Bank1 D23-D16 Bank2 D15-D8 Bank3 D7-D0
|
||||
j = 62;
|
||||
for(i = 0; i < count; ++i)
|
||||
{
|
||||
sprintf(text, "%8.8x", swap_int(code[i]));
|
||||
index = i / 32;
|
||||
ptr_list[index][j] = text[0]; // Bank0 D31- D28
|
||||
ptr_list[index][j+1] = text[1]; // Bank0 D27- D24
|
||||
ptr_list[index+64][j] = text[2]; // Bank0 D23- D20
|
||||
ptr_list[index+64][j+1] = text[3]; // Bank0 D19- D16
|
||||
ptr_list[index+128][j] = text[4]; // Bank0 D15- D12
|
||||
ptr_list[index+128][j+1] = text[5]; // Bank0 D11- D8
|
||||
ptr_list[index+192][j] = text[6]; // Bank0 D7 - D4
|
||||
ptr_list[index+192][j+1] = text[7]; // Bank0 D3 - D0
|
||||
j -= 2;
|
||||
if(j < 0)
|
||||
j = 62;
|
||||
}
|
||||
|
||||
//Write ram_image.vhd
|
||||
file = fopen(argv[3], "wb");
|
||||
if(file == NULL)
|
||||
{
|
||||
printf("Can't write %s!\n", argv[3]);
|
||||
return -1;
|
||||
}
|
||||
fwrite(buf, 1, size, file);
|
||||
fclose(file);
|
||||
free(buf);
|
||||
free(code);
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user