Adding plasma example

This commit is contained in:
Carlos Camargo 2010-04-21 20:01:38 -05:00
parent f80360a678
commit 22c469585b
59 changed files with 18082 additions and 0 deletions

52
plasma/include/plasma.h Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

71
plasma/kernel/os_stubs.c Normal file
View 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

File diff suppressed because it is too large Load Diff

377
plasma/kernel/rtos.h Normal file
View 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
View 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

File diff suppressed because it is too large Load Diff

131
plasma/kernel/tcpip.h Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

Binary file not shown.

Binary file not shown.

183
plasma/logic/eth_dma.vhd Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

View 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

View 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

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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;
}