Date:2010-04-22 03:01:38 (13 years 11 months ago)
Author:Carlos Camargo
Commit:22c469585bd1f73b2ffd641d71b2caf1405cf281
Message:Adding plasma example

Files: plasma/include/plasma.h (1 diff)
plasma/kernel/dll.h (1 diff)
plasma/kernel/dlltest.c (1 diff)
plasma/kernel/ethernet.c (1 diff)
plasma/kernel/filesys.c (1 diff)
plasma/kernel/flash.c (1 diff)
plasma/kernel/http.c (1 diff)
plasma/kernel/libc.c (1 diff)
plasma/kernel/makefile (1 diff)
plasma/kernel/math.c (1 diff)
plasma/kernel/netutil.c (1 diff)
plasma/kernel/os_stubs.c (1 diff)
plasma/kernel/rtos.c (1 diff)
plasma/kernel/rtos.h (1 diff)
plasma/kernel/rtos_test.c (1 diff)
plasma/kernel/tcpip.c (1 diff)
plasma/kernel/tcpip.h (1 diff)
plasma/kernel/uart.c (1 diff)
plasma/lib/crt0.S (1 diff)
plasma/lib/ddr_init.c (1 diff)
plasma/lib/no_os.c (1 diff)
plasma/logic/Makefile (1 diff)
plasma/logic/_impact.cmd (1 diff)
plasma/logic/alu.vhd (1 diff)
plasma/logic/bus_mux.vhd (1 diff)
plasma/logic/cache.vhd (1 diff)
plasma/logic/code.txt (1 diff)
plasma/logic/control.vhd (1 diff)
plasma/logic/ddr_ctrl.vhd (1 diff)
plasma/logic/default.ipf (0 diffs)
plasma/logic/default.ipf_ISE_Backup (0 diffs)
plasma/logic/eth_dma.vhd (1 diff)
plasma/logic/mem_ctrl.vhd (1 diff)
plasma/logic/mlite_cpu.vhd (1 diff)
plasma/logic/mlite_pack.vhd (1 diff)
plasma/logic/mult.vhd (1 diff)
plasma/logic/pc_next.vhd (1 diff)
plasma/logic/pipeline.vhd (1 diff)
plasma/logic/plasma.vhd (1 diff)
plasma/logic/plasma_3e.ucf (1 diff)
plasma/logic/plasma_3e.vhd (1 diff)
plasma/logic/plasma_if.ucf (1 diff)
plasma/logic/plasma_if.vhd (1 diff)
plasma/logic/prog.cmd (1 diff)
plasma/logic/ram.vhd (1 diff)
plasma/logic/ram_image.vhd (1 diff)
plasma/logic/ram_xilinx.vhd (1 diff)
plasma/logic/reg_bank.vhd (1 diff)
plasma/logic/shifter.vhd (1 diff)
plasma/logic/simulation/output.txt (1 diff)
plasma/logic/simulation/plasma_3e_TB.do (1 diff)
plasma/logic/simulation/transcript (1 diff)
plasma/logic/tbench.vhd (1 diff)
plasma/logic/uart.vhd (1 diff)
plasma/src/Makefile (1 diff)
plasma/src/bootldr.c (1 diff)
plasma/tools/Makefile (1 diff)
plasma/tools/mlite.c (1 diff)
plasma/tools/ramimage.c (1 diff)

Change Details

plasma/include/plasma.h
1/*--------------------------------------------------------------------
2 * TITLE: Plasma Hardware Defines
3 * AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4 * DATE CREATED: 12/17/05
5 * FILENAME: plasma.h
6 * PROJECT: Plasma CPU core
7 * COPYRIGHT: Software placed into the public domain by the author.
8 * Software 'as is' without warranty. Author liable for nothing.
9 * DESCRIPTION:
10 * Plasma Hardware Defines
11 *--------------------------------------------------------------------*/
12#ifndef __PLASMA_H__
13#define __PLASMA_H__
14
15/*********** Hardware addesses ***********/
16#define RAM_INTERNAL_BASE 0x00000000 //8KB
17#define RAM_EXTERNAL_BASE 0x10000000 //1MB
18#define RAM_EXTERNAL_SIZE 0x00100000
19#define MISC_BASE 0x20000000
20#define UART_WRITE 0x20000000
21#define UART_READ 0x20000000
22#define IRQ_MASK 0x20000010
23#define IRQ_STATUS 0x20000020
24#define GPIO0_OUT 0x20000030
25#define GPIO0_CLEAR 0x20000040
26#define GPIOA_IN 0x20000050
27#define COUNTER_REG 0x20000060
28#define ETHERNET_REG 0x20000070
29#define FLASH_BASE 0x30000000
30
31/*********** GPIO out bits ***************/
32#define ETHERNET_MDIO 0x00200000
33#define ETHERNET_MDIO_WE 0x00400000
34#define ETHERENT_MDC 0x00800000
35#define ETHERNET_ENABLE 0x01000000
36
37/*********** Interrupt bits **************/
38#define IRQ_UART_READ_AVAILABLE 0x01
39#define IRQ_UART_WRITE_AVAILABLE 0x02
40#define IRQ_COUNTER18_NOT 0x04
41#define IRQ_COUNTER18 0x08
42#define IRQ_ETHERNET_RECEIVE 0x10
43#define IRQ_ETHERNET_TRANSMIT 0x20
44#define IRQ_GPIO31_NOT 0x40
45#define IRQ_GPIO31 0x80
46
47/*********** Ethernet buffers ************/
48#define ETHERNET_RECEIVE 0x13ff0000
49#define ETHERNET_TRANSMIT 0x13fe0000
50
51#endif //__PLASMA_H__
52
plasma/kernel/dll.h
1/*--------------------------------------------------------------------
2 * TITLE: Plasma Dynamic Link Library
3 * AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4 * DATE CREATED: 4/4/08
5 * FILENAME: dll.h
6 * PROJECT: Plasma CPU core
7 * COPYRIGHT: Software placed into the public domain by the author.
8 * Software 'as is' without warranty. Author liable for nothing.
9 * DESCRIPTION:
10 * Dynamic Link Library
11 *--------------------------------------------------------------------*/
12#ifndef __DLL_H__
13#define __DLL_H__
14
15#define INCLUDE_FILESYS
16#include "rtos.h"
17#include "tcpip.h"
18
19typedef void *(*DllFunc)();
20
21// Included by Plasma Kernel to create array of function pointers
22#ifdef DLL_SETUP
23
24void *DllDummy(void) { printf("Dummy"); return NULL; }
25
26const DllFunc DllFuncList[] = {
27   (DllFunc)strcpy,
28   (DllFunc)strncpy,
29   (DllFunc)strcat,
30   (DllFunc)strncat,
31   (DllFunc)strcmp,
32   (DllFunc)strncmp,
33   (DllFunc)strstr,
34   (DllFunc)strlen,
35   (DllFunc)memcpy,
36   (DllFunc)memmove,
37   (DllFunc)memcmp,
38   (DllFunc)memset,
39   (DllFunc)abs,
40   (DllFunc)rand,
41   (DllFunc)srand,
42   (DllFunc)strtol,
43   (DllFunc)atoi,
44   (DllFunc)itoa,
45   (DllFunc)sprintf,
46   (DllFunc)sscanf,
47#ifdef INCLUDE_DUMP
48   (DllFunc)dump,
49#else //INCLUDE_DUMP
50   DllDummy,
51#endif //INCLUDE_DUMP
52#ifdef INCLUDE_QSORT
53   (DllFunc)qsort,
54   (DllFunc)bsearch,
55#else //INCLUDE_QSORT
56   DllDummy,
57   DllDummy,
58#endif //INCLUDE_QSORT
59#ifdef INCLUDE_TIMELIB
60   (DllFunc)mktime,
61   (DllFunc)gmtime_r,
62   (DllFunc)gmtimeDst,
63   (DllFunc)gmtimeDstSet,
64#else //INCLUDE_TIMELIB
65   DllDummy,
66   DllDummy,
67   DllDummy,
68   DllDummy,
69#endif //INCLUDE_TIMELIB
70   (DllFunc)OS_AsmInterruptEnable,
71   (DllFunc)OS_HeapCreate,
72   (DllFunc)OS_HeapDestroy,
73   (DllFunc)OS_HeapMalloc,
74   (DllFunc)OS_HeapFree,
75   (DllFunc)OS_HeapAlternate,
76   (DllFunc)OS_HeapRegister,
77   (DllFunc)OS_ThreadCreate,
78   (DllFunc)OS_ThreadExit,
79   (DllFunc)OS_ThreadSelf,
80   (DllFunc)OS_ThreadSleep,
81   (DllFunc)OS_ThreadTime,
82   (DllFunc)OS_ThreadInfoSet,
83   (DllFunc)OS_ThreadInfoGet,
84   (DllFunc)OS_ThreadPriorityGet,
85   (DllFunc)OS_ThreadPrioritySet,
86   (DllFunc)OS_ThreadProcessId,
87   (DllFunc)OS_ThreadCpuLock,
88   (DllFunc)OS_SemaphoreCreate,
89   (DllFunc)OS_SemaphoreDelete,
90   (DllFunc)OS_SemaphorePend,
91   (DllFunc)OS_SemaphorePost,
92   (DllFunc)OS_MutexCreate,
93   (DllFunc)OS_MutexDelete,
94   (DllFunc)OS_MutexPend,
95   (DllFunc)OS_MutexPost,
96   (DllFunc)OS_MQueueCreate,
97   (DllFunc)OS_MQueueDelete,
98   (DllFunc)OS_MQueueSend,
99   (DllFunc)OS_MQueueGet,
100   (DllFunc)OS_Job,
101   (DllFunc)OS_TimerCreate,
102   (DllFunc)OS_TimerDelete,
103   (DllFunc)OS_TimerCallback,
104   (DllFunc)OS_TimerStart,
105   (DllFunc)OS_TimerStop,
106   (DllFunc)OS_InterruptRegister,
107   (DllFunc)OS_InterruptStatus,
108   (DllFunc)OS_InterruptMaskSet,
109   (DllFunc)OS_InterruptMaskClear,
110   (DllFunc)UartPrintf,
111   (DllFunc)UartPrintfPoll,
112   (DllFunc)UartPrintfCritical,
113   (DllFunc)UartScanf,
114   (DllFunc)puts,
115   (DllFunc)getch,
116   (DllFunc)kbhit,
117   (DllFunc)Led,
118   (DllFunc)FP_Sqrt,
119   (DllFunc)FP_Cos,
120   (DllFunc)FP_Sin,
121   (DllFunc)FP_Atan,
122   (DllFunc)FP_Atan2,
123   (DllFunc)FP_Exp,
124   (DllFunc)FP_Log,
125   (DllFunc)FP_Pow,
126#ifdef INCLUDE_FILESYS
127   (DllFunc)OS_fopen,
128   (DllFunc)OS_fclose,
129   (DllFunc)OS_fread,
130   (DllFunc)OS_fwrite,
131   (DllFunc)OS_fseek,
132   (DllFunc)OS_fmkdir,
133   (DllFunc)OS_fdir,
134   (DllFunc)OS_fdelete,
135#else //INCLUDE_FILESYS
136   DllDummy,
137   DllDummy,
138   DllDummy,
139   DllDummy,
140   DllDummy,
141   DllDummy,
142   DllDummy,
143   DllDummy,
144#endif //INCLUDE_FILESYS
145#ifndef WIN32
146   (DllFunc)FlashRead,
147   (DllFunc)FlashWrite,
148   (DllFunc)FlashErase,
149#else //WIN32
150   DllDummy,
151   DllDummy,
152   DllDummy,
153#endif //WIN32
154   (DllFunc)IPOpen,
155   (DllFunc)IPWriteFlush,
156   (DllFunc)IPWrite,
157   (DllFunc)IPRead,
158   (DllFunc)IPClose,
159   (DllFunc)IPPrintf,
160   (DllFunc)IPResolve,
161   (DllFunc)IPAddressSelf,
162   (DllFunc)IPNameValue
163};
164
165#endif //DLL_SETUP
166
167// Included by DLL to call OS functions via array of function pointers
168#if defined(DLL_CALL) || !defined(DLL_SETUP)
169
170enum {
171   ENUM_strcpy,
172   ENUM_strncpy,
173   ENUM_strcat,
174   ENUM_strncat,
175   ENUM_strcmp,
176   ENUM_strncmp,
177   ENUM_strstr,
178   ENUM_strlen,
179   ENUM_memcpy,
180   ENUM_memmove,
181   ENUM_memcmp,
182   ENUM_memset,
183   ENUM_abs,
184   ENUM_rand,
185   ENUM_srand,
186   ENUM_strtol,
187   ENUM_atoi,
188   ENUM_itoa,
189   ENUM_sprintf,
190   ENUM_sscanf,
191   ENUM_dump,
192   ENUM_qsort,
193   ENUM_bsearch,
194   ENUM_mktime,
195   ENUM_gmtime_r,
196   ENUM_gmtimeDst,
197   ENUM_gmtimeDstSet,
198   ENUM_OS_AsmInterruptEnable,
199   ENUM_OS_HeapCreate,
200   ENUM_OS_HeapDestroy,
201   ENUM_OS_HeapMalloc,
202   ENUM_OS_HeapFree,
203   ENUM_OS_HeapAlternate,
204   ENUM_OS_HeapRegister,
205   ENUM_OS_ThreadCreate,
206   ENUM_OS_ThreadExit,
207   ENUM_OS_ThreadSelf,
208   ENUM_OS_ThreadSleep,
209   ENUM_OS_ThreadTime,
210   ENUM_OS_ThreadInfoSet,
211   ENUM_OS_ThreadInfoGet,
212   ENUM_OS_ThreadPriorityGet,
213   ENUM_OS_ThreadPrioritySet,
214   ENUM_OS_ThreadProcessId,
215   ENUM_OS_ThreadCpuLock,
216   ENUM_OS_SemaphoreCreate,
217   ENUM_OS_SemaphoreDelete,
218   ENUM_OS_SemaphorePend,
219   ENUM_OS_SemaphorePost,
220   ENUM_OS_MutexCreate,
221   ENUM_OS_MutexDelete,
222   ENUM_OS_MutexPend,
223   ENUM_OS_MutexPost,
224   ENUM_OS_MQueueCreate,
225   ENUM_OS_MQueueDelete,
226   ENUM_OS_MQueueSend,
227   ENUM_OS_MQueueGet,
228   ENUM_OS_Job,
229   ENUM_OS_TimerCreate,
230   ENUM_OS_TimerDelete,
231   ENUM_OS_TimerCallback,
232   ENUM_OS_TimerStart,
233   ENUM_OS_TimerStop,
234   ENUM_OS_InterruptRegister,
235   ENUM_OS_InterruptStatus,
236   ENUM_OS_InterruptMaskSet,
237   ENUM_OS_InterruptMaskClear,
238   ENUM_UartPrintf,
239   ENUM_UartPrintfPoll,
240   ENUM_UartPrintfCritical,
241   ENUM_UartScanf,
242   ENUM_puts,
243   ENUM_getch,
244   ENUM_kbhit,
245   ENUM_Led,
246   ENUM_FP_Sqrt,
247   ENUM_FP_Cos,
248   ENUM_FP_Sin,
249   ENUM_FP_Atan,
250   ENUM_FP_Atan2,
251   ENUM_FP_Exp,
252   ENUM_FP_Log,
253   ENUM_FP_Pow,
254   ENUM_OS_fopen,
255   ENUM_OS_fclose,
256   ENUM_OS_fread,
257   ENUM_OS_fwrite,
258   ENUM_OS_fseek,
259   ENUM_OS_fmkdir,
260   ENUM_OS_fdir,
261   ENUM_OS_fdelete,
262   ENUM_FlashRead,
263   ENUM_FlashWrite,
264   ENUM_FlashErase,
265   ENUM_IPOpen,
266   ENUM_IPWriteFlush,
267   ENUM_IPWrite,
268   ENUM_IPRead,
269   ENUM_IPClose,
270   ENUM_IPPrintf,
271   ENUM_IPResolve,
272   ENUM_IPAddressSelf,
273   ENUM_IPNameValue
274};
275
276extern const DllFunc *DllF;
277
278#undef strcpy
279#undef strcat
280#undef strncat
281#undef strcmp
282#undef strlen
283#undef memcpy
284#undef memcmp
285#undef memset
286#undef abs
287#undef atoi
288#undef puts
289#undef getch
290#undef kbhit
291
292#define strcpy DllF[ENUM_strcpy]
293#define strncpy DllF[ENUM_strncpy]
294#define strcat DllF[ENUM_strcat]
295#define strncat DllF[ENUM_strncat]
296#define strcmp (int)DllF[ENUM_strcmp]
297#define strncmp (int)DllF[ENUM_strncmp]
298#define strstr DllF[ENUM_strstr]
299#define strlen (int)DllF[ENUM_strlen]
300#define memcpy DllF[ENUM_memcpy]
301#define memmove DllF[ENUM_memmove]
302#define memcmp (int)DllF[ENUM_memcmp]
303#define memset DllF[ENUM_memset]
304#define abs (int)DllF[ENUM_abs]
305#define rand (int)DllF[ENUM_rand]
306#define srand DllF[ENUM_srand]
307#define strtol (int)DllF[ENUM_strtol]
308#define atoi (int)DllF[ENUM_atoi]
309#define itoa DllF[ENUM_itoa]
310#define sprintf DllF[ENUM_sprintf]
311#define sscanf DllF[ENUM_sscanf]
312#define dump DllF[ENUM_dump]
313#define qsort DllF[ENUM_qsort]
314#define bsearch DllF[ENUM_bsearch]
315#define mktime DllF[ENUM_mktime]
316#define gmtime_r DllF[ENUM_gmtime_r]
317#define gmtimeDst DllF[ENUM_gmtimeDst]
318#define gmtimeDstSet DllF[ENUM_gmtimeDstSet]
319#define OS_AsmInterruptEnable (int)DllF[ENUM_OS_AsmInterruptEnable]
320#define OS_HeapCreate DllF[ENUM_OS_HeapCreate]
321#define OS_HeapDestroy DllF[ENUM_OS_HeapDestroy]
322#define OS_HeapMalloc DllF[ENUM_OS_HeapMalloc]
323#define OS_HeapFree DllF[ENUM_OS_HeapFree]
324#define OS_HeapAlternate DllF[ENUM_OS_HeapAlternate]
325#define OS_HeapRegister DllF[ENUM_OS_HeapRegister]
326#define OS_ThreadCreate DllF[ENUM_OS_ThreadCreate]
327#define OS_ThreadExit DllF[ENUM_OS_ThreadExit]
328#define OS_ThreadSelf DllF[ENUM_OS_ThreadSelf]
329#define OS_ThreadSleep DllF[ENUM_OS_ThreadSleep]
330#define OS_ThreadTime DllF[ENUM_OS_ThreadTime]
331#define OS_ThreadInfoSet DllF[ENUM_OS_ThreadInfoSet]
332#define OS_ThreadInfoGet DllF[ENUM_OS_ThreadInfoGet]
333#define OS_ThreadPriorityGet (int)DllF[ENUM_OS_ThreadPriorityGet]
334#define OS_ThreadPrioritySet DllF[ENUM_OS_ThreadPrioritySet]
335#define OS_ThreadProcessId DllF[ENUM_OS_ThreadProcessId]
336#define OS_ThreadCpuLock DllF[ENUM_OS_ThreadCpuLock]
337#define OS_SemaphoreCreate DllF[ENUM_OS_SemaphoreCreate]
338#define OS_SemaphoreDelete DllF[ENUM_OS_SemaphoreDelete]
339#define OS_SemaphorePend (int)DllF[ENUM_OS_SemaphorePend]
340#define OS_SemaphorePost DllF[ENUM_OS_SemaphorePost]
341#define OS_MutexCreate DllF[ENUM_OS_MutexCreate]
342#define OS_MutexDelete DllF[ENUM_OS_MutexDelete]
343#define OS_MutexPend (int)DllF[ENUM_OS_MutexPend]
344#define OS_MutexPost DllF[ENUM_OS_MutexPost]
345#define OS_MQueueCreate DllF[ENUM_OS_MQueueCreate]
346#define OS_MQueueDelete DllF[ENUM_OS_MQueueDelete]
347#define OS_MQueueSend DllF[ENUM_OS_MQueueSend]
348#define OS_MQueueGet (int)DllF[ENUM_OS_MQueueGet]
349#define OS_Job DllF[ENUM_OS_Job]
350#define OS_TimerCreate DllF[ENUM_OS_TimerCreate]
351#define OS_TimerDelete DllF[ENUM_OS_TimerDelete]
352#define OS_TimerCallback DllF[ENUM_OS_TimerCallback]
353#define OS_TimerStart DllF[ENUM_OS_TimerStart]
354#define OS_TimerStop DllF[ENUM_OS_TimerStop]
355#define OS_InterruptRegister DllF[ENUM_OS_InterruptRegister]
356#define OS_InterruptStatus (int)DllF[ENUM_OS_InterruptStatus]
357#define OS_InterruptMaskSet DllF[ENUM_OS_InterruptMaskSet]
358#define OS_InterruptMaskClear DllF[ENUM_OS_InterruptMaskClear]
359#define UartPrintf DllF[ENUM_UartPrintf]
360#define UartPrintfPoll DllF[ENUM_UartPrintfPoll]
361#define UartPrintfCritical DllF[ENUM_UartPrintfCritical]
362#define UartScanf DllF[ENUM_UartScanf]
363#define puts DllF[ENUM_puts]
364#define getch (int)DllF[ENUM_getch]
365#define kbhit (int)DllF[ENUM_kbhit]
366#define Led DllF[ENUM_Led]
367#define FP_Sqrt (float)(int)DllF[ENUM_FP_Sqrt]
368#define FP_Cos (float)(int)DllF[ENUM_FP_Cos]
369#define FP_Sin (float)(int)DllF[ENUM_FP_Sin]
370#define FP_Atan (float)(int)DllF[ENUM_FP_Atan]
371#define FP_Atan2 (float)(int)DllF[ENUM_FP_Atan2]
372#define FP_Exp (float)(int)DllF[ENUM_FP_Exp]
373#define FP_Log (float)(int)DllF[ENUM_FP_Log]
374#define FP_Pow (float)(int)DllF[ENUM_FP_Pow]
375#define OS_fopen DllF[ENUM_OS_fopen]
376#define OS_fclose DllF[ENUM_OS_fclose]
377#define OS_fread (int)DllF[ENUM_OS_fread]
378#define OS_fwrite DllF[ENUM_OS_fwrite]
379#define OS_fseek DllF[ENUM_OS_fseek]
380#define OS_fmkdir DllF[ENUM_OS_fmkdir]
381#define OS_fdir DllF[ENUM_OS_fdir]
382#define OS_fdelete DllF[ENUM_OS_fdelete]
383#define FlashRead DllF[ENUM_FlashRead]
384#define FlashWrite DllF[ENUM_FlashWrite]
385#define FlashErase DllF[ENUM_FlashErase]
386#define IPOpen DllF[ENUM_IPOpen]
387#define IPWriteFlush DllF[ENUM_IPWriteFlush]
388#define IPWrite (int)DllF[ENUM_IPWrite]
389#define IPRead (int)DllF[ENUM_IPRead]
390#define IPClose DllF[ENUM_IPClose]
391#define IPPrintf DllF[ENUM_IPPrintf]
392#define IPResolve DllF[ENUM_IPResolve]
393#define IPAddressSelf (int)DllF[ENUM_IPAddressSelf]
394#define IPNameValue DllF[ENUM_IPNameValue]
395
396#endif //DLL_CALL
397
398
399#if defined(DLL_SETUP) && defined(DLL_CALL)
400const DllFunc *DllF = DllFuncList;
401#elif !defined(DLL_SETUP) && !defined(DLL_CALL) && !defined(DLL_ENTRY)
402#define DLL_ENTRY 1
403#endif //DLL_SETUP && DLL_CALL
404
405
406// Included by DLL to initialize the DLL
407#if defined(DLL_ENTRY) && !defined(NO_DLL_ENTRY)
408const DllFunc *DllF; //array of function pointers
409extern void *__bss_start;
410extern void *_end;
411void Start(IPSocket *socket, char *argv[]);
412
413//Must be first function in file
414void *__start(DllFunc *DllFuncList)
415{
416   int *bss;
417   if(DllFuncList == NULL)
418      return (void*)__start; //address where DLL should be loaded
419   for(bss = (int*)&__bss_start; bss < (int*)&_end; ++bss)
420      *bss = 0;
421   DllF = DllFuncList;
422   return (void*)Start;
423}
424#endif //DLL_ENTRY
425
426
427#ifdef DLL_STRINGS
428const char * const DllStrings[] = {
429   "strcpy",
430   "strncpy",
431   "strcat",
432   "strncat",
433   "strcmp",
434   "strncmp",
435   "strstr",
436   "strlen",
437   "memcpy",
438   "memmove",
439   "memcmp",
440   "memset",
441   "abs",
442   "rand",
443   "srand",
444   "strtol",
445   "atoi",
446   "itoa",
447   "sprintf",
448   "sscanf",
449   "dump",
450   "qsort",
451   "bsearch",
452   "mktime",
453   "gmtime_r",
454   "gmtimeDst",
455   "gmtimeDstSet",
456   "OS_AsmInterruptEnable",
457   "OS_HeapCreate",
458   "OS_HeapDestroy",
459   "OS_HeapMalloc",
460   "OS_HeapFree",
461   "OS_HeapAlternate",
462   "OS_HeapRegister",
463   "OS_ThreadCreate",
464   "OS_ThreadExit",
465   "OS_ThreadSelf",
466   "OS_ThreadSleep",
467   "OS_ThreadTime",
468   "OS_ThreadInfoSet",
469   "OS_ThreadInfoGet",
470   "OS_ThreadPriorityGet",
471   "OS_ThreadPrioritySet",
472   "OS_ThreadProcessId",
473   "OS_ThreadCpuLock",
474   "OS_SemaphoreCreate",
475   "OS_SemaphoreDelete",
476   "OS_SemaphorePend",
477   "OS_SemaphorePost",
478   "OS_MutexCreate",
479   "OS_MutexDelete",
480   "OS_MutexPend",
481   "OS_MutexPost",
482   "OS_MQueueCreate",
483   "OS_MQueueDelete",
484   "OS_MQueueSend",
485   "OS_MQueueGet",
486   "OS_Job",
487   "OS_TimerCreate",
488   "OS_TimerDelete",
489   "OS_TimerCallback",
490   "OS_TimerStart",
491   "OS_TimerStop",
492   "OS_InterruptRegister",
493   "OS_InterruptStatus",
494   "OS_InterruptMaskSet",
495   "OS_InterruptMaskClear",
496   "printf", //"UartPrintf",
497   "UartPrintfPoll",
498   "UartPrintfCritical",
499   "scanf", //"UartScanf",
500   "puts",
501   "getch",
502   "kbhit",
503   "Led",
504   "FP_Sqrt",
505   "FP_Cos",
506   "FP_Sin",
507   "FP_Atan",
508   "FP_Atan2",
509   "FP_Exp",
510   "FP_Log",
511   "FP_Pow",
512   "OS_fopen",
513   "OS_fclose",
514   "OS_fread",
515   "OS_fwrite",
516   "OS_fseek",
517   "OS_fmkdir",
518   "OS_fdir",
519   "OS_fdelete",
520   "FlashRead",
521   "FlashWrite",
522   "FlashErase",
523   "IPOpen",
524   "IPWriteFlush",
525   "IPWrite",
526   "IPRead",
527   "IPClose",
528   "IPPrintf",
529   "IPResolve",
530   "IPAddressSelf",
531   "IPNameValue",
532   NULL
533};
534#endif //DLL_STRINGS
535
536#endif //__DLL_H__
537
plasma/kernel/dlltest.c
1// dlltest.c
2// Compile this program with "make dlltest".
3// Then ftp test.bin to /flash/bin/dlltest.
4// Then from a telnet prompt type "dlltest".
5#include "dll.h"
6
7
8void SocketReceive(IPSocket *socket)
9{
10}
11
12
13void MyThread(void *sock)
14{
15   char buf[80];
16   int i, bytes;
17   IPSocket *socket = sock;
18
19   for(i = 0; i < 10; ++i)
20   {
21      bytes = IPRead(socket, buf, sizeof(buf)-1);
22      buf[bytes] = 0;
23      IPPrintf(socket, "%d %s\n", i, buf);
24      OS_ThreadSleep(100);
25   }
26   socket->funcPtr = socket->userFunc; //restore socket receive function
27}
28
29
30// Function shouldn't block
31void Start(IPSocket *socket, char *argv[])
32{
33   IPPrintf(socket, "Hello from dlltest\n");
34   socket->userFunc = socket->funcPtr; //remember prev socket receive func
35   socket->funcPtr = SocketReceive; //new socket receive function
36   OS_ThreadCreate("MyThread", MyThread, socket, 100, 0);
37}
38
plasma/kernel/ethernet.c
1/*--------------------------------------------------------------------
2 * TITLE: Plasma Ethernet MAC
3 * AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4 * DATE CREATED: 1/12/08
5 * FILENAME: ethernet.c
6 * PROJECT: Plasma CPU core
7 * COPYRIGHT: Software placed into the public domain by the author.
8 * Software 'as is' without warranty. Author liable for nothing.
9 * DESCRIPTION:
10 * Ethernet MAC implementation.
11 * Data is received from the Ethernet PHY four bits at a time.
12 * After 32-bits are received they are written to 0x13ff0000 + N.
13 * The data is received LSB first for each byte which requires the
14 * nibbles to be swapped.
15 * Transmit data is read from 0x13fe0000. Write length/4+1 to
16 * ETHERNET_REG to start transfer.
17 *--------------------------------------------------------------------*/
18#include "plasma.h"
19#include "rtos.h"
20#include "tcpip.h"
21
22#define POLYNOMIAL 0x04C11DB7 //CRC bit 33 is truncated
23#define TOPBIT (1<<31)
24#define BYTE_EMPTY 0xde //Data copied into receive buffer
25#define COUNT_EMPTY 16 //Count to decide there isn't data
26#define INDEX_MASK 0xffff //Size of receive buffer
27
28//void dump(const unsigned char *data, int length);
29
30static unsigned char gDestMac[]={0x5d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
31static unsigned int CrcTable[256];
32static unsigned char reflect[256];
33static unsigned char reflectNibble[256];
34static OS_Semaphore_t *SemEthernet, *SemEthTransmit;
35static int gIndex; //byte index into 0x13ff0000 receive buffer
36static int gCheckedBefore;
37static int gEmptyBefore;
38
39
40//Read received data from 0x13ff0000. Data starts with 0x5d+MACaddress.
41//Data is being received while processing the data. Therefore,
42//all errors require waiting and then re-processing the data
43//to see if the error is fixed by receiving the rest of the packet.
44int EthernetReceive(unsigned char *buffer, int length)
45{
46   int count;
47   int start, i, j, shift, offset;
48   int byte, byteNext;
49   unsigned long crc;
50   int byteCrc;
51   volatile unsigned char *buf = (unsigned char*)ETHERNET_RECEIVE;
52   int countEmpty, countEmptyGoal, countOk, needWait;
53   int packetExpected;
54
55   //Find the start of a frame
56   countEmpty = 0;
57   countOk = 0;
58   needWait = 0;
59   countEmptyGoal = COUNT_EMPTY;
60   packetExpected = MemoryRead(IRQ_STATUS) & IRQ_ETHERNET_RECEIVE;
61   if(packetExpected && buf[gIndex] == BYTE_EMPTY && gEmptyBefore)
62   {
63      //printf("Check ");
64      countEmptyGoal = 1500;
65   }
66   MemoryRead(ETHERNET_REG); //clear receive interrupt
67   for(i = 0; i < INDEX_MASK; ++i)
68   {
69      //Check if partial packet possibly received
70      if(needWait && gCheckedBefore == 0 && countOk != i && countEmpty != i)
71      {
72         gCheckedBefore = 1;
73         //printf("W(%d,%d,%d)", i, countOk, countEmpty);
74         return 0; //Wait for more data
75      }
76
77      //Detect start of frame
78      byte = buf[(gIndex + i) & INDEX_MASK];
79      if(byte == gDestMac[countOk] || (countOk && byte == 0xff))
80      {
81         if(++countOk == sizeof(gDestMac))
82         {
83            //Set bytes before 0x5d to BYTE_EMPTY
84            offset = i - (int)sizeof(gDestMac);
85            //if(offset > 3)
86            // printf("es%d ", offset);
87            for(j = 0; j <= offset; ++j)
88            {
89               buf[gIndex] = BYTE_EMPTY;
90               gIndex = (gIndex + 1) & INDEX_MASK;
91            }
92            break;
93         }
94      }
95      else
96      {
97         //if(countOk)
98         // printf("N%d ", countOk);
99         if(countOk == 3 && byte == BYTE_EMPTY)
100            needWait = 1;
101         if(byte == 0x5d)
102            countOk = 1;
103         else
104            countOk = 0;
105      }
106
107      //Check if remainder of buffer is empty
108      if(byte == BYTE_EMPTY)
109      {
110         if(++countEmpty >= countEmptyGoal)
111         {
112            //Set skiped bytes to BYTE_EMPTY
113            //if(i - countEmpty > 3)
114            //{
115            // printf("eb%d \n", i - countEmpty);
116            // //dump((char*)buf+gIndex, 0x200);
117            //}
118            for(j = 0; j <= i - countEmpty; ++j)
119            {
120               buf[gIndex] = BYTE_EMPTY;
121               gIndex = (gIndex + 1) & INDEX_MASK;
122            }
123            gCheckedBefore = 0;
124            if(countEmpty >= i && packetExpected)
125               gEmptyBefore = 1;
126            return 0;
127         }
128      }
129      else
130      {
131         if(countEmpty > 2 || (countEmpty > 0 && countEmpty == i))
132            needWait = 1;
133         countEmpty = 0;
134         gEmptyBefore = 0;
135      }
136   }
137
138   //Found start of frame. Now find end of frame and check CRC.
139   start = gIndex;
140   gIndex = (gIndex + 1) & INDEX_MASK; //skip 0x5d byte
141   crc = 0xffffffff;
142   for(count = 0; count < length; )
143   {
144      byte = buf[gIndex];
145      gIndex = (gIndex + 1) & INDEX_MASK;
146
147      byte = ((byte << 4) & 0xf0) | (byte >> 4); //swap nibbles
148      buffer[count++] = (unsigned char)byte;
149      byte = reflect[byte] ^ (crc >> 24); //calculate CRC32
150      crc = CrcTable[byte] ^ (crc << 8);
151      if(count >= 40)
152      {
153         //Check if CRC matches to detect end of frame
154         byteCrc = reflectNibble[crc >> 24];
155         byteNext = buf[gIndex];
156         if(byteCrc == byteNext)
157         {
158            for(i = 1; i < 4; ++i)
159            {
160               shift = 24 - (i << 3);
161               byteCrc = reflectNibble[(crc >> shift) & 0xff];
162               byteNext = buf[(gIndex + i) & 0xffff];
163               if(byteCrc != byteNext)
164               {
165                  //printf("nope %d %d 0x%x 0x%x\n", count, i, byteCrc, byteNext);
166                  i = 99;
167               }
168            }
169            if(i == 4)
170            {
171               //Found end of frame -- set used bytes to BYTE_EMPTY
172               //printf("Found it! %d\n", count);
173               gIndex = (gIndex + 4) & INDEX_MASK;
174               for(i = 0; i < count+5; ++i)
175                  buf[(start + i) & INDEX_MASK] = BYTE_EMPTY;
176               while(gIndex & 3)
177               {
178                  buf[gIndex] = BYTE_EMPTY;
179                  gIndex = (gIndex + 1) & INDEX_MASK;
180               }
181               gCheckedBefore = 0;
182               return count;
183            }
184         }
185      }
186   }
187   gIndex = start;
188   if(gCheckedBefore)
189   {
190      //printf("CRC failure\n");
191      buf[gIndex] = BYTE_EMPTY;
192   }
193   gCheckedBefore = 1;
194   return 0; //wait for more data
195}
196
197
198//Copy transmit data to 0x13fe0000 with preamble and CRC32
199void EthernetTransmit(unsigned char *buffer, int length)
200{
201   int i, byte, shift;
202   unsigned long crc;
203   volatile unsigned char *buf = (unsigned char*)ETHERNET_TRANSMIT;
204
205   OS_SemaphorePend(SemEthTransmit, OS_WAIT_FOREVER);
206
207   //Wait for previous transfer to complete
208   for(i = 0; i < 10000; ++i)
209   {
210      if(MemoryRead(IRQ_STATUS) & IRQ_ETHERNET_TRANSMIT)
211         break;
212   }
213   //if(i > 100)
214   // printf("wait=%d ", i);
215
216   Led(2, 2);
217   while(length < 60 || (length & 3) != 0)
218      buffer[length++] = 0;
219
220   //Start of Ethernet frame
221   for(i = 0; i < 7; ++i)
222      buf[i] = 0x55;
223   buf[7] = 0x5d;
224
225   //Calculate CRC32
226   crc = 0xffffffff;
227   for(i = 0; i < length; ++i)
228   {
229      byte = buffer[i];
230      buf[i + 8] = (unsigned char)((byte << 4) | (byte >> 4)); //swap nibbles
231      byte = reflect[byte] ^ (crc >> 24); //calculate CRC32
232      crc = CrcTable[byte] ^ (crc << 8);
233   }
234
235   //Output CRC32
236   for(i = 0; i < 4; ++i)
237   {
238      shift = 24 - (i << 3);
239      byte = reflectNibble[(crc >> shift) & 0xff];
240      buf[length + 8 + i] = (unsigned char)byte;
241   }
242
243   //Start transfer
244   length = (length + 12 + 4) >> 2;
245   MemoryWrite(ETHERNET_REG, length);
246   Led(2, 0);
247
248   OS_SemaphorePost(SemEthTransmit);
249}
250
251
252void EthernetThread(void *arg)
253{
254   int length;
255   int rc;
256   unsigned int ticks, ticksLast=0;
257   IPFrame *ethFrame=NULL;
258   (void)arg;
259
260   for(;;)
261   {
262      OS_InterruptMaskSet(IRQ_ETHERNET_RECEIVE);
263      OS_SemaphorePend(SemEthernet, 50); //wait for interrupt
264
265      //Process all received packets
266      for(;;)
267      {
268         if(ethFrame == NULL)
269            ethFrame = IPFrameGet(FRAME_COUNT_RCV);
270         if(ethFrame == NULL)
271         {
272            OS_ThreadSleep(50);
273            break;
274         }
275         length = EthernetReceive(ethFrame->packet, PACKET_SIZE);
276         if(length == 0)
277            break;
278         Led(1, 1);
279         rc = IPProcessEthernetPacket(ethFrame, length);
280         Led(1, 0);
281         if(rc)
282            ethFrame = NULL;
283      }
284
285      ticks = OS_ThreadTime();
286      if(ticks - ticksLast > 50)
287      {
288         IPTick();
289         ticksLast = ticks;
290      }
291   }
292}
293
294
295void EthernetIsr(void *arg)
296{
297   (void)arg;
298   OS_InterruptMaskClear(IRQ_ETHERNET_TRANSMIT | IRQ_ETHERNET_RECEIVE);
299   OS_SemaphorePost(SemEthernet);
300}
301
302
303/******************* CRC32 calculations **********************
304 * The CRC32 code is modified from Michale Barr's article in
305 * Embedded Systems Programming January 2000.
306 * A CRC is really modulo-2 binary division. Substraction means XOR. */
307static unsigned int Reflect(unsigned int value, int bits)
308{
309   unsigned int num=0;
310   int i;
311   for(i = 0; i < bits; ++i)
312   {
313      num = (num << 1) | (value & 1);
314      value >>= 1;
315   }
316   return num;
317}
318
319
320static void CrcInit(void)
321{
322   unsigned int remainder;
323   int dividend, bit, i;
324
325   //Compute the remainder of each possible dividend
326   for(dividend = 0; dividend < 256; ++dividend)
327   {
328      //Start with the dividend followed by zeros
329      remainder = dividend << 24;
330      //Perform modulo-2 division, a bit at a time
331      for(bit = 8; bit > 0; --bit)
332      {
333         //Try to divide the current data bit
334         if(remainder & TOPBIT)
335            remainder = (remainder << 1) ^ POLYNOMIAL;
336         else
337            remainder = remainder << 1;
338      }
339      CrcTable[dividend] = remainder;
340   }
341   for(i = 0; i < 256; ++i)
342   {
343      reflect[i] = (unsigned char)Reflect(i, 8);
344      reflectNibble[i] = (unsigned char)((Reflect((i >> 4) ^ 0xf, 4) << 4) |
345         Reflect(i ^ 0xf, 4));
346   }
347}
348
349
350static void SpinWait(int clocks)
351{
352   int value = *(volatile int*)COUNTER_REG + clocks;
353   while(*(volatile int*)COUNTER_REG - value < 0)
354      ;
355}
356
357
358void EthernetInit(unsigned char MacAddress[6])
359{
360   //Format of SMI data: 0101 A4:A0 R4:R0 00 D15:D0
361   unsigned long data=0x5f800100; //SMI R0 = 10Mbps full duplex
362   //unsigned long data=0x5f800000; //SMI R0 = 10Mbps half duplex
363   int i, value;
364   volatile unsigned char *buf = (unsigned char*)ETHERNET_RECEIVE;
365
366   CrcInit();
367   for(i = 0; i < 6; ++i)
368   {
369      value = MacAddress[i];
370      gDestMac[i+1] = (unsigned char)((value >> 4) | (value << 4));
371   }
372
373   //Configure Ethernet PHY for 10Mbps full duplex via SMI interface
374   MemoryWrite(GPIO0_OUT, ETHERNET_MDIO | ETHERNET_MDIO_WE | ETHERENT_MDC);
375   for(i = 0; i < 34; ++i)
376   {
377      MemoryWrite(GPIO0_OUT, ETHERENT_MDC); //clock high
378      SpinWait(10);
379      MemoryWrite(GPIO0_CLEAR, ETHERENT_MDC); //clock low
380      SpinWait(10);
381   }
382   for(i = 31; i >= 0; --i)
383   {
384      value = (data >> i) & 1;
385      if(value)
386         MemoryWrite(GPIO0_OUT, ETHERNET_MDIO);
387      else
388         MemoryWrite(GPIO0_CLEAR, ETHERNET_MDIO);
389      MemoryWrite(GPIO0_OUT, ETHERENT_MDC); //clock high
390      SpinWait(10);
391      MemoryWrite(GPIO0_CLEAR, ETHERENT_MDC); //clock low
392      SpinWait(10);
393   }
394   MemoryWrite(GPIO0_CLEAR, ETHERNET_MDIO_WE | ETHERNET_ENABLE);
395
396   //Clear receive buffer
397   for(i = 0; i <= INDEX_MASK; ++i)
398      buf[i] = BYTE_EMPTY;
399
400   //Start receive DMA
401   MemoryWrite(GPIO0_OUT, ETHERNET_ENABLE);
402
403   //Setup interrupts for receiving data
404   SemEthernet = OS_SemaphoreCreate("eth", 0);
405   SemEthTransmit = OS_SemaphoreCreate("ethT", 1);
406   OS_ThreadCreate("eth", EthernetThread, NULL, 240, 0);
407   OS_InterruptRegister(IRQ_ETHERNET_RECEIVE, EthernetIsr);
408}
plasma/kernel/filesys.c
1/*--------------------------------------------------------------------
2 * TITLE: Plasma File System
3 * AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4 * DATE CREATED: 4/26/07
5 * FILENAME: filesys.c
6 * PROJECT: Plasma CPU core
7 * COPYRIGHT: Software placed into the public domain by the author.
8 * Software 'as is' without warranty. Author liable for nothing.
9 * DESCRIPTION:
10 * Plasma File System. Supports RAM, flash, and disk file systems.
11 * Possible call tree:
12 * OS_fclose()
13 * FileFindRecursive() //find the existing file
14 * FileOpen() //open root file system
15 * FileFind() //find the next level of directory
16 * OS_fread() //read the directory file
17 * BlockRead() //read blocks of directory
18 * MediaBlockRead() //low level read
19 * FileOpen() //open next directory
20 * OS_fwrite() //write file entry into directory
21 * BlockRead() //flush changes to directory
22 *--------------------------------------------------------------------*/
23#ifdef WIN32
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27#define _LIBC
28#endif
29#include "rtos.h"
30
31#define FLASH_SIZE 1024*1024*16
32#define FLASH_SECTOR_SIZE 1024*128
33#define FLASH_BLOCK_SIZE 512
34#define FLASH_LN2_SIZE 9 //2^FLASH_LN2_SIZE == FLASH_BLOCK_SIZE
35#define FLASH_OFFSET FLASH_SECTOR_SIZE //offset to start of flash file system
36
37#define BLOCK_SIZE 512
38#define FILE_NAME_SIZE 40
39#define FULL_NAME_SIZE 128
40#define BLOCK_MALLOC 0x0
41#define BLOCK_EOF 0xffffffff
42
43typedef enum {
44   FILE_MEDIA_RAM,
45   FILE_MEDIA_FLASH,
46   FILE_MEDIA_DISK
47} OS_MediaType_e;
48
49typedef struct OS_FileEntry_s {
50   char name[FILE_NAME_SIZE];
51   uint32 blockIndex; //first block of file
52   uint32 modifiedTime;
53   uint32 length;
54   uint8 isDirectory;
55   uint8 attributes;
56   uint8 valid;
57   uint8 mediaType;
58   uint16 blockSize; //Normally BLOCK_SIZE
59} OS_FileEntry_t;
60
61typedef struct OS_Block_s {
62   uint32 next;
63   uint8 data[4];
64} OS_Block_t;
65
66struct OS_FILE_s {
67   OS_FileEntry_t fileEntry; //written to directory upon OS_fclose()
68   uint8 fileModified;
69   uint8 blockModified;
70   uint32 blockIndex; //index of block
71   uint32 blockOffset; //byte offset into block
72   uint32 fileOffset; //byte offset into file
73   char fullname[FULL_NAME_SIZE]; //includes full path
74   OS_Block_t *block;
75   OS_Block_t *blockLocal; //local copy for flash or disk file system
76};
77
78static OS_FileEntry_t rootFileEntry;
79static OS_Mutex_t *mutexFilesys;
80
81// Public prototypes
82#ifndef _FILESYS_
83typedef struct OS_FILE_s OS_FILE;
84#endif
85OS_FILE *OS_fopen(char *name, char *mode);
86void OS_fclose(OS_FILE *file);
87int OS_fread(void *buffer, int size, int count, OS_FILE *file);
88int OS_fwrite(void *buffer, int size, int count, OS_FILE *file);
89int OS_fseek(OS_FILE *file, int offset, int mode);
90int OS_fmkdir(char *name);
91int OS_fdir(OS_FILE *dir, char name[64]);
92void OS_fdelete(char *name);
93
94
95/***************** Media Functions Start ***********************/
96#ifdef INCLUDE_FLASH
97#define FLASH_BLOCKS FLASH_SIZE/FLASH_BLOCK_SIZE
98#define FLASH_START (FLASH_OFFSET+FLASH_BLOCKS/8*2)/FLASH_BLOCK_SIZE
99static unsigned char FlashBlockEmpty[FLASH_BLOCKS/8];
100static unsigned char FlashBlockUsed[FLASH_BLOCKS/8];
101static int FlashBlock;
102
103//Free unused flash blocks
104static int MediaBlockCleanup(void)
105{
106   int i, sector, block, count=0;
107   unsigned char *buf;
108
109   printf("FlashCleanup\n");
110   buf = (unsigned char*)malloc(FLASH_SECTOR_SIZE);
111   if(buf == NULL)
112      return 0;
113   for(sector = FLASH_OFFSET / FLASH_SECTOR_SIZE; sector < FLASH_SIZE / FLASH_SECTOR_SIZE; ++sector)
114   {
115      FlashRead((uint16*)buf, FLASH_SECTOR_SIZE*sector, FLASH_SECTOR_SIZE);
116      if(sector == FLASH_OFFSET / FLASH_SECTOR_SIZE)
117      {
118         for(i = 0; i < FLASH_BLOCKS/8; ++i)
119            FlashBlockEmpty[i] |= ~FlashBlockUsed[i];
120         memcpy(buf, FlashBlockEmpty, sizeof(FlashBlockEmpty));
121         memset(FlashBlockUsed, 0xff, sizeof(FlashBlockUsed));
122         memset(buf+sizeof(FlashBlockEmpty), 0xff, sizeof(FlashBlockUsed));
123      }
124      //Erase empty blocks
125      for(block = 0; block < FLASH_SECTOR_SIZE / FLASH_BLOCK_SIZE; ++block)
126      {
127         i = sector * FLASH_SECTOR_SIZE / FLASH_BLOCK_SIZE + block;
128         if(i < FLASH_BLOCKS/8 && (FlashBlockEmpty[i >> 3] & (1 << (i & 7))))
129         {
130            memset(buf + FLASH_BLOCK_SIZE*block, 0xff, FLASH_BLOCK_SIZE);
131            ++count;
132         }
133      }
134      FlashErase(FLASH_SECTOR_SIZE * sector);
135      FlashWrite((uint16*)buf, FLASH_SECTOR_SIZE * sector, FLASH_SECTOR_SIZE);
136   }
137   free(buf);
138   return count;
139}
140
141
142int MediaBlockInit(void)
143{
144   FlashRead((uint16*)FlashBlockEmpty, FLASH_OFFSET, sizeof(FlashBlockEmpty));
145   FlashRead((uint16*)FlashBlockUsed, FLASH_OFFSET+sizeof(FlashBlockEmpty),
146             sizeof(FlashBlockUsed));
147   FlashBlock = FLASH_START;
148   return FlashBlockEmpty[FlashBlock >> 3] & (1 << (FlashBlock & 7));
149}
150#endif
151
152
153static uint32 MediaBlockMalloc(OS_FILE *file)
154{
155   int i, j;
156   (void)i; (void)j;
157
158   if(file->fileEntry.mediaType == FILE_MEDIA_RAM)
159      return (uint32)malloc(file->fileEntry.blockSize);
160#ifdef INCLUDE_FLASH
161   //Find empty flash block
162   for(i = FlashBlock; i < FLASH_BLOCKS; ++i)
163   {
164      if(FlashBlockEmpty[i >> 3] & (1 << (i & 7)))
165      {
166         FlashBlock = i + 1;
167         FlashBlockEmpty[i >> 3] &= ~(1 << (i & 7));
168         j = i >> 3;
169         j &= ~1;
170         FlashWrite((uint16*)(FlashBlockEmpty + j), FLASH_OFFSET + j, 2);
171         return i;
172      }
173   }
174
175   i = MediaBlockCleanup();
176   if(i == 0)
177      return 0;
178   FlashBlock = FLASH_START;
179   return MediaBlockMalloc(file);
180#else
181   return 0;
182#endif
183}
184
185
186static void MediaBlockFree(OS_FILE *file, uint32 blockIndex)
187{
188   if(file->fileEntry.mediaType == FILE_MEDIA_RAM)
189      free((void*)blockIndex);
190#ifdef INCLUDE_FLASH
191   else
192   {
193      int i=blockIndex, j;
194      FlashBlockUsed[i >> 3] &= ~(1 << (i & 7));
195      j = i >> 3;
196      j &= ~1;
197      FlashWrite((uint16*)(FlashBlockUsed + j), FLASH_OFFSET + sizeof(FlashBlockEmpty) + j, 2);
198   }
199#endif
200}
201
202
203static void MediaBlockRead(OS_FILE *file, uint32 blockIndex)
204{
205   if(file->fileEntry.mediaType == FILE_MEDIA_RAM)
206      file->block = (OS_Block_t*)blockIndex;
207#ifdef INCLUDE_FLASH
208   else
209   {
210      if(file->blockLocal == NULL)
211         file->blockLocal = (OS_Block_t*)malloc(FLASH_BLOCK_SIZE);
212      file->block = file->blockLocal;
213      FlashRead((uint16*)file->block, blockIndex << FLASH_LN2_SIZE, FLASH_BLOCK_SIZE);
214   }
215#endif
216}
217
218
219static void MediaBlockWrite(OS_FILE *file, uint32 blockIndex)
220{
221   (void)file;
222   (void)blockIndex;
223#ifdef INCLUDE_FLASH
224   if(file->fileEntry.mediaType != FILE_MEDIA_RAM)
225      FlashWrite((uint16*)file->block, blockIndex << FLASH_LN2_SIZE, FLASH_BLOCK_SIZE);
226#endif
227}
228
229/***************** Media Functions End *************************/
230
231// Get the next block and write the old block if it was modified
232static void BlockRead(OS_FILE *file, uint32 blockIndex)
233{
234   uint32 blockIndexSave = blockIndex;
235
236   OS_MutexPend(mutexFilesys);
237   if(blockIndex == BLOCK_MALLOC)
238   {
239      // Get a new block
240      blockIndex = MediaBlockMalloc(file);
241      if(blockIndex == 0)
242         blockIndex = BLOCK_EOF;
243      if(file->block)
244      {
245         // Set next pointer in previous block
246         file->block->next = blockIndex;
247         file->blockModified = 1;
248      }
249   }
250   if(file->block && file->blockModified)
251   {
252      // Write block back to flash or disk
253      MediaBlockWrite(file, file->blockIndex);
254      file->blockModified = 0;
255   }
256   if(blockIndex == BLOCK_EOF)
257   {
258      OS_MutexPost(mutexFilesys);
259      return;
260   }
261   file->blockIndex = blockIndex;
262   file->blockOffset = 0;
263   MediaBlockRead(file, blockIndex);
264   if(blockIndexSave == BLOCK_MALLOC)
265   {
266      memset(file->block, 0xff, file->fileEntry.blockSize);
267      file->blockModified = 1;
268   }
269   OS_MutexPost(mutexFilesys);
270}
271
272
273int OS_fread(void *buffer, int size, int count, OS_FILE *file)
274{
275   int items, bytes;
276   uint8 *buf = (uint8*)buffer;
277
278   for(items = 0; items < count; ++items)
279   {
280      for(bytes = 0; bytes < size; ++bytes)
281      {
282         if(file->fileOffset >= file->fileEntry.length &&
283            file->fileEntry.isDirectory == 0)
284            return items;
285         if(file->blockOffset >= file->fileEntry.blockSize - sizeof(uint32))
286         {
287            if(file->block->next == BLOCK_EOF)
288               return items;
289            BlockRead(file, file->block->next);
290         }
291         *buf++ = file->block->data[file->blockOffset++];
292         ++file->fileOffset;
293      }
294   }
295   return items;
296}
297
298
299int OS_fwrite(void *buffer, int size, int count, OS_FILE *file)
300{
301   int items, bytes;
302   uint8 *buf = (uint8*)buffer;
303
304   OS_MutexPend(mutexFilesys);
305   file->blockModified = 1;
306   for(items = 0; items < count; ++items)
307   {
308      for(bytes = 0; bytes < size; ++bytes)
309      {
310         if(file->blockOffset >= file->fileEntry.blockSize - sizeof(uint32))
311         {
312            if(file->block->next == BLOCK_EOF)
313               file->block->next = BLOCK_MALLOC;
314            BlockRead(file, file->block->next);
315            if(file->blockIndex == BLOCK_EOF)
316            {
317               count = 0;
318               --items;
319               break;
320            }
321            file->blockModified = 1;
322         }
323         file->block->data[file->blockOffset++] = *buf++;
324         ++file->fileOffset;
325      }
326   }
327   file->blockModified = 1;
328   file->fileModified = 1;
329   if(file->fileOffset > file->fileEntry.length)
330      file->fileEntry.length = file->fileOffset;
331   OS_MutexPost(mutexFilesys);
332   return items;
333}
334
335
336int OS_fseek(OS_FILE *file, int offset, int mode)
337{
338   if(mode == 1) //SEEK_CUR
339      offset += file->fileOffset;
340   else if(mode == 2) //SEEK_END
341      offset += file->fileEntry.length;
342   file->fileOffset = offset;
343   BlockRead(file, file->fileEntry.blockIndex);
344   while(offset > (int)file->fileEntry.blockSize - (int)sizeof(uint32))
345   {
346      BlockRead(file, file->block->next);
347      offset -= file->fileEntry.blockSize - (int)sizeof(uint32);
348   }
349   file->blockOffset = offset;
350   return 0;
351}
352
353
354static int FileOpen(OS_FILE *file, char *name, OS_FileEntry_t *fileEntry)
355{
356   memset(file, 0, sizeof(OS_FILE));
357   if(fileEntry == NULL)
358   {
359      // Open root file
360      memcpy(&file->fileEntry, &rootFileEntry, sizeof(OS_FileEntry_t));
361   }
362   else if(fileEntry->valid == 1)
363   {
364      // Open existing file
365      memcpy(&file->fileEntry, fileEntry, sizeof(OS_FileEntry_t));
366   }
367   else
368   {
369      // Initialize new file
370      file->fileModified = 1;
371      file->blockModified = 1;
372      memset(&file->fileEntry, 0, sizeof(OS_FileEntry_t));
373      file->fileEntry.isDirectory = 0;
374      file->fileEntry.length = 0;
375      strncpy(file->fileEntry.name, name, FILE_NAME_SIZE-1);
376      file->fileEntry.blockIndex = 0;
377      file->fileEntry.valid = 1;
378      file->fileEntry.blockSize = fileEntry->blockSize;
379      file->fileEntry.mediaType = fileEntry->mediaType;
380   }
381   BlockRead(file, file->fileEntry.blockIndex); //Get first block
382   file->fileEntry.blockIndex = file->blockIndex;
383   file->fileOffset = 0;
384   if(file->blockIndex == BLOCK_EOF)
385      return -1;
386   return 0;
387}
388
389
390static int FileFind(OS_FILE *directory, char *name, OS_FileEntry_t *fileEntry)
391{
392   int count, rc = -1;
393   uint32 blockIndex, blockOffset;
394   uint32 blockIndexEmpty=BLOCK_EOF, blockOffsetEmpty=0;
395
396   // Loop through files in directory
397   for(;;)
398   {
399      blockIndex = directory->blockIndex;
400      blockOffset = directory->blockOffset;
401      count = OS_fread(fileEntry, sizeof(OS_FileEntry_t), 1, directory);
402      if(count == 0 || fileEntry->blockIndex == BLOCK_EOF)
403         break;
404      if(fileEntry->valid == 1 && strcmp(fileEntry->name, name) == 0)
405      {
406         rc = 0; //Found the file in the directory
407         break;
408      }
409      if(fileEntry->valid != 1 && blockIndexEmpty == BLOCK_EOF)
410      {
411         blockIndexEmpty = blockIndex;
412         blockOffsetEmpty = blockOffset;
413      }
414   }
415   if(rc == 0 || directory->fileEntry.mediaType == FILE_MEDIA_FLASH ||
416      blockIndexEmpty == BLOCK_EOF)
417   {
418      // Backup to start of fileEntry or last entry in directory
419      if(directory->blockIndex != blockIndex)
420         BlockRead(directory, blockIndex);
421      directory->blockOffset = blockOffset;
422   }
423   else
424   {
425      // Backup to empty slot
426      if(directory->blockIndex != blockIndexEmpty)
427         BlockRead(directory, blockIndexEmpty);
428      directory->blockOffset = blockOffsetEmpty;
429   }
430   return rc;
431}
432
433
434static int FileFindRecursive(OS_FILE *directory, char *name,
435                             OS_FileEntry_t *fileEntry, char *filename)
436{
437   int rc, length;
438
439   rc = FileOpen(directory, NULL, NULL); //Open root directory
440   for(;;)
441   {
442      if(name[0] == '/')
443         ++name;
444      for(length = 0; length < FILE_NAME_SIZE; ++length)
445      {
446         if(name[length] == 0 || name[length] == '/')
447            break;
448         filename[length] = name[length];
449      }
450      filename[length] = 0;
451      rc = FileFind(directory, filename, fileEntry); //Find file
452      if(rc)
453      {
454         // File not found
455         fileEntry->mediaType = directory->fileEntry.mediaType;
456         fileEntry->blockSize = directory->fileEntry.blockSize;
457         fileEntry->valid = 0;
458         if(strstr(name, "/") == NULL)
459            return rc;
460         else
461            return -2; //can't find parent directory
462      }
463      name += length;
464      if(name[0])
465         rc = FileOpen(directory, filename, fileEntry); //Open subdir
466      else
467         break;
468   }
469   return rc;
470}
471
472
473OS_FILE *OS_fopen(char *name, char *mode)
474{
475   OS_FILE *file;
476   OS_FileEntry_t fileEntry;
477   OS_FILE dir;
478   char filename[FILE_NAME_SIZE]; //Name without directories
479   int rc;
480
481   if(rootFileEntry.blockIndex == 0)
482   {
483      // Mount file system
484      mutexFilesys = OS_MutexCreate("filesys");
485      memset(&dir, 0, sizeof(OS_FILE));
486      dir.fileEntry.blockSize = BLOCK_SIZE;
487      //dir.fileEntry.mediaType = FILE_MEDIA_FLASH; //Test flash
488      BlockRead(&dir, BLOCK_MALLOC);
489      strcpy(rootFileEntry.name, "/");
490      rootFileEntry.mediaType = dir.fileEntry.mediaType;
491      rootFileEntry.blockIndex = dir.blockIndex;
492      rootFileEntry.blockSize = dir.fileEntry.blockSize;
493      rootFileEntry.isDirectory = 1;
494      BlockRead(&dir, BLOCK_EOF); //Flush data
495#ifdef INCLUDE_FLASH
496      file = OS_fopen("flash", "w+");
497      if(file == NULL)
498         return NULL;
499      file->fileEntry.isDirectory = 1;
500      file->fileEntry.mediaType = FILE_MEDIA_FLASH;
501      file->fileEntry.blockSize = FLASH_BLOCK_SIZE;
502      file->blockLocal = file->block;
503      file->block = NULL;
504      rc = MediaBlockInit();
505      if(rc == 1)
506         BlockRead(file, BLOCK_MALLOC);
507      else
508         BlockRead(file, FLASH_START);
509      file->fileEntry.blockIndex = file->blockIndex;
510      OS_fclose(file);
511#endif
512   }
513
514   file = (OS_FILE*)malloc(sizeof(OS_FILE));
515   if(file == NULL)
516      return NULL;
517   OS_MutexPend(mutexFilesys);
518   if(name[0] == 0 || strcmp(name, "/") == 0)
519   {
520      FileOpen(file, NULL, NULL);
521      OS_MutexPost(mutexFilesys);
522      return file;
523   }
524   if(mode[0] == 'w')
525   {
526      //Don't over write a directory
527      fileEntry.isDirectory = 0;
528      rc = FileFindRecursive(&dir, name, &fileEntry, filename);
529      if(dir.blockLocal)
530         free(dir.blockLocal);
531      if(rc == 0)
532      {
533         if(fileEntry.isDirectory)
534         {
535            free(file);
536            return NULL;
537         }
538         OS_fdelete(name);
539      }
540   }
541   rc = FileFindRecursive(&dir, name, &fileEntry, filename);
542   if(dir.blockLocal)
543      free(dir.blockLocal);
544   if(rc == -2 || (rc && mode[0] == 'r'))
545   {
546      free(file);
547      OS_MutexPost(mutexFilesys);
548      return NULL;
549   }
550   if(rc)
551      fileEntry.valid = 0;
552   rc = FileOpen(file, filename, &fileEntry); //Open file
553   file->fullname[0] = 0;
554   strncat(file->fullname, name, FULL_NAME_SIZE);
555   OS_MutexPost(mutexFilesys);
556   if(mode[0] == 'a')
557      OS_fseek(file, 0, 2); //goto end of file
558   return file;
559}
560
561
562void OS_fclose(OS_FILE *file)
563{
564   OS_FileEntry_t fileEntry;
565   OS_FILE dir;
566   char filename[FILE_NAME_SIZE];
567   int rc;
568
569   if(file->fileModified)
570   {
571      // Write file->fileEntry into parent directory
572      OS_MutexPend(mutexFilesys);
573      BlockRead(file, BLOCK_EOF);
574      rc = FileFindRecursive(&dir, file->fullname, &fileEntry, filename);
575      if(file->fileEntry.mediaType == FILE_MEDIA_FLASH && rc == 0)
576      {
577         // Invalidate old entry and add new entry at the end
578         fileEntry.valid = 0;
579         OS_fwrite(&fileEntry, sizeof(OS_FileEntry_t), 1, &dir);
580         FileFind(&dir, "endoffile", &fileEntry);
581      }
582      OS_fwrite(&file->fileEntry, sizeof(OS_FileEntry_t), 1, &dir);
583      BlockRead(&dir, BLOCK_EOF); //flush data
584      if(dir.blockLocal)
585         free(dir.blockLocal);
586      OS_MutexPost(mutexFilesys);
587   }
588   if(file->blockLocal)
589      free(file->blockLocal);
590   free(file);
591}
592
593
594int OS_fmkdir(char *name)
595{
596   OS_FILE *file;
597   file = OS_fopen(name, "w+");
598   if(file == NULL)
599      return -1;
600   file->fileEntry.isDirectory = 1;
601   OS_fclose(file);
602   return 0;
603}
604
605
606void OS_fdelete(char *name)
607{
608   OS_FILE dir, file;
609   OS_FileEntry_t fileEntry;
610   int rc;
611   uint32 blockIndex;
612   char filename[FILE_NAME_SIZE]; //Name without directories
613
614   OS_MutexPend(mutexFilesys);
615   rc = FileFindRecursive(&dir, name, &fileEntry, filename);
616   if(rc == 0)
617   {
618      FileOpen(&file, NULL, &fileEntry);
619      for(blockIndex = file.blockIndex; file.block->next != BLOCK_EOF; blockIndex = file.blockIndex)
620      {
621         BlockRead(&file, file.block->next);
622         MediaBlockFree(&file, blockIndex);
623      }
624      MediaBlockFree(&file, blockIndex);
625      fileEntry.valid = 0;
626      OS_fwrite((char*)&fileEntry, sizeof(OS_FileEntry_t), 1, &dir);
627      BlockRead(&dir, BLOCK_EOF);
628      if(file.blockLocal)
629         free(file.blockLocal);
630   }
631   if(dir.blockLocal)
632      free(dir.blockLocal);
633   OS_MutexPost(mutexFilesys);
634}
635
636
637int OS_flength(char *entry)
638{
639   OS_FileEntry_t *entry2=(OS_FileEntry_t*)entry;
640   return entry2->length;
641}
642
643
644int OS_fdir(OS_FILE *dir, char name[64])
645{
646   OS_FileEntry_t *fileEntry = (OS_FileEntry_t*)name;
647   int count;
648   for(;;)
649   {
650      count = OS_fread(fileEntry, sizeof(OS_FileEntry_t), 1, dir);
651      if(count == 0 || fileEntry->blockIndex == BLOCK_EOF)
652         return -1;
653      if(fileEntry->valid == 1)
654         break;
655   }
656   return 0;
657}
658
659/*************************************************/
660#define TEST_FILES
661#ifdef TEST_FILES
662int DirRecursive(char *name)
663{
664   OS_FileEntry_t fileEntry;
665   OS_FILE *dir;
666   char fullname[FULL_NAME_SIZE];
667   int rc;
668
669   dir = OS_fopen(name, "r");
670   for(;;)
671   {
672      rc = OS_fdir(dir, (char*)&fileEntry);
673      if(rc)
674         break;
675      printf("%s %d\n", fileEntry.name, fileEntry.length);
676      if(fileEntry.isDirectory)
677      {
678         if(strcmp(name, "/") == 0)
679            sprintf(fullname, "/%s", fileEntry.name);
680         else
681            sprintf(fullname, "%s/%s", name, fileEntry.name);
682         DirRecursive(fullname);
683      }
684   }
685   OS_fclose(dir);
686   return 0;
687}
688
689int OS_ftest(void)
690{
691   OS_FILE *file;
692   char *buf;
693   int count;
694   int i, j;
695
696   buf = (char*)malloc(5000);
697   memset(buf, 0, 5000);
698   for(count = 0; count < 4000; ++count)
699      buf[count] = (char)('A' + (count % 26));
700   OS_fmkdir("dir");
701   OS_fmkdir("/dir/subdir");
702   file = OS_fopen("/dir/subdir/test.txt", "w");
703   count = OS_fwrite(buf, 1, 4000, file);
704   OS_fclose(file);
705   memset(buf, 0, 5000);
706   file = OS_fopen("/dir/subdir/test.txt", "r");
707   count = OS_fread(buf, 1, 5000, file);
708   OS_fclose(file);
709   printf("(%s)\n", buf);
710
711   DirRecursive("/");
712
713   for(i = 0; i < 5; ++i)
714   {
715      sprintf(buf, "/dir%d", i);
716      OS_fmkdir(buf);
717      for(j = 0; j < 5; ++j)
718      {
719         sprintf(buf, "/dir%d/file%d%d", i, i, j);
720         file = OS_fopen(buf, "w");
721         sprintf(buf, "i=%d j=%d", i, j);
722         OS_fwrite(buf, 1, 8, file);
723         OS_fclose(file);
724      }
725   }
726
727   OS_fdelete("/dir1/file12");
728   DirRecursive("/");
729   file = OS_fopen("/baddir/myfile.txt", "w");
730   if(file)
731      printf("ERROR!\n");
732
733   for(i = 0; i < 5; ++i)
734   {
735      for(j = 0; j < 5; ++j)
736      {
737         sprintf(buf, "/dir%d/file%d%d", i, i, j);
738         file = OS_fopen(buf, "r");
739         if(file)
740         {
741            count = OS_fread(buf, 1, 500, file);
742            printf("i=%d j=%d count=%d (%s)\n", i, j, count, buf);
743            OS_fclose(file);
744         }
745      }
746   }
747
748   OS_fdelete("/dir/subdir/test.txt");
749   OS_fdelete("/dir/subdir");
750   OS_fdelete("/dir");
751   for(i = 0; i < 5; ++i)
752   {
753      for(j = 0; j < 5; ++j)
754      {
755         sprintf(buf, "/dir%d/file%d%d", i, i, j);
756         OS_fdelete(buf);
757      }
758      sprintf(buf, "/dir%d", i);
759      OS_fdelete(buf);
760   }
761
762   DirRecursive("/");
763
764   free(buf);
765   return 0;
766}
767#endif //TEST_FILES
plasma/kernel/flash.c
1/*--------------------------------------------------------------------
2 * TITLE: Plasma Flash
3 * AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4 * DATE CREATED: 12/17/05
5 * FILENAME: plasma.h
6 * PROJECT: Plasma CPU core
7 * COPYRIGHT: Software placed into the public domain by the author.
8 * Software 'as is' without warranty. Author liable for nothing.
9 * DESCRIPTION:
10 * Plasma flash controller
11 * Only the lower 16-bits of each 32-bit word are connected --
12 * this changes the address mapping to the flash.
13 * ByteOffset and bytes must be a multiple of two.
14 *--------------------------------------------------------------------*/
15#include "plasma.h"
16#include "rtos.h"
17
18
19void FlashRead(uint16 *dst, uint32 byteOffset, int bytes)
20{
21   volatile uint32 *ptr=(uint32*)(FLASH_BASE + (byteOffset << 1));
22   *ptr = 0xff; //read mode
23   while(bytes > 0)
24   {
25      *dst++ = (uint16)*ptr++;
26      bytes -= 2;
27   }
28}
29
30
31void FlashWrite(uint16 *src, uint32 byteOffset, int bytes)
32{
33   volatile uint32 *ptr=(uint32*)(FLASH_BASE + (byteOffset << 1));
34   while(bytes > 0)
35   {
36      *ptr = 0x40; //write mode
37      *ptr++ = *src++; //write data
38      while((*ptr & 0x80) == 0) //check status
39         ;
40      bytes -= 2;
41   }
42}
43
44
45void FlashErase(uint32 byteOffset)
46{
47   volatile uint32 *ptr=(uint32*)(FLASH_BASE + (byteOffset << 1));
48   *ptr = 0x20; //erase block
49   *ptr = 0xd0; //confirm
50   while((*ptr & 0x80) == 0) //check status
51      ;
52}
plasma/kernel/http.c
1/*--------------------------------------------------------------------
2 * TITLE: Plasma TCP/IP HTTP Server
3 * AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4 * DATE CREATED: 4/22/06
5 * FILENAME: http.c
6 * PROJECT: Plasma CPU core
7 * COPYRIGHT: Software placed into the public domain by the author.
8 * Software 'as is' without warranty. Author liable for nothing.
9 * DESCRIPTION:
10 * Plasma TCP/IP HTTP Server
11 *--------------------------------------------------------------------*/
12#ifdef WIN32
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <ctype.h>
17#define _LIBC
18#endif
19#include "rtos.h"
20#include "tcpip.h"
21#ifdef WIN32
22#define UartPrintf printf
23#define OS_MQueueCreate(A,B,C) 0
24#define OS_MQueueGet(A,B,C) 0
25#define OS_ThreadCreate(A,B,C,D,E) 0
26#endif
27
28static const char pageGif[]=
29{
30   "HTTP/1.0 200 OK\r\n"
31   "Content-Length: %d\r\n"
32   "Content-Type: binary/gif\r\n\r\n"
33};
34static const char pageGif2[]=
35{
36   "HTTP/1.0 200 OK\r\n"
37   "Content-Type: binary/gif\r\n\r\n"
38};
39static const char pageBinary[]=
40{
41   "HTTP/1.0 200 OK\r\n"
42   "Content-Length: %d\r\n"
43   "Content-Type: binary/binary\r\n\r\n"
44};
45static const char pageBinary2[]=
46{
47   "HTTP/1.0 200 OK\r\n"
48   "Content-Type: binary/binary\r\n\r\n"
49};
50static const char pageHtml[]={
51   "HTTP/1.0 200 OK\r\n"
52   "Content-Length: %d\r\n"
53   "Content-Type: text/html\r\n\r\n"
54};
55static const char pageHtml2[]={
56   "HTTP/1.0 200 OK\r\n"
57   "Content-Type: text/html\r\n\r\n"
58};
59static const char pageText[]={
60   "HTTP/1.0 200 OK\r\n"
61   "Content-Length: %d\r\n"
62   "Content-Type: text/text\r\n\r\n"
63};
64static const char pageEmpty[]=
65{
66   "HTTP/1.0 404 OK\r\n"
67   "Content-Length: 0\r\n"
68   "Content-Type: text/html\r\n\r\n"
69};
70
71static const PageEntry_t *HtmlPages;
72static int HtmlFiles;
73
74
75void HttpServer(IPSocket *socket)
76{
77   uint8 buf[600];
78   char filename[80];
79   int bytes, i, length, len, needFooter;
80   char *name=NULL, *page=NULL;
81   const char *header, *header2;
82
83   if(socket == NULL)
84      return;
85   if(socket->funcPtr != HttpServer && socket->funcPtr)
86   {
87      socket->funcPtr(socket);
88      return;
89   }
90   bytes = IPRead(socket, buf, sizeof(buf)-1);
91   if(bytes)
92   {
93      buf[bytes] = 0;
94      if(strncmp((char*)buf, "GET /", 5) == 0)
95      {
96         for(i = 0; ; ++i)
97         {
98            length = HtmlPages[i].length;
99            if(length == -1)
100               break;
101            name = (char*)HtmlPages[i].name;
102            page = (char*)HtmlPages[i].page;
103            len = (int)strlen(name);
104            if(strncmp((char*)buf+4, name, len) == 0)
105               break;
106         }
107#if defined(WIN32) || defined(INCLUDE_FILESYS)
108         if(length == HTML_LENGTH_LIST_END && HtmlFiles)
109         {
110            FILE *file;
111            char *ptr;
112
113            name = (char*)buf + 5;
114            ptr = strstr(name, " ");
115            if(ptr)
116               *ptr = 0;
117            strcpy(filename, "/web/");
118            strncat(filename, name, 60);
119            file = fopen(filename, "rb");
120            if(file == NULL)
121            {
122               strcpy(filename, "/flash/web/");
123               strncat(filename, name, 60);
124               file = fopen(filename, "rb");
125            }
126            if(file)
127            {
128               if(strstr(name, ".htm"))
129                  IPWrite(socket, (uint8*)pageHtml2, sizeof(pageHtml2)-1);
130               else if(strstr(name, ".gif"))
131                  IPWrite(socket, (uint8*)pageGif2, sizeof(pageGif2)-1);
132               else
133                  IPWrite(socket, (uint8*)pageBinary2, sizeof(pageBinary2)-1);
134               for(;;)
135               {
136                  len = fread(buf, 1, sizeof(buf), file);
137                  if(len == 0)
138                     break;
139                  IPWrite(socket, (uint8*)buf, len);
140               }
141               fclose(file);
142               IPWriteFlush(socket);
143               IPClose(socket);
144               return;
145            }
146         }
147#endif
148         if(length != HTML_LENGTH_LIST_END)
149         {
150            if(length == HTML_LENGTH_CALLBACK)
151            {
152               IPFuncPtr funcPtr = (IPFuncPtr)(uint32)page;
153               funcPtr(socket, buf, bytes);
154               return;
155            }
156            if(length == 0)
157               length = (int)strlen(page);
158            needFooter = 0;
159            header2 = NULL;
160            if(strstr(name, ".html"))
161               header = pageHtml;
162            else if(strstr(name, ".htm") || strcmp(name, "/ ") == 0)
163            {
164               header = pageHtml;
165               header2 = HtmlPages[0].page;
166               needFooter = 1;
167            }
168            else if(strstr(HtmlPages[i].name, ".gif"))
169               header = pageGif;
170            else
171               header = pageBinary;
172            len = 0;
173            if(header2)
174               len += (int)strlen(header2) + (int)strlen(HtmlPages[1].page);
175            sprintf((char*)buf, header, length + len);
176            IPWrite(socket, buf, (int)strlen((char*)buf));
177            if(header2)
178               IPWrite(socket, (uint8*)header2, (int)strlen(header2));
179            IPWrite(socket, (uint8*)page, length);
180            if(needFooter)
181               IPWrite(socket, (uint8*)HtmlPages[1].page, (int)strlen(HtmlPages[1].page));
182         }
183         else
184         {
185            IPWrite(socket, (uint8*)pageEmpty, (int)strlen(pageEmpty));
186         }
187         IPClose(socket);
188      }
189   }
190}
191
192
193void HttpInit(const PageEntry_t *Pages, int UseFiles)
194{
195   HtmlPages = Pages;
196   HtmlFiles = UseFiles;
197   IPOpen(IP_MODE_TCP, 0, 80, HttpServer);
198   IPOpen(IP_MODE_TCP, 0, 8080, HttpServer);
199}
200
201
202#ifdef EXAMPLE_HTML
203//Example test code
204static void MyProg(IPSocket *socket, char *request, int bytes)
205{
206   char *text="HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n"
207              "<html><body>Hello World!</body></html>";
208   (void)request; (void)bytes;
209   IPWrite(socket, (uint8*)text, (int)strlen(text));
210   IPClose(socket);
211}
212static const PageEntry_t pageEntry[]=
213{ //name, length, htmlText
214   {"/Header", 0, "<HTML><HEAD><TITLE>Plasma CPU</TITLE></HEAD>\n<BODY>"},
215   {"/Footer", 0, "</BODY></HTML>"},
216   {"/ ", 0, "<h2>Home Page</h2>Welcome! <a href='/other.htm'>Other</a>"
217             " <a href='/cgi/myprog'>myprog</a>"},
218   {"/other.htm ", 0, "<h2>Other</h2>Other."},
219   //{"/binary/plasma.gif ", 1945, PlasmaGif},
220   {"/cgi/myprog", HTML_LENGTH_CALLBACK, (char*)MyProg},
221   {"", HTML_LENGTH_LIST_END, NULL}
222};
223void HtmlInit(int UseFiles)
224{
225   (void)UseFiles;
226   HttpInit(pageEntry, 1);
227}
228#endif
229
230
plasma/kernel/libc.c
1/*--------------------------------------------------------------------
2 * TITLE: ANSI C Library
3 * AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4 * DATE CREATED: 12/17/05
5 * FILENAME: libc.c
6 * PROJECT: Plasma CPU core
7 * COPYRIGHT: Software placed into the public domain by the author.
8 * Software 'as is' without warranty. Author liable for nothing.
9 * DESCRIPTION:
10 * Subset of the ANSI C library
11 *--------------------------------------------------------------------*/
12#define NO_ELLIPSIS
13#include "rtos.h"
14
15
16char *strcpy(char *dst, const char *src)
17{
18   char *dstSave=dst;
19   int c;
20   do
21   {
22      c = *dst++ = *src++;
23   } while(c);
24   return dstSave;
25}
26
27
28char *strncpy(char *dst, const char *src, int count)
29{
30   int c=1;
31   char *dstSave=dst;
32   while(count-- > 0 && c)
33      c = *dst++ = *src++;
34   *dst = 0;
35   return dstSave;
36}
37
38
39char *strcat(char *dst, const char *src)
40{
41   int c;
42   char *dstSave=dst;
43   while(*dst)
44      ++dst;
45   do
46   {
47      c = *dst++ = *src++;
48   } while(c);
49   return dstSave;
50}
51
52
53char *strncat(char *dst, const char *src, int count)
54{
55   int c=1;
56   char *dstSave=dst;
57   while(*dst && --count > 0)
58      ++dst;
59   while(--count > 0 && c)
60      c = *dst++ = *src++;
61   *dst = 0;
62   return dstSave;
63}
64
65
66int strcmp(const char *string1, const char *string2)
67{
68   int diff, c;
69   for(;;)
70   {
71      diff = *string1++ - (c = *string2++);
72      if(diff)
73         return diff;
74      if(c == 0)
75         return 0;
76   }
77}
78
79
80int strncmp(const char *string1, const char *string2, int count)
81{
82   int diff, c;
83   while(count-- > 0)
84   {
85      diff = *string1++ - (c = *string2++);
86      if(diff)
87         return diff;
88      if(c == 0)
89         return 0;
90   }
91   return 0;
92}
93
94
95char *strstr(const char *string, const char *find)
96{
97   int i;
98   for(;;)
99   {
100      for(i = 0; string[i] == find[i] && find[i]; ++i) ;
101      if(find[i] == 0)
102         return (char*)string;
103      if(*string++ == 0)
104         return NULL;
105   }
106}
107
108
109int strlen(const char *string)
110{
111   const char *base=string;
112   while(*string++) ;
113   return string - base - 1;
114}
115
116
117void *memcpy(void *dst, const void *src, unsigned long bytes)
118{
119   if(((uint32)dst | (uint32)src | bytes) & 3)
120   {
121      uint8 *Dst = (uint8*)dst, *Src = (uint8*)src;
122      while((int)bytes-- > 0)
123         *Dst++ = *Src++;
124   }
125   else
126   {
127      uint32 *Dst32 = (uint32*)dst, *Src32 = (uint32*)src;
128      bytes >>= 2;
129      while((int)bytes-- > 0)
130         *Dst32++ = *Src32++;
131   }
132   return dst;
133}
134
135
136void *memmove(void *dst, const void *src, unsigned long bytes)
137{
138   uint8 *Dst = (uint8*)dst;
139   uint8 *Src = (uint8*)src;
140   if(Dst < Src)
141   {
142      while((int)bytes-- > 0)
143         *Dst++ = *Src++;
144   }
145   else
146   {
147      Dst += bytes;
148      Src += bytes;
149      while((int)bytes-- > 0)
150         *--Dst = *--Src;
151   }
152   return dst;
153}
154
155
156int memcmp(const void *cs, const void *ct, unsigned long bytes)
157{
158   uint8 *Dst = (uint8*)cs;
159   uint8 *Src = (uint8*)ct;
160   int diff;
161   while((int)bytes-- > 0)
162   {
163      diff = *Dst++ - *Src++;
164      if(diff)
165         return diff;
166   }
167   return 0;
168}
169
170
171void *memset(void *dst, int c, unsigned long bytes)
172{
173   uint8 *Dst = (uint8*)dst;
174   while((int)bytes-- > 0)
175      *Dst++ = (uint8)c;
176   return dst;
177}
178
179
180int abs(int n)
181{
182   return n>=0 ? n : -n;
183}
184
185
186static uint32 Rand1=0x1f2bcda3, Rand2=0xdeafbeef, Rand3=0xc5134306;
187int rand(void)
188{
189   int shift;
190   Rand1 += 0x13423123 + Rand2;
191   Rand2 += 0x2312fdea + Rand3;
192   Rand3 += 0xf2a12de1;
193   shift = Rand3 & 31;
194   Rand1 = (Rand1 << (32 - shift)) | (Rand1 >> shift);
195   Rand3 ^= Rand1;
196   shift = (Rand3 >> 8) & 31;
197   Rand2 = (Rand2 << (32 - shift)) | (Rand2 >> shift);
198   return Rand1;
199}
200
201
202void srand(unsigned int seed)
203{
204   Rand1 = seed;
205}
206
207
208long strtol(const char *s, char **end, int base)
209{
210   int i;
211   unsigned long ch, value=0, neg=0;
212
213   if(s[0] == '-')
214   {
215      neg = 1;
216      ++s;
217   }
218   if(s[0] == '0' && s[1] == 'x')
219   {
220      base = 16;
221      s += 2;
222   }
223   for(i = 0; i <= 8; ++i)
224   {
225      ch = *s++;
226      if('0' <= ch && ch <= '9')
227         ch -= '0';
228      else if('A' <= ch && ch <= 'Z')
229         ch = ch - 'A' + 10;
230      else if('a' <= ch && ch <= 'z')
231         ch = ch - 'a' + 10;
232      else
233         break;
234      value = value * base + ch;
235   }
236   if(end)
237      *end = (char*)s - 1;
238   if(neg)
239      value = -(int)value;
240   return value;
241}
242
243
244int atoi(const char *s)
245{
246   return strtol(s, NULL, 10);
247}
248
249
250char *itoa(int num, char *dst, int base)
251{
252   int digit, negate=0, place;
253   char c, text[20];
254
255   if(base == 10 && num < 0)
256   {
257      num = -num;
258      negate = 1;
259   }
260   text[16] = 0;
261   for(place = 15; place >= 0; --place)
262   {
263      digit = (unsigned int)num % (unsigned int)base;
264      if(num == 0 && place < 15 && base == 10 && negate)
265      {
266         c = '-';
267         negate = 0;
268      }
269      else if(digit < 10)
270         c = (char)('0' + digit);
271      else
272         c = (char)('a' + digit - 10);
273      text[place] = c;
274      num = (unsigned int)num / (unsigned int)base;
275      if(num == 0 && negate == 0)
276         break;
277   }
278   strcpy(dst, text + place);
279   return dst;
280}
281
282
283int sprintf(char *s, const char *format,
284            int arg0, int arg1, int arg2, int arg3,
285            int arg4, int arg5, int arg6, int arg7)
286{
287   int argv[8];
288   int argc=0, width, length;
289   char f, text[20], fill;
290
291   argv[0] = arg0; argv[1] = arg1; argv[2] = arg2; argv[3] = arg3;
292   argv[4] = arg4; argv[5] = arg5; argv[6] = arg6; argv[7] = arg7;
293
294   for(;;)
295   {
296      f = *format++;
297      if(f == 0)
298         return argc;
299      else if(f == '%')
300      {
301         width = 0;
302         fill = ' ';
303         f = *format++;
304         while('0' <= f && f <= '9')
305         {
306            width = width * 10 + f - '0';
307            f = *format++;
308         }
309         if(f == '.')
310         {
311            fill = '0';
312            f = *format++;
313         }
314         if(f == 0)
315            return argc;
316
317         if(f == 'd')
318         {
319            memset(s, fill, width);
320            itoa(argv[argc++], text, 10);
321            length = (int)strlen(text);
322            if(width < length)
323               width = length;
324            strcpy(s + width - length, text);
325         }
326         else if(f == 'x' || f == 'f')
327         {
328            memset(s, '0', width);
329            itoa(argv[argc++], text, 16);
330            length = (int)strlen(text);
331            if(width < length)
332               width = length;
333            strcpy(s + width - length, text);
334         }
335         else if(f == 'c')
336         {
337            *s++ = (char)argv[argc++];
338            *s = 0;
339         }
340         else if(f == 's')
341         {
342            length = strlen((char*)argv[argc]);
343            if(width > length)
344            {
345               memset(s, ' ', width - length);
346               s += width - length;
347            }
348            strcpy(s, (char*)argv[argc++]);
349         }
350         s += strlen(s);
351      }
352      else
353      {
354         if(f == '\n')
355            *s++ = '\r';
356         *s++ = f;
357         if(f == '\r' && *format == '\n')
358            *s++ = *format++;
359      }
360      *s = 0;
361   }
362}
363
364
365int sscanf(const char *s, const char *format,
366           int arg0, int arg1, int arg2, int arg3,
367           int arg4, int arg5, int arg6, int arg7)
368{
369   int argv[8];
370   int argc=0;
371   char f, *ptr;
372
373   argv[0] = arg0; argv[1] = arg1; argv[2] = arg2; argv[3] = arg3;
374   argv[4] = arg4; argv[5] = arg5; argv[6] = arg6; argv[7] = arg7;
375
376   for(;;)
377   {
378      if(*s == 0)
379         return argc;
380      f = *format++;
381      if(f == 0)
382         return argc;
383      else if(f == '%')
384      {
385         while(isspace(*s))
386            ++s;
387         f = *format++;
388         if(f == 0)
389            return argc;
390         if(f == 'd')
391            *(int*)argv[argc++] = strtol(s, (char**)&s, 10);
392         else if(f == 'x')
393            *(int*)argv[argc++] = strtol(s, (char**)&s, 16);
394         else if(f == 'c')
395            *(char*)argv[argc++] = *s++;
396         else if(f == 's')
397         {
398            ptr = (char*)argv[argc++];
399            while(!isspace(*s))
400               *ptr++ = *s++;
401            *ptr = 0;
402         }
403      }
404      else
405      {
406         while(*s && *s != f)
407            ++s;
408         if(*s)
409            ++s;
410      }
411   }
412}
413
414
415#ifdef INCLUDE_DUMP
416/*********************** dump ***********************/
417void dump(const unsigned char *data, int length)
418{
419   int i, index=0, value;
420   char string[80];
421   memset(string, 0, sizeof(string));
422   for(i = 0; i < length; ++i)
423   {
424      if((i & 15) == 0)
425      {
426         if(strlen(string))
427            printf("%s\n", string);
428         printf("%4x ", i);
429         memset(string, 0, sizeof(string));
430         index = 0;
431      }
432      value = data[i];
433      printf("%2x ", value);
434      if(isprint(value))
435         string[index] = (char)value;
436      else
437         string[index] = '.';
438      ++index;
439   }
440   for(; index < 16; ++index)
441      printf(" ");
442   printf("%s\n", string);
443}
444#endif //INCLUDE_DUMP
445
446
447#ifdef INCLUDE_QSORT
448/*********************** qsort ***********************/
449static void QsortSwap(char *base, long left, long right, long size)
450{
451   int temp, i;
452   char *ptrLeft, *ptrRight;
453   ptrLeft = base + left * size;
454   ptrRight = base + right * size;
455   for(i = 0; i < size; ++i)
456   {
457      temp = ptrLeft[i];
458      ptrLeft[i] = ptrRight[i];
459      ptrRight[i] = (char)temp;
460   }
461}
462
463
464//Modified from K&R
465static void qsort2(void *base, long left, long right, long size,
466      int (*cmp)(const void *,const void *))
467{
468   int i, last;
469   char *base2=(char*)base, *pivot;
470   if(left >= right)
471      return;
472   QsortSwap(base2, left, (left + right)/2, size);
473   last = left;
474   pivot = &base2[left*size];
475   for(i = left + 1; i <= right; ++i)
476   {
477      if(cmp(&base2[i*size], pivot) < 0)
478         QsortSwap(base2, ++last, i, size);
479   }
480   QsortSwap(base2, left, last, size);
481   qsort2(base, left, last-1, size, cmp);
482   qsort2(base, last+1, right, size, cmp);
483}
484
485
486void qsort(void *base,
487           long n,
488           long size,
489           int (*cmp)(const void *,const void *))
490{
491   qsort2(base, 0, n-1, size, cmp);
492}
493
494
495void *bsearch(const void *key,
496              const void *base,
497              long n,
498              long size,
499              int (*cmp)(const void *,const void *))
500{
501   long cond, low=0, high=n-1, mid;
502   char *base2=(char*)base;
503   while(low <= high)
504   {
505      mid = (low + high)/2;
506      cond = cmp(key, &base2[mid*size]);
507      if(cond < 0)
508         high = mid - 1;
509      else if(cond > 0)
510         low = mid + 1;
511      else
512         return &base2[mid * size];
513   }
514   return NULL;
515}
516#endif //INCLUDE_QSORT
517
518
519#ifdef INCLUDE_TIMELIB
520/************************* time.h ***********************/
521#define SEC_PER_YEAR (365L*24*60*60)
522#define SEC_PER_DAY (24L*60*60)
523//typedef unsigned long time_t; //start at 1/1/80
524//struct tm {
525// int tm_sec; //(0,59)
526// int tm_min; //(0,59)
527// int tm_hour; //(0,23)
528// int tm_mday; //(1,31)
529// int tm_mon; //(0,11)
530// int tm_year; //(0,n) from 1900
531// int tm_wday; //(0,6) calculated
532// int tm_yday; //(0,365) calculated
533// int tm_isdst; //hour adjusted for day light savings
534//};
535static const unsigned short DaysUntilMonth[]=
536   {0,31,59,90,120,151,181,212,243,273,304,334,365};
537static const unsigned short DaysInMonth[]=
538   {31,28,31,30,31,30,31,31,30,31,30,31};
539static time_t DstTimeIn, DstTimeOut;
540
541
542/* Leap year if divisible by 4. Centenary years should only be
543   leap-years if they were divisible by 400. */
544static int IsLeapYear(int year)
545{
546   return(((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0));
547}
548
549time_t mktime(struct tm *tp)
550{
551   time_t seconds;
552   unsigned long days, y, year;
553
554   days = tp->tm_mday - 1 + DaysUntilMonth[tp->tm_mon] +
555      365 * (tp->tm_year - 80);
556   seconds = (unsigned long)tp->tm_sec + 60L * (tp->tm_min +
557      60L * (tp->tm_hour + 24L * days));
558   if(tp->tm_isdst)
559      seconds -= 60 * 60;
560   year = 1900 + tp->tm_year - (tp->tm_mon < 2);
561   for(y = 1980; y <= year; y += 4)
562   {
563      if(y % 100 != 0 || y % 400 == 0)
564         seconds += SEC_PER_DAY;
565   }
566   return seconds;
567}
568
569
570void gmtime_r(const time_t *tp, struct tm *out)
571{
572   time_t seconds, delta, secondsIn=*tp;
573   int isLeapYear;
574   unsigned long year, month;
575
576   out->tm_isdst = 0;
577   if(DstTimeIn <= secondsIn && secondsIn < DstTimeOut)
578   {
579      secondsIn += 60 * 60;
580      out->tm_isdst = 1;
581   }
582   seconds = secondsIn;
583   for(year = 0; ; ++year)
584   {
585      delta = SEC_PER_YEAR + IsLeapYear(1980 + year) * SEC_PER_DAY;
586      if(seconds >= delta)
587         seconds -= delta;
588      else
589         break;
590   }
591   out->tm_year = year + 80;
592   isLeapYear = IsLeapYear(1980 + year);
593   for(month = 0; ; ++month)
594   {
595      delta = SEC_PER_DAY * (DaysInMonth[month] + (isLeapYear && (month == 1)));
596      if(seconds >= delta)
597         seconds -= delta;
598      else
599         break;
600   }
601   out->tm_mon = month;
602   out->tm_mday = seconds / SEC_PER_DAY;
603   out->tm_yday = DaysUntilMonth[month] + out->tm_mday;
604   seconds -= out->tm_mday * SEC_PER_DAY;
605   ++out->tm_mday;
606   out->tm_hour = seconds / (60 * 60);
607   seconds -= out->tm_hour * (60 * 60);
608   out->tm_min = seconds / 60;
609   seconds -= out->tm_min * 60;
610   out->tm_sec = seconds;
611   seconds = secondsIn % (SEC_PER_DAY * 7);
612   out->tm_wday = (seconds / SEC_PER_DAY + 2) % 7; /* 1/1/80 is a Tue */
613   //printf("%4.d/%2.d/%2.d:%2.d:%2.d:%2.d\n",
614   // out->tm_year+1900, out->tm_mon+1, out->tm_mday,
615   // out->tm_hour, out->tm_min, out->tm_sec);
616}
617
618
619void gmtimeDst(time_t dstTimeIn, time_t dstTimeOut)
620{
621   DstTimeIn = dstTimeIn;
622   DstTimeOut = dstTimeOut;
623}
624
625
626//DST from 2am on the second Sunday in March to 2am first Sunday in November
627void gmtimeDstSet(time_t *tp, time_t *dstTimeIn, time_t *dstTimeOut)
628{
629   time_t seconds, timeIn, timeOut;
630   struct tm tmDate;
631   int year, days;
632
633   DstTimeIn = 0;
634   DstTimeOut = 0;
635   gmtime_r(tp, &tmDate);
636   year = tmDate.tm_year;
637
638   //March 1, year, 2AM -> second Sunday
639   tmDate.tm_year = year;
640   tmDate.tm_mon = 2;
641   tmDate.tm_mday = 1;
642   tmDate.tm_hour = 2;
643   tmDate.tm_min = 0;
644   tmDate.tm_sec = 0;
645   seconds = mktime(&tmDate);
646   gmtime_r(&seconds, &tmDate);
647   days = 7 - tmDate.tm_wday + 7;
648   *dstTimeIn = timeIn = seconds + days * SEC_PER_DAY;
649
650   //November 1, year, 2AM -> first Sunday
651   tmDate.tm_year = year;
652   tmDate.tm_mon = 10;
653   tmDate.tm_mday = 1;
654   tmDate.tm_hour = 2;
655   tmDate.tm_min = 0;
656   tmDate.tm_sec = 0;
657   seconds = mktime(&tmDate);
658   gmtime_r(&seconds, &tmDate);
659   days = 7 - tmDate.tm_wday;
660   *dstTimeOut = timeOut = seconds + days * SEC_PER_DAY;
661
662   DstTimeIn = timeIn;
663   DstTimeOut = timeOut;
664}
665#endif //INCLUDE_TIMELIB
666
plasma/kernel/makefile
1# Makefile for Plasma RTOS and Plasma TCP/IP stack
2
3ifeq ($(LANG),)
4
5# Customize for Windows
6# The MIPS gcc compiler must use the cygwin1.dll that came with the compiler.
7CC_X86 = cl /O1 /nologo /I..\tools
8CP = copy
9RM = del
10DWIN32 = -DWIN32
11BIN_MIPS = ..\gccmips_elf
12TOOLS_DIR = ..\tools\\
13TOOLS2_DIR = ..\tools
14APP_DIR = ..\App\\
15LINUX_PWD =
16ALIASING =
17GCC_MIPS = $(BIN_MIPS)\gcc $(CFLAGS)
18AS_MIPS = $(BIN_MIPS)\as
19LD_MIPS = $(BIN_MIPS)\ld
20DUMP_MIPS = $(BIN_MIPS)\objdump
21CONVERT_BIN = $(TOOLS_DIR)convert_bin.exe
22OBJ = obj
23CFLAGS_X86 = /c /DWIN32
24LFLAGS_X86 =
25
26else
27
28# Customized for Linux
29# See the GNU GCC tab on the Opencores Plasma page
30CC_X86 = gcc -Wall -O -g -I../tools
31CP = cp
32RM = rm -rf
33DWIN32 =
34TOOLS_DIR = ../tools/
35TOOLS2_DIR = ../tools
36APP_DIR = ../App/
37LINUX_PWD = ./
38ALIASING = -fno-strict-aliasing
39GCC_MIPS = $(BIN_MIPS)mips-elf-gcc $(CFLAGS)
40AS_MIPS = $(BIN_MIPS)mips-elf-as
41LD_MIPS = $(BIN_MIPS)mips-elf-ld
42DUMP_MIPS = $(BIN_MIPS)mips-elf-objdump
43CONVERT_BIN = $(TOOLS_DIR)convert_bin.exe
44#CONVERT_BIN = $(BIN_MIPS)mips-elf-objcopy -I elf32-big -O binary test.axf test.bin
45OBJ = o
46CFLAGS_X86 = -c -DWIN32 -DLINUX
47LFLAGS_X86 = -lm
48
49endif
50
51# Use software multiplier (don't use mult.vhd)
52CFLAGS_SW_MULT = -mno-mul -DUSE_SW_MULT
53
54# Use 16 fewer registers (make reg_bank.vhd smaller)
55CFLAGS_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
56
57CFLAGS = -O2 -Wall -c -s -I$(TOOLS2_DIR) -msoft-float -fno-builtin
58#CFLAGS += $(CFLAGS_SW_MULT)
59#CFLAGS += $(CFLAGS_FEW_REGS)
60
61# Build just the Plasma RTOS for Plasma CPU
62rtos:
63    $(AS_MIPS) -o boot.o $(TOOLS_DIR)boot.asm
64    $(GCC_MIPS) rtos.c
65    $(GCC_MIPS) libc.c
66    $(GCC_MIPS) uart.c
67    $(GCC_MIPS) rtos_test.c
68    $(GCC_MIPS) math.c $(ALIASING)
69    $(LD_MIPS) -Ttext 0x10000000 -eentry -Map test.map -s -N -o test.axf \
70    boot.o rtos.o libc.o uart.o rtos_test.o math.o
71    $(CONVERT_BIN)
72    @sort <test.map >test2.map
73    @$(DUMP_MIPS) --disassemble test.axf > test.lst
74
75# Build the Plasma RTOS, Plasma TCP/IP stack, and web server for the Plasma CPU
76# Use the serial port and etermip for TCP/IP packets
77rtos_tcpip:
78    $(AS_MIPS) -o boot.o $(TOOLS_DIR)boot.asm
79    $(GCC_MIPS) rtos.c
80    $(GCC_MIPS) libc.c
81    $(GCC_MIPS) uart.c
82    $(GCC_MIPS) rtos_test.c -DINCLUDE_HTML -DINCLUDE_CONSOLE
83    $(GCC_MIPS) math.c $(ALIASING)
84    $(GCC_MIPS) tcpip.c -DINCLUDE_FILESYS
85    $(GCC_MIPS) http.c -DINCLUDE_FILESYS -DEXAMPLE_HTML
86    $(GCC_MIPS) netutil.c
87    $(GCC_MIPS) filesys.c
88    $(LD_MIPS) -Ttext 0x10000000 -eentry -Map test.map -s -N -o test.axf \
89    boot.o rtos.o libc.o uart.o rtos_test.o math.o tcpip.o \
90    http.o netutil.o filesys.o
91    $(CONVERT_BIN)
92    @sort <test.map >test2.map
93    @$(DUMP_MIPS) --disassemble test.axf > test.lst
94
95# Use Ethernet for TCP/IP packets, use flash file system
96rtos_tcpip_eth:
97    $(AS_MIPS) -o boot.o $(TOOLS_DIR)boot.asm
98    $(GCC_MIPS) rtos.c
99    $(GCC_MIPS) libc.c
100    $(GCC_MIPS) uart.c -DNO_PACKETS
101    $(GCC_MIPS) rtos_test.c -DINCLUDE_ETH -DINCLUDE_CONSOLE
102    $(GCC_MIPS) math.c $(ALIASING)
103    $(GCC_MIPS) tcpip.c -DINCLUDE_FILESYS
104    $(GCC_MIPS) http.c -DINCLUDE_FILESYS -DEXAMPLE_HTML
105    $(GCC_MIPS) netutil.c -DINCLUDE_FLASH -DDLL_SETUP
106    $(GCC_MIPS) filesys.c -DINCLUDE_FLASH
107    $(GCC_MIPS) ethernet.c
108    $(GCC_MIPS) flash.c
109    $(LD_MIPS) -Ttext 0x10000000 -eentry -Map test.map -s -N -o test.axf \
110    boot.o rtos.o libc.o uart.o rtos_test.o math.o tcpip.o \
111    http.o netutil.o filesys.o ethernet.o flash.o
112    $(CONVERT_BIN)
113    @sort <test.map >test2.map
114    @$(DUMP_MIPS) --disassemble test.axf > test.lst
115
116# Build full test application
117rtosfull:
118    $(AS_MIPS) -o boot.o $(TOOLS_DIR)boot.asm
119    $(GCC_MIPS) rtos.c
120    $(GCC_MIPS) libc.c
121    $(GCC_MIPS) uart.c -DNO_PACKETS
122    $(GCC_MIPS) rtos_test.c -DINCLUDE_ETH -DINCLUDE_CONSOLE
123    $(GCC_MIPS) math.c $(ALIASING)
124    $(GCC_MIPS) tcpip.c -DINCLUDE_FILESYS
125    $(GCC_MIPS) http.c -DINCLUDE_FILESYS
126    $(GCC_MIPS) netutil.c -DINCLUDE_FLASH -DDLL_SETUP
127    $(GCC_MIPS) filesys.c -DINCLUDE_FLASH
128    $(GCC_MIPS) ethernet.c
129    $(GCC_MIPS) flash.c
130    $(GCC_MIPS) -I. $(APP_DIR)html.c -DMainThread=HtmlThread
131    $(GCC_MIPS) -I. $(APP_DIR)image.c
132    $(GCC_MIPS) -I. $(APP_DIR)tictac.c
133    $(GCC_MIPS) -I. $(APP_DIR)tic3d.c
134    $(GCC_MIPS) -I. $(APP_DIR)connect4.c
135    $(LD_MIPS) -Ttext 0x10000000 -eentry -Map test.map -s -N -o test.axf \
136    boot.o rtos.o libc.o uart.o rtos_test.o math.o tcpip.o \
137    http.o netutil.o filesys.o ethernet.o flash.o \
138    html.o image.o tictac.o tic3d.o connect4.o
139    $(CONVERT_BIN)
140    @sort <test.map >test2.map
141    @$(DUMP_MIPS) --disassemble test.axf > test.lst
142
143# Create a separate Dynamically Linked Library executable
144# ftp test.bin to /flash/web/dlltest
145# telnet to board and execute "dlltest"
146dlltest:
147    $(GCC_MIPS) -G0 dlltest.c
148    $(LD_MIPS) -Ttext 0x10100000 -s -N -o test.axf dlltest.o
149    $(CONVERT_BIN)
150    @$(DUMP_MIPS) --disassemble test.axf > test.lst
151
152# Test the RTOS running on a PC
153testrtos:
154    @$(CC_X86) $(CFLAGS_X86) rtos.c
155    @$(CC_X86) $(CFLAGS_X86) libc.c
156    @$(CC_X86) $(CFLAGS_X86) uart.c
157    @$(CC_X86) $(CFLAGS_X86) rtos_test.c
158    @$(CC_X86) $(CFLAGS_X86) math.c $(ALIASING)
159    @$(CC_X86) $(LFLAGS_X86) -o testrtos.exe rtos.$(OBJ) libc.$(OBJ) uart.$(OBJ) rtos_test.$(OBJ) math.$(OBJ)
160    $(LINUX_PWD)testrtos.exe
161
162# Test the TCP/IP protocol stack running on a PC (requires Windows)
163testip:
164    @$(CC_X86) $(CFLAGS_X86) tcpip.c
165    @$(CC_X86) $(CFLAGS_X86) http.c /DEXAMPLE_HTML
166    @$(CC_X86) $(CFLAGS_X86) netutil.c
167    @$(CC_X86) $(CFLAGS_X86) filesys.c
168    @$(CC_X86) $(CFLAGS_X86) libc.c /I$(TOOLS_DIR)
169    @$(CC_X86) $(CFLAGS_X86) /DSIMULATE_PLASMA $(TOOLS_DIR)etermip.c
170    @$(CC_X86) $(CFLAGS_X86) os_stubs.c
171    @$(CC_X86) -o testip.exe etermip.obj $(TOOLS_DIR)wpcap.lib \
172    tcpip.obj http.obj netutil.obj filesys.obj libc.obj os_stubs.obj
173    @echo Try http://plasmb/. Try telnet plasmb. Try ftp plasmb.
174    $(LINUX_PWD)testip.exe
175
176clean:
177    -$(RM) *.o *.obj *.axf *.map *.lst *.hex *.txt *.bin *.exe
178
179# Run a Plasma CPU opcode simulator (can execute rtos target)
180run:
181    @$(TOOLS_DIR)mlite.exe test.bin
182
183disassemble:
184    -@$(TOOLS_DIR)mlite.exe test.bin BD > test.txt
185
186# Start the EtermIP terminal program to download the code to the Plasma CPU
187# and permit an Ethernet packets to be transfered.
188download:
189    @echo Reset board before downloading code
190    $(TOOLS_DIR)etermip.exe
191
192
plasma/kernel/math.c
1/*--------------------------------------------------------------------
2 * TITLE: Plasma Floating Point Library
3 * AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4 * DATE CREATED: 3/2/06
5 * FILENAME: math.c
6 * PROJECT: Plasma CPU core
7 * COPYRIGHT: Software placed into the public domain by the author.
8 * Software 'as is' without warranty. Author liable for nothing.
9 * DESCRIPTION:
10 * Plasma Floating Point Library
11 *--------------------------------------------------------------------
12 * IEEE_fp = sign(1) | exponent(8) | fraction(23)
13 * cos(x)=1-x^2/2!+x^4/4!-x^6/6!+...
14 * exp(x)=1+x+x^2/2!+x^3/3!+...
15 * ln(1+x)=x-x^2/2+x^3/3-x^4/4+...
16 * atan(x)=x-x^3/3+x^5/5-x^7/7+...
17 * pow(x,y)=exp(y*ln(x))
18 * x=tan(a+b)=(tan(a)+tan(b))/(1-tan(a)*tan(b))
19 * atan(x)=b+atan((x-atan(b))/(1+x*atan(b)))
20 * ln(a*x)=ln(a)+ln(x); ln(x^n)=n*ln(x)
21 *--------------------------------------------------------------------*/
22#include "rtos.h"
23
24//#define USE_SW_MULT
25#if !defined(WIN32) && !defined(USE_SW_MULT)
26#define USE_MULT64
27#endif
28
29#define PI ((float)3.1415926)
30#define PI_2 ((float)(PI/2.0))
31#define PI2 ((float)(PI*2.0))
32
33#define FtoL(X) (*(unsigned long*)&(X))
34#define LtoF(X) (*(float*)&(X))
35
36
37float FP_Neg(float a_fp)
38{
39   unsigned long a;
40   a = FtoL(a_fp);
41   a ^= 0x80000000;
42   return LtoF(a);
43}
44
45
46float FP_Add(float a_fp, float b_fp)
47{
48   unsigned long a, b, c;
49   unsigned long as, bs, cs; //sign
50   long ae, af, be, bf, ce, cf; //exponent and fraction
51   a = FtoL(a_fp);
52   b = FtoL(b_fp);
53   as = a >> 31; //sign
54   ae = (a >> 23) & 0xff; //exponent
55   af = 0x00800000 | (a & 0x007fffff); //fraction
56   bs = b >> 31;
57   be = (b >> 23) & 0xff;
58   bf = 0x00800000 | (b & 0x007fffff);
59   if(ae > be)
60   {
61      if(ae - be < 30)
62         bf >>= ae - be;
63      else
64         bf = 0;
65      ce = ae;
66   }
67   else
68   {
69      if(be - ae < 30)
70         af >>= be - ae;
71      else
72         af = 0;
73      ce = be;
74   }
75   cf = (as ? -af : af) + (bs ? -bf : bf);
76   cs = cf < 0;
77   cf = cf>=0 ? cf : -cf;
78   if(cf == 0)
79      return LtoF(cf);
80   while(cf & 0xff000000)
81   {
82      ++ce;
83      cf >>= 1;
84   }
85   while((cf & 0xff800000) == 0)
86   {
87      --ce;
88      cf <<= 1;
89   }
90   c = (cs << 31) | (ce << 23) | (cf & 0x007fffff);
91   if(ce < 1)
92      c = 0;
93   return LtoF(c);
94}
95
96
97float FP_Sub(float a_fp, float b_fp)
98{
99   return FP_Add(a_fp, FP_Neg(b_fp));
100}
101
102
103float FP_Mult(float a_fp, float b_fp)
104{
105   unsigned long a, b, c;
106   unsigned long as, af, bs, bf, cs, cf;
107   long ae, be, ce;
108#ifndef USE_MULT64
109   unsigned long a2, a1, b2, b1, med1, med2;
110#endif
111   unsigned long hi, lo;
112   a = FtoL(a_fp);
113   b = FtoL(b_fp);
114   as = a >> 31;
115   ae = (a >> 23) & 0xff;
116   af = 0x00800000 | (a & 0x007fffff);
117   bs = b >> 31;
118   be = (b >> 23) & 0xff;
119   bf = 0x00800000 | (b & 0x007fffff);
120   cs = as ^ bs;
121#ifndef USE_MULT64
122   a1 = af & 0xffff;
123   a2 = af >> 16;
124   b1 = bf & 0xffff;
125   b2 = bf >> 16;
126   lo = a1 * b1;
127   med1 = a2 * b1 + (lo >> 16);
128   med2 = a1 * b2;
129   hi = a2 * b2 + (med1 >> 16) + (med2 >> 16);
130   med1 = (med1 & 0xffff) + (med2 & 0xffff);
131   hi += (med1 >> 16);
132   lo = (med1 << 16) | (lo & 0xffff);
133#else
134   lo = OS_AsmMult(af, bf, &hi);
135#endif
136   cf = (hi << 9) | (lo >> 23);
137   ce = ae + be - 0x80 + 1;
138   if(cf == 0)
139      return LtoF(cf);
140   while(cf & 0xff000000)
141   {
142      ++ce;
143      cf >>= 1;
144   }
145   c = (cs << 31) | (ce << 23) | (cf & 0x007fffff);
146   if(ce < 1)
147      c = 0;
148   return LtoF(c);
149}
150
151
152float FP_Div(float a_fp, float b_fp)
153{
154   unsigned long a, b, c;
155   unsigned long as, af, bs, bf, cs, cf;
156   unsigned long a1, b1;
157#ifndef USE_MULT64
158   unsigned long a2, b2, med1, med2;
159#endif
160   unsigned long hi, lo;
161   long ae, be, ce, d;
162   a = FtoL(a_fp);
163   b = FtoL(b_fp);
164   as = a >> 31;
165   ae = (a >> 23) & 0xff;
166   af = 0x00800000 | (a & 0x007fffff);
167   bs = b >> 31;
168   be = (b >> 23) & 0xff;
169   bf = 0x00800000 | (b & 0x007fffff);
170   cs = as ^ bs;
171   ce = ae - (be - 0x80) + 6 - 8;
172   a1 = af << 4; //8
173   b1 = bf >> 8;
174   cf = a1 / b1;
175   cf <<= 12; //8
176#if 1 /*non-quick*/
177#ifndef USE_MULT64
178   a1 = cf & 0xffff;
179   a2 = cf >> 16;
180   b1 = bf & 0xffff;
181   b2 = bf >> 16;
182   lo = a1 * b1;
183   med1 =a2 * b1 + (lo >> 16);
184   med2 = a1 * b2;
185   hi = a2 * b2 + (med1 >> 16) + (med2 >> 16);
186   med1 = (med1 & 0xffff) + (med2 & 0xffff);
187   hi += (med1 >> 16);
188   lo = (med1 << 16) | (lo & 0xffff);
189#else
190   lo = OS_AsmMult(cf, bf, &hi);
191#endif
192   lo = (hi << 8) | (lo >> 24);
193   d = af - lo; //remainder
194   assert(-0xffff < d && d < 0xffff);
195   d <<= 16;
196   b1 = bf >> 8;
197   d = d / (long)b1;
198   cf += d;
199#endif
200   if(cf == 0)
201      return LtoF(cf);
202   while(cf & 0xff000000)
203   {
204      ++ce;
205      cf >>= 1;
206   }
207   if(ce < 0)
208      ce = 0;
209   c = (cs << 31) | (ce << 23) | (cf & 0x007fffff);
210   if(ce < 1)
211      c = 0;
212   return LtoF(c);
213}
214
215
216long FP_ToLong(float a_fp)
217{
218   unsigned long a;
219   unsigned long as;
220   long ae;
221   long af, shift;
222   a = FtoL(a_fp);
223   as = a >> 31;
224   ae = (a >> 23) & 0xff;
225   af = 0x00800000 | (a & 0x007fffff);
226   af <<= 7;
227   shift = -(ae - 0x80 - 29);
228   if(shift > 0)
229   {
230      if(shift < 31)
231         af >>= shift;
232      else
233         af = 0;
234   }
235   af = as ? -af: af;
236   return af;
237}
238
239
240float FP_ToFloat(long af)
241{
242   unsigned long a;
243   unsigned long as, ae;
244   as = af>=0 ? 0: 1;
245   af = af>=0 ? af: -af;
246   ae = 0x80 + 22;
247   if(af == 0)
248      return LtoF(af);
249   while(af & 0xff000000)
250   {
251      ++ae;
252      af >>= 1;
253   }
254   while((af & 0xff800000) == 0)
255   {
256      --ae;
257      af <<= 1;
258   }
259   a = (as << 31) | (ae << 23) | (af & 0x007fffff);
260   return LtoF(a);
261}
262
263
264//0 iff a==b; 1 iff a>b; -1 iff a<b
265int FP_Cmp(float a_fp, float b_fp)
266{
267   unsigned long a, b;
268   unsigned long as, ae, af, bs, be, bf;
269   int gt;
270   a = FtoL(a_fp);
271   b = FtoL(b_fp);
272   if(a == b)
273      return 0;
274   as = a >> 31;
275   bs = b >> 31;
276   if(as > bs)
277      return -1;
278   if(as < bs)
279      return 1;
280   gt = as ? -1 : 1;
281   ae = (a >> 23) & 0xff;
282   be = (b >> 23) & 0xff;
283   if(ae > be)
284      return gt;
285   if(ae < be)
286      return -gt;
287   af = 0x00800000 | (a & 0x007fffff);
288   bf = 0x00800000 | (b & 0x007fffff);
289   if(af > bf)
290      return gt;
291   return -gt;
292}
293
294
295int __ltsf2(float a, float b)
296{
297   return FP_Cmp(a, b);
298}
299
300int __lesf2(float a, float b)
301{
302   return FP_Cmp(a, b);
303}
304
305int __gtsf2(float a, float b)
306{
307   return FP_Cmp(a, b);
308}
309
310int __gesf2(float a, float b)
311{
312   return FP_Cmp(a, b);
313}
314
315int __eqsf2(float a, float b)
316{
317   return FtoL(a) != FtoL(b);
318}
319
320int __nesf2(float a, float b)
321{
322   return FtoL(a) != FtoL(b);
323}
324
325
326float FP_Sqrt(float a)
327{
328   float x1, y1, x2, y2, x3;
329   long i;
330   x1 = FP_ToFloat(1);
331   y1 = FP_Sub(FP_Mult(x1, x1), a); //y1=x1*x1-a;
332   x2 = FP_ToFloat(100);
333   y2 = FP_Sub(FP_Mult(x2, x2), a);
334   for(i = 0; i < 10; ++i)
335   {
336      if(FtoL(y1) == FtoL(y2))
337         return x2;
338      //x3=x2-(x1-x2)*y2/(y1-y2);
339      x3 = FP_Sub(x2, FP_Div(FP_Mult(FP_Sub(x1, x2), y2), FP_Sub(y1, y2)));
340      x1 = x2;
341      y1 = y2;
342      x2 = x3;
343      y2 = FP_Sub(FP_Mult(x2, x2), a);
344   }
345   return x2;
346}
347
348
349float FP_Cos(float rad)
350{
351   int n;
352   float answer, x2, top, bottom, sign;
353   while(FP_Cmp(rad, PI2) > 0)
354      rad = FP_Sub(rad, PI2);
355   while(FP_Cmp(rad, (float)0.0) < 0)
356      rad = FP_Add(rad, PI2);
357   answer = 1.0;
358   sign = 1.0;
359   if(FP_Cmp(rad, PI) >= 0)
360   {
361      rad = FP_Sub(rad, PI);
362      sign = FP_ToFloat(-1);
363   }
364   if(FP_Cmp(rad, PI_2) >= 0)
365   {
366      rad = FP_Sub(PI, rad);
367      sign = FP_Neg(sign);
368   }
369   x2 = FP_Mult(rad, rad);
370   top = 1.0;
371   bottom = 1.0;
372   for(n = 2; n < 12; n += 2)
373   {
374      top = FP_Mult(top, FP_Neg(x2));
375      bottom = FP_Mult(bottom, FP_ToFloat((n - 1) * n));
376      answer = FP_Add(answer, FP_Div(top, bottom));
377   }
378   return FP_Mult(answer, sign);
379}
380
381
382float FP_Sin(float rad)
383{
384   const float pi_2=(float)(PI/2.0);
385   return FP_Cos(FP_Sub(rad, pi_2));
386}
387
388
389float FP_Atan(float x)
390{
391   const float b=(float)(PI/8.0);
392   const float atan_b=(float)0.37419668; //atan(b);
393   int n;
394   float answer, x2, top;
395   if(FP_Cmp(x, (float)0.0) >= 0)
396   {
397      if(FP_Cmp(x, (float)1.0) > 0)
398         return FP_Sub(PI_2, FP_Atan(FP_Div((float)1.0, x)));
399   }
400   else
401   {
402      if(FP_Cmp(x, (float)-1.0) > 0)
403         return FP_Sub(-PI_2, FP_Atan(FP_Div((float)1.0, x)));
404   }
405   if(FP_Cmp(x, (float)0.45) > 0)
406   {
407      //answer = (x - atan_b) / (1 + x * atan_b);
408      answer = FP_Div(FP_Sub(x, atan_b), FP_Add(1.0, FP_Mult(x, atan_b)));
409      //answer = b + FP_Atan(answer) - (float)0.034633; /*FIXME fudge?*/
410      answer = FP_Sub(FP_Add(b, FP_Atan(answer)), (float)0.034633);
411      return answer;
412   }
413   if(FP_Cmp(x, (float)-0.45) < 0)
414   {
415      x = FP_Neg(x);
416      //answer = (x - atan_b) / (1 + x * atan_b);
417      answer = FP_Div(FP_Sub(x, atan_b), FP_Add(1.0, FP_Mult(x, atan_b)));
418      //answer = b + FP_Atan(answer) - (float)0.034633; /*FIXME*/
419      answer = FP_Sub(FP_Add(b, FP_Atan(answer)), (float)0.034633);
420      return FP_Neg(answer);
421   }
422   answer = x;
423   x2 = FP_Mult(FP_Neg(x), x);
424   top = x;
425   for(n = 3; n < 14; n += 2)
426   {
427      top = FP_Mult(top, x2);
428      answer = FP_Add(answer, FP_Div(top, FP_ToFloat(n)));
429   }
430   return answer;
431}
432
433
434float FP_Atan2(float y, float x)
435{
436   float answer,r;
437   r = y / x;
438   answer = FP_Atan(r);
439   if(FP_Cmp(x, (float)0.0) < 0)
440   {
441      if(FP_Cmp(y, (float)0.0) > 0)
442         answer = FP_Add(answer, PI);
443      else
444         answer = FP_Sub(answer, PI);
445   }
446   return answer;
447}
448
449
450float FP_Exp(float x)
451{
452   const float e2=(float)7.389056099;
453   const float inv_e2=(float)0.135335283;
454   float answer, top, bottom, mult;
455   int n;
456
457   mult = 1.0;
458   while(FP_Cmp(x, (float)2.0) > 0)
459   {
460      mult = FP_Mult(mult, e2);
461      x = FP_Add(x, (float)-2.0);
462   }
463   while(FP_Cmp(x, (float)-2.0) < 0)
464   {
465      mult = FP_Mult(mult, inv_e2);
466      x = FP_Add(x, (float)2.0);
467   }
468   answer = FP_Add((float)1.0, x);
469   top = x;
470   bottom = 1.0;
471   for(n = 2; n < 15; ++n)
472   {
473      top = FP_Mult(top, x);
474      bottom = FP_Mult(bottom, FP_ToFloat(n));
475      answer = FP_Add(answer, FP_Div(top, bottom));
476   }
477   return FP_Mult(answer, mult);
478}
479
480
481float FP_Log(float x)
482{
483   const float log_2=(float)0.69314718; /*log(2.0)*/
484   int n;
485   float answer, top, add;
486   add = 0.0;
487   while(FP_Cmp(x, 16.0) > 0)
488   {
489      x = FP_Mult(x, (float)0.0625);
490      add = FP_Add(add, (float)(log_2 * 4));
491   }
492   while(FP_Cmp(x, 1.5) > 0)
493   {
494      x = FP_Mult(x, 0.5);
495      add = FP_Add(add, log_2);
496   }
497   while(FP_Cmp(x, 0.5) < 0)
498   {
499      x = FP_Mult(x, 2.0);
500      add = FP_Sub(add, log_2);
501   }
502   x = FP_Sub(x, 1.0);
503   answer = 0.0;
504   top = -1.0;
505   for(n = 1; n < 14; ++n)
506   {
507      top = FP_Mult(top, FP_Neg(x));
508      answer = FP_Add(answer, FP_Div(top, FP_ToFloat(n)));
509   }
510   return FP_Add(answer, add);
511}
512
513
514float FP_Pow(float x, float y)
515{
516   return FP_Exp(y * FP_Log(x));
517}
518
519
520/********************************************/
521//These five functions will only be used if the flag "-mno-mul" is enabled
522#ifdef USE_SW_MULT
523unsigned long __mulsi3(unsigned long a, unsigned long b)
524{
525   unsigned long answer = 0;
526   while(b)
527   {
528      if(b & 1)
529         answer += a;
530      a <<= 1;
531      b >>= 1;
532   }
533   return answer;
534}
535
536
537static unsigned long DivideMod(unsigned long a, unsigned long b, int doMod)
538{
539   unsigned long upper=a, lower=0;
540   int i;
541   a = b << 31;
542   for(i = 0; i < 32; ++i)
543   {
544      lower = lower << 1;
545      if(upper >= a && a && b < 2)
546      {
547         upper = upper - a;
548         lower |= 1;
549      }
550      a = ((b&2) << 30) | (a >> 1);
551      b = b >> 1;
552   }
553   if(!doMod)
554      return lower;
555   return upper;
556}
557
558
559unsigned long __udivsi3(unsigned long a, unsigned long b)
560{
561   return DivideMod(a, b, 0);
562}
563
564
565long __divsi3(long a, long b)
566{
567   long answer, negate=0;
568   if(a < 0)
569   {
570      a = -a;
571      negate = !negate;
572   }
573   if(b < 0)
574   {
575      b = -b;
576      negate = !negate;
577   }
578   answer = DivideMod(a, b, 0);
579   if(negate)
580      answer = -answer;
581   return answer;
582}
583
584
585unsigned long __umodsi3(unsigned long a, unsigned long b)
586{
587   return DivideMod(a, b, 1);
588}
589#endif
590
591
592/*************** Test *****************/
593#ifdef WIN32
594#undef _LIBC
595#include <math.h>
596#undef printf
597#undef getch
598int printf(const char *, ...);
599struct {
600   char *name;
601   float low, high;
602   double (*func1)(double);
603   float (*func2)(float);
604} test_info[]={
605   {"cos", -2*PI, 2*PI, cos, FP_Cos},
606   {"sin", -2*PI, 2*PI, sin, FP_Sin},
607   {"atan", -3.0, 2.0, atan, FP_Atan},
608   {"log", (float)0.01, (float)4.0, log, FP_Log},
609   {"exp", (float)-5.01, (float)30.0, exp, FP_Exp},
610   {"sqrt", (float)0.01, (float)1000.0, sqrt, FP_Sqrt}
611};
612
613
614void TestMathFull(void)
615{
616   float a, b, c, d;
617   float error1, error2, error3, error4, error5;
618   int test;
619
620   a = PI * PI;
621   b = PI;
622   c = FP_Div(a, b);
623   printf("%10f %10f %10f %10f %10f\n",
624      (double)a, (double)b, (double)(a/b), (double)c, (double)(a/b-c));
625   a = a * 200;
626   for(b = -(float)2.718281828*100; b < 300; b += (float)23.678)
627   {
628      c = FP_Div(a, b);
629      d = a / b - c;
630      printf("%10f %10f %10f %10f %10f\n",
631         (double)a, (double)b, (double)(a/b), (double)c, (double)(a/b-c));
632   }
633   //getch();
634
635   for(test = 0; test < 6; ++test)
636   {
637      printf("\nTesting %s\n", test_info[test].name);
638      for(a = test_info[test].low;
639          a <= test_info[test].high;
640          a += (test_info[test].high-test_info[test].low)/(float)20.0)
641      {
642         b = (float)test_info[test].func1(a);
643         c = test_info[test].func2(a);
644         d = b - c;
645         printf("%s %10f %10f %10f %10f\n", test_info[test].name, a, b, c, d);
646      }
647      //getch();
648   }
649
650   a = FP_ToFloat((long)6.0);
651   b = FP_ToFloat((long)2.0);
652   printf("%f %f\n", (double)a, (double)b);
653   c = FP_Add(a, b);
654   printf("add %f %f\n", (double)(a + b), (double)c);
655   c = FP_Sub(a, b);
656   printf("sub %f %f\n", (double)(a - b), (double)c);
657   c = FP_Mult(a, b);
658   printf("mult %f %f\n", (double)(a * b), (double)c);
659   c = FP_Div(a, b);
660   printf("div %f %f\n", (double)(a / b), (double)c);
661   //getch();
662
663   for(a = (float)-13756.54; a < (float)17400.0; a += (float)64.45)
664   {
665      for(b = (float)-875.36; b < (float)935.8; b += (float)36.7)
666      {
667         error1 = (float)1.0 - (a + b) / FP_Add(a, b);
668         error2 = (float)1.0 - (a * b) / FP_Mult(a, b);
669         error3 = (float)1.0 - (a / b) / FP_Div(a, b);
670         error4 = (float)1.0 - a / FP_ToFloat(FP_ToLong(a));
671         error5 = error1 + error2 + error3 + error4;
672         if(error5 < 0.00005)
673            continue;
674         printf("ERROR!\n");
675         printf("a=%f b=%f\n", (double)a, (double)b);
676         printf(" a+b=%f %f\n", (double)(a+b), (double)FP_Add(a, b));
677         printf(" a*b=%f %f\n", (double)(a*b), (double)FP_Mult(a, b));
678         printf(" a/b=%f %f\n", (double)(a/b), (double)FP_Div(a, b));
679         printf(" a=%f %ld %f\n", (double)a, FP_ToLong(a),
680                                   (double)FP_ToFloat((long)a));
681         printf(" %f %f %f %f\n", (double)error1, (double)error2,
682            (double)error3, (double)error4);
683         //if(error5 > 0.001)
684         // getch();
685      }
686   }
687   printf("done.\n");
688   //getch();
689}
690#endif
691
692
plasma/kernel/netutil.c
1/*--------------------------------------------------------------------
2 * TITLE: Plasma TCP/IP Network Utilities
3 * AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4 * DATE CREATED: 4/20/07
5 * FILENAME: netutil.c
6 * PROJECT: Plasma CPU core
7 * COPYRIGHT: Software placed into the public domain by the author.
8 * Software 'as is' without warranty. Author liable for nothing.
9 * DESCRIPTION:
10 * Plasma FTP server and FTP client and TFTP server and client
11 * and Telnet server.
12 *--------------------------------------------------------------------*/
13#undef INCLUDE_FILESYS
14#define INCLUDE_FILESYS
15#ifdef WIN32
16#include <stdio.h>
17#include <stdlib.h>
18#include <string.h>
19#include <ctype.h>
20#define _LIBC
21#endif
22#include "rtos.h"
23#include "tcpip.h"
24
25#ifdef DLL_SETUP
26static void ConsoleRun(IPSocket *socket, char *argv[]);
27#endif
28
29//******************* FTP Server ************************
30typedef struct {
31   IPSocket *socket;
32   int ip, port, bytes, done, canReceive;
33   FILE *file;
34} FtpdInfo;
35
36static void FtpdSender(IPSocket *socket)
37{
38   unsigned char buf[600];
39   int i, bytes, bytes2;
40   FtpdInfo *info = (FtpdInfo*)socket->userPtr;
41
42   if(info == NULL || info->done)
43      return;
44   fseek(info->file, info->bytes, 0);
45   for(i = 0; i < 100000; ++i)
46   {
47      bytes = fread(buf, 1, 512, info->file);
48      bytes2 = IPWrite(socket, buf, bytes);
49      info->bytes += bytes2;
50      if(bytes != bytes2)
51         return;
52      if(bytes < 512)
53      {
54         fclose(info->file);
55         IPClose(socket);
56         info->done = 1;
57         IPPrintf(info->socket, "226 Done\r\n");
58         return;
59      }
60   }
61}
62
63
64static void FtpdReceiver(IPSocket *socket)
65{
66   unsigned char buf[600];
67   int bytes, state = socket->state;
68   FtpdInfo *info = (FtpdInfo*)socket->userPtr;
69
70   if(info == NULL || info->done)
71      return;
72   do
73   {
74      bytes = IPRead(socket, buf, sizeof(buf));
75      fwrite(buf, 1, bytes, info->file);
76   } while(bytes);
77
78   if(state > IP_TCP)
79   {
80      fclose(info->file);
81      info->done = 1;
82      IPPrintf(info->socket, "226 Done\r\n");
83      IPClose(socket);
84      return;
85   }
86}
87
88
89static void FtpdServer(IPSocket *socket)
90{
91   uint8 buf[600];
92   int bytes;
93   int ip0, ip1, ip2, ip3, port0, port1;
94   IPSocket *socketOut;
95   FtpdInfo *info = (FtpdInfo*)socket->userPtr;
96
97   if(socket == NULL)
98      return;
99   bytes = IPRead(socket, buf, sizeof(buf)-1);
100   buf[bytes] = 0;
101   //printf("(%s)\n", buf);
102   if(socket->userPtr == NULL)
103   {
104      info = (FtpdInfo*)malloc(sizeof(FtpdInfo));
105      if(info == NULL)
106         return;
107      memset(info, 0, sizeof(FtpdInfo));
108      socket->userPtr = info;
109      info->socket = socket;
110      socket->timeoutReset = 60;
111      IPPrintf(socket, "220 Connected to Plasma\r\n");
112   }
113   else if(socket->userPtr == (void*)-1)
114   {
115      return;
116   }
117   else if(strstr((char*)buf, "USER"))
118   {
119      if(strstr((char*)buf, "PlasmaSend"))
120         info->canReceive = 1;
121      IPPrintf(socket, "331 Password?\r\n");
122   }
123   else if(strstr((char*)buf, "PASS"))
124   {
125      IPPrintf(socket, "230 Logged in\r\n");
126   }
127   else if(strstr((char*)buf, "PORT"))
128   {
129      sscanf((char*)buf + 5, "%d,%d,%d,%d,%d,%d", &ip0, &ip1, &ip2, &ip3, &port0, &port1);
130      info->ip = (ip0 << 24) | (ip1 << 16) | (ip2 << 8) | ip3;
131      info->port = (port0 << 8) | port1;
132      //printf("ip=0x%x port=%d\n", info->ip, info->port);
133      IPPrintf(socket, "200 OK\r\n");
134   }
135   else if(strstr((char*)buf, "RETR") || strstr((char*)buf, "STOR"))
136   {
137      char *ptr = strstr((char*)buf, "\r");
138      if(ptr)
139         *ptr = 0;
140      info->file = NULL;
141      info->bytes = 0;
142      info->done = 0;
143      if(strstr((char*)buf, "RETR"))
144         info->file = fopen((char*)buf + 5, "rb");
145      else if(info->canReceive)
146         info->file = fopen((char*)buf + 5, "wb");
147      if(info->file)
148      {
149         IPPrintf(socket, "150 File ready\r\n");
150         if(strstr((char*)buf, "RETR"))
151            socketOut = IPOpen(IP_MODE_TCP, info->ip, info->port, FtpdSender);
152         else
153            socketOut = IPOpen(IP_MODE_TCP, info->ip, info->port, FtpdReceiver);
154         if(socketOut)
155            socketOut->userPtr = info;
156      }
157      else
158      {
159         IPPrintf(socket, "500 Error\r\n");
160      }
161   }
162   else if(strstr((char*)buf, "QUIT"))
163   {
164      if(socket->userPtr)
165         free(socket->userPtr);
166      socket->userPtr = (void*)-1;
167      IPPrintf(socket, "221 Bye\r\n");
168      IPClose(socket);
169   }
170   else if(bytes)
171   {
172      IPPrintf(socket, "500 Error\r\n");
173   }
174}
175
176
177void FtpdInit(int UseFiles)
178{
179   (void)UseFiles;
180   IPOpen(IP_MODE_TCP, 0, 21, FtpdServer);
181}
182
183
184//******************* FTP Client ************************
185
186typedef struct {
187   uint32 ip, port;
188   char user[80], passwd[80], filename[80];
189   uint8 *buf;
190   int size, bytes, send, state;
191} FtpInfo;
192
193
194static void FtpCallbackTransfer(IPSocket *socket)
195{
196   int bytes, state = socket->state;
197   FtpInfo *info = (FtpInfo*)socket->userPtr;
198
199   //printf("FtpCallbackTransfer\n");
200   if(info == NULL)
201      return;
202   bytes = info->size - info->bytes;
203   if(info->send == 0)
204      bytes = IPRead(socket, info->buf + info->bytes, bytes);
205   else
206      bytes = IPWrite(socket, info->buf + info->bytes, bytes);
207   info->bytes += bytes;
208   if(info->bytes == info->size || (bytes == 0 && state > IP_TCP))
209   {
210      socket->userFunc(info->buf, info->bytes);
211      free(info);
212      socket->userPtr = NULL;
213      IPClose(socket);
214   }
215}
216
217
218static void FtpCallback(IPSocket *socket)
219{
220   char buf[600];
221   FtpInfo *info = (FtpInfo*)socket->userPtr;
222   int bytes, value;
223
224   bytes = IPRead(socket, (uint8*)buf, sizeof(buf)-1);
225   if(bytes == 0)
226      return;
227   buf[bytes] = 0;
228   sscanf(buf, "%d", &value);
229   if(bytes > 2)
230      buf[bytes-2] = 0;
231   //printf("FtpCallback(%d:%s)\n", socket->userData, buf);
232   if(value / 100 != 2 && value / 100 != 3)
233      return;
234   buf[0] = 0;
235   switch(socket->userData) {
236   case 0:
237      sprintf(buf, "USER %s\r\n", info->user);
238      socket->userData = 1;
239      break;
240   case 1:
241      sprintf(buf, "PASS %s\r\n", info->passwd);
242      socket->userData = 2;
243      if(value == 331)
244         break; //possible fall-through
245   case 2:
246      sprintf(buf, "PORT %d,%d,%d,%d,%d,%d\r\n",
247         info->ip >> 24, (uint8)(info->ip >> 16),
248         (uint8)(info->ip >> 8), (uint8)info->ip,
249         (uint8)(info->port >> 8), (uint8)info->port);
250      socket->userData = 3;
251      break;
252   case 3:
253      if(info->send == 0)
254         sprintf(buf, "RETR %s\r\n", info->filename);
255      else
256         sprintf(buf, "STOR %s\r\n", info->filename);
257      socket->userData = 4;
258      break;
259   case 4:
260      sprintf(buf, "QUIT\r\n");
261      socket->userData = 9;
262      break;
263   }
264   IPWrite(socket, (uint8*)buf, strlen(buf));
265   IPWriteFlush(socket);
266   if(socket->userData == 9)
267      IPClose(socket);
268}
269
270
271IPSocket *FtpTransfer(uint32 ip, char *user, char *passwd,
272                      char *filename, uint8 *buf, int size,
273                      int send, void (*callback)(uint8 *data, int size))
274{
275   IPSocket *socket, *socketTransfer;
276   FtpInfo *info;
277   uint8 *ptr;
278   info = (FtpInfo*)malloc(sizeof(FtpInfo));
279   if(info == NULL)
280      return NULL;
281   strncpy(info->user, user, 80);
282   strncpy(info->passwd, passwd, 80);
283   strncpy(info->filename, filename, 80);
284   info->buf = buf;
285   info->size = size;
286   info->send = send;
287   info->bytes = 0;
288   info->state = 0;
289   info->port = 2000;
290   socketTransfer = IPOpen(IP_MODE_TCP, 0, info->port, FtpCallbackTransfer);
291   socketTransfer->userPtr = info;
292   socketTransfer->userFunc = callback;
293   socket = IPOpen(IP_MODE_TCP, ip, 21, FtpCallback);
294   socket->userPtr = info;
295   socket->userFunc = callback;
296   ptr = socket->headerSend;
297   info->ip = IPAddressSelf();
298   return socket;
299}
300
301
302//******************* TFTP Server ************************
303
304
305static void TftpdCallback(IPSocket *socket)
306{
307   unsigned char buf[512+4];
308   int bytes, blockNum;
309   FILE *file = (FILE*)socket->userPtr;
310   bytes = IPRead(socket, buf, sizeof(buf));
311   //printf("TfptdCallback bytes=%d\n", bytes);
312   if(bytes < 4 || buf[0])
313      return;
314   if(buf[1] == 1) //RRQ = Read Request
315   {
316      if(file)
317         fclose(file);
318      file = fopen((char*)buf+2, "rb");
319      socket->userPtr = file;
320      if(file == NULL)
321      {
322         buf[0] = 0;
323         buf[1] = 5; //ERROR
324         buf[2] = 0;
325         buf[3] = 0;
326         buf[4] = 'X'; //Error string
327         buf[5] = 0;
328         IPWrite(socket, buf, 6);
329         return;
330      }
331   }
332   if(buf[1] == 1 || buf[1] == 4) //ACK
333   {
334      if(file == NULL)
335         return;
336      if(buf[1] == 1)
337         blockNum = 0;
338      else
339         blockNum = (buf[2] << 8) | buf[3];
340      ++blockNum;
341      buf[0] = 0;
342      buf[1] = 3; //DATA
343      buf[2] = (uint8)(blockNum >> 8);
344      buf[3] = (uint8)blockNum;
345      fseek(file, (blockNum-1)*512, 0);
346      bytes = fread(buf+4, 1, 512, file);
347      IPWrite(socket, buf, bytes+4);
348   }
349}
350
351
352void TftpdInit(void)
353{
354   IPSocket *socket;
355   socket = IPOpen(IP_MODE_UDP, 0, 69, TftpdCallback);
356}
357
358
359//******************* TFTP Client ************************
360
361
362static void TftpCallback(IPSocket *socket)
363{
364   unsigned char buf[512+4];
365   int bytes, blockNum, length;
366
367   bytes = IPRead(socket, buf, sizeof(buf));
368   if(bytes < 4 || buf[0])
369      return;
370   blockNum = (buf[2] << 8) | buf[3];
371   length = blockNum * 512 - 512 + bytes - 4;
372   //printf("TftpCallback(%d,%d)\n", buf[1], blockNum);
373   if(length > (int)socket->userData)
374   {
375      bytes -= length - (int)socket->userData;
376      length = (int)socket->userData;
377   }
378   if(buf[1] == 3) //DATA
379   {
380      memcpy((uint8*)socket->userPtr + blockNum * 512 - 512, buf+4, bytes-4);
381      buf[1] = 4; //ACK
382      IPWrite(socket, buf, 4);
383      if(bytes-4 < 512)
384      {
385         socket->userFunc(socket->userPtr, length);
386         IPClose(socket);
387      }
388   }
389}
390
391
392IPSocket *TftpTransfer(uint32 ip, char *filename, uint8 *buffer, int size,
393                       void (*callback)(uint8 *data, int bytes))
394{
395   IPSocket *socket;
396   uint8 buf[512+4];
397   int bytes;
398   socket = IPOpen(IP_MODE_UDP, ip, 69, TftpCallback);
399   socket->userPtr = buffer;
400   socket->userData = size;
401   socket->userFunc = callback;
402   buf[0] = 0;
403   buf[1] = 1; //read
404   strcpy((char*)buf+2, filename);
405   bytes = strlen(filename);
406   strcpy((char*)buf+bytes+3, "octet");
407   IPWrite(socket, buf, bytes+9);
408   return socket;
409}
410
411
412//******************* Telnet Server ************************
413
414#define COMMAND_BUFFER_SIZE 80
415#define COMMAND_BUFFER_COUNT 10
416static char CommandHistory[400];
417static char *CommandPtr[COMMAND_BUFFER_COUNT];
418static int CommandIndex;
419
420typedef void (*ConsoleFunc)(IPSocket *socket, char *argv[]);
421typedef struct {
422   char *name;
423   ConsoleFunc func;
424} TelnetFunc_t;
425static TelnetFunc_t *TelnetFuncList;
426
427
428static void TelnetServer(IPSocket *socket)
429{
430   uint8 buf[COMMAND_BUFFER_SIZE+4];
431   char bufOut[32];
432   int bytes, i, j, k, length, found;
433   char *ptr, *command = socket->userPtr;
434   char *argv[10];
435
436   if(socket->state > IP_TCP)
437      return;
438   for(;;)
439   {
440      bytes = IPRead(socket, buf, sizeof(buf)-1);
441      if(command == NULL)
442      {
443         socket->userPtr = command = (char*)malloc(COMMAND_BUFFER_SIZE);
444         if(command == NULL)
445         {
446            IPClose(socket);
447            return;
448         }
449         socket->timeoutReset = 300;
450         buf[0] = 255; //IAC
451         buf[1] = 251; //WILL
452         buf[2] = 3; //suppress go ahead
453         buf[3] = 255; //IAC
454         buf[4] = 251; //WILL
455         buf[5] = 1; //echo
456         strcpy((char*)buf+6, "Welcome to Plasma.\r\n-> ");
457         IPWrite(socket, buf, 6+23);
458         IPWriteFlush(socket);
459         command[0] = 0;
460         return;
461      }
462      if(bytes == 0)
463         return;
464      socket->dontFlush = 0;
465      buf[bytes] = 0;
466      length = (int)strlen(command);
467      for(j = 0; j < bytes; ++j)
468      {
469         if(buf[j] == 255)
470            return;
471         if(buf[j] == 8 || (buf[j] == 27 && buf[j+2] == 'D'))
472         {
473            if(buf[j] == 27)
474               j += 2;
475            if(length)
476            {
477               // Backspace
478               command[--length] = 0;
479               bufOut[0] = 8;
480               bufOut[1] = ' ';
481               bufOut[2] = 8;
482               IPWrite(socket, (uint8*)bufOut, 3);
483            }
484         }
485         else if(buf[j] == 27)
486         {
487            // Command History
488            if(buf[j+2] == 'A')
489            {
490               if(++CommandIndex > COMMAND_BUFFER_COUNT)
491                  CommandIndex = COMMAND_BUFFER_COUNT;
492            }
493            else if(buf[j+2] == 'B')
494            {
495               if(--CommandIndex < 0)
496                  CommandIndex = 0;
497            }
498            else
499               return;
500            bufOut[0] = 8;
501            bufOut[1] = ' ';
502            bufOut[2] = 8;
503            for(i = 0; i < length; ++i)
504               IPWrite(socket, (uint8*)bufOut, 3);
505            command[0] = 0;
506            if(CommandIndex && CommandPtr[CommandIndex-1])
507               strncat(command, CommandPtr[CommandIndex-1], COMMAND_BUFFER_SIZE-1);
508            length = (int)strlen(command);
509            IPWrite(socket, (uint8*)command, length);
510            j += 2;
511         }
512         else
513         {
514            if(buf[j] == 0)
515               buf[j] = '\n'; //Linux support
516            if(length < COMMAND_BUFFER_SIZE-4 || (length <
517               COMMAND_BUFFER_SIZE-2 && (buf[j] == '\r' || buf[j] == '\n')))
518            {
519               IPWrite(socket, buf+j, 1);
520               command[length] = buf[j];
521               command[++length] = 0;
522            }
523         }
524         ptr = strstr(command, "\r\n");
525         if(ptr)
526         {
527            // Save command in CommandHistory
528            ptr[0] = 0;
529            length = (int)strlen(command);
530            if(length == 0)
531            {
532               IPPrintf(socket, "-> ");
533               continue;
534            }
535            if(length < COMMAND_BUFFER_SIZE)
536            {
537               memmove(CommandHistory + length + 1, CommandHistory,
538                  sizeof(CommandHistory) - length - 1);
539               strcpy(CommandHistory, command);
540               CommandHistory[sizeof(CommandHistory)-1] = 0;
541               for(i = COMMAND_BUFFER_COUNT-2; i >= 0; --i)
542               {
543                  if(CommandPtr[i] == NULL || CommandPtr[i] + length + 1 >=
544                     CommandHistory + sizeof(CommandHistory))
545                     CommandPtr[i+1] = NULL;
546                  else
547                     CommandPtr[i+1] = CommandPtr[i] + length + 1;
548               }
549               CommandPtr[0] = CommandHistory;
550            }
551
552            //Start command
553            for(i = 0; i < 10; ++i)
554               argv[i] = "";
555            i = 0;
556            argv[i++] = command;
557            for(ptr = command; *ptr && i < 10; ++ptr)
558            {
559               if(*ptr == ' ')
560               {
561                  *ptr = 0;
562                  argv[i++] = ptr + 1;
563               }
564            }
565            if(argv[0][0] == 0)
566            {
567               IPPrintf(socket, "-> ");
568               continue;
569            }
570            found = 0;
571            for(i = 0; TelnetFuncList[i].name; ++i)
572            {
573               if(strcmp(command, TelnetFuncList[i].name) == 0 &&
574                  TelnetFuncList[i].func)
575               {
576                  found = 1;
577                  for(k = 1; k < 10; ++k)
578                  {
579                     if(argv[k][0] == '>' && argv[k][1]) //stdout to file?
580                     {
581                        socket->fileOut = fopen(&argv[k][1], "a");
582                        argv[k] = "";
583                     }
584                     if(argv[k][0] == '<' && argv[k][1]) //stdin from file?
585                     {
586                        socket->fileIn = fopen(&argv[k][1], "r");
587                        argv[k] = "";
588                     }
589                  }
590                  TelnetFuncList[i].func(socket, argv);
591                  if(socket->fileOut)
592                  {
593                     fwrite("\r\n", 1, 2, socket->fileOut);
594                     fclose(socket->fileOut);
595                  }
596                  socket->fileOut = NULL;
597                  break;
598               }
599            }
600#ifdef DLL_SETUP
601            if(found == 0)
602            {
603               strcpy((char*)buf, "/flash/bin/");
604               strcat((char*)buf, argv[0]);
605               argv[0] = (char*)buf;
606               ConsoleRun(socket, argv);
607            }
608#endif
609            if(socket->state > IP_TCP)
610               return;
611            command[0] = 0;
612            length = 0;
613            CommandIndex = 0;
614            if(socket->dontFlush == 0)
615               IPPrintf(socket, "\r\n-> ");
616         } //command entered
617      } //bytes
618      IPWriteFlush(socket);
619   }
620}
621
622
623void TelnetInit(TelnetFunc_t *funcList)
624{
625   IPSocket *socket;
626   TelnetFuncList = funcList;
627   socket = IPOpen(IP_MODE_TCP, 0, 23, TelnetServer);
628}
629
630
631//******************* Console ************************
632
633#define STORAGE_SIZE 1024*64
634static uint8 *myStorage;
635static IPSocket *socketTelnet;
636static char storageFilename[60];
637
638
639static void ConsoleHelp(IPSocket *socket, char *argv[])
640{
641   char buf[200];
642   int i;
643   (void)argv;
644   strcpy(buf, "Commands: ");
645   for(i = 0; TelnetFuncList[i].name; ++i)
646   {
647      if(TelnetFuncList[i].func)
648      {
649         if(i)
650            strcat(buf, ", ");
651         strcat(buf, TelnetFuncList[i].name);
652      }
653   }
654   IPPrintf(socket, buf);
655}
656
657
658static void ConsoleExit(IPSocket *socket, char *argv[])
659{
660   free(argv[0]);
661   socket->userPtr = NULL;
662   IPClose(socket);
663}
664
665
666static void ConsoleCat(IPSocket *socket, char *argv[])
667{
668   FILE *file;
669   uint8 buf[200];
670   int bytes;
671
672   file = fopen(argv[1], "r");
673   if(file == NULL)
674      return;
675   for(;;)
676   {
677      bytes = fread(buf, 1, sizeof(buf), file);
678      if(bytes == 0)
679         break;
680      IPWrite(socket, buf, bytes);
681   }
682   fclose(file);
683}
684
685
686static void ConsoleCp(IPSocket *socket, char *argv[])
687{
688   FILE *fileIn, *fileOut;
689   uint8 buf[200];
690   int bytes;
691   (void)socket;
692
693   fileIn = fopen(argv[1], "r");
694   if(fileIn == NULL)
695      return;
696   fileOut = fopen(argv[2], "w");
697   if(fileOut)
698   {
699      for(;;)
700      {
701         bytes = fread(buf, 1, sizeof(buf), fileIn);
702         if(bytes == 0)
703            break;
704         fwrite(buf, 1, bytes, fileOut);
705      }
706      fclose(fileOut);
707   }
708   fclose(fileIn);
709}
710
711
712static void ConsoleRm(IPSocket *socket, char *argv[])
713{
714   (void)socket;
715   OS_fdelete(argv[1]);
716}
717
718
719static void ConsoleMkdir(IPSocket *socket, char *argv[])
720{
721   (void)socket;
722   OS_fmkdir(argv[1]);
723}
724
725
726static void ConsoleLs(IPSocket *socket, char *argv[])
727{
728   FILE *file;
729   char buf[200], buf2[80];
730   int bytes, width;
731
732   file = fopen(argv[1], "r");
733   if(file == NULL)
734      return;
735   width = 0;
736   for(;;)
737   {
738      bytes = OS_fdir(file, buf);
739      if(bytes)
740         break;
741      if(buf[0] == 255)
742         continue;
743      bytes = OS_flength(buf);
744      sprintf(buf2, "%s:%d ", buf, bytes);
745      bytes = strlen(buf2);
746      bytes -= bytes % 20;
747      buf2[bytes] = 0;
748      width += bytes;
749      if(width == 80)
750         --bytes;
751      if(width > 80)
752      {
753         IPPrintf(socket, "\n");
754         width = bytes;
755      }
756      IPPrintf(socket, "%s", buf2);
757   }
758   fclose(file);
759}
760
761
762#ifdef INCLUDE_FLASH
763static void ConsoleFlashErase(IPSocket *socket, char *argv[])
764{
765   int bytes;
766   (void)argv;
767   IPPrintf(socket, "\r\nErasing");
768   for(bytes = 1024*128; bytes < 1024*1024*16; bytes += 1024*128)
769   {
770      IPPrintf(socket, ".");
771      FlashErase(bytes);
772   }
773   IPPrintf(socket, "\r\nMust Reboot\r\n");
774   OS_ThreadSleep(OS_WAIT_FOREVER);
775}
776#endif
777
778
779static void ConsoleMath(IPSocket *socket, char *argv[])
780{
781   int v1, v2, ch;
782   if(argv[3][0] == 0)
783   {
784      IPPrintf(socket, "Usage: math <number> <operator> <value>\r\n");
785      return;
786   }
787   v1 = atoi(argv[1]);
788   ch = argv[2][0];
789   v2 = atoi(argv[3]);
790   if(ch == '+')
791      v1 += v2;
792   else if(ch == '-')
793      v1 -= v2;
794   else if(ch == '*')
795      v1 *= v2;
796   else if(ch == '/')
797   {
798      if(v2 != 0)
799         v1 /= v2;
800   }
801   IPPrintf(socket, "%d", v1);
802}
803
804
805static void PingCallback(IPSocket *socket)
806{
807   IPSocket *socket2 = socket->userPtr;
808   IPClose(socket);
809   if(socket2)
810      IPPrintf(socket2, "Ping Reply");
811   else
812      printf("Ping Reply\n");
813}
814
815
816static void DnsResultCallback(IPSocket *socket, uint32 ip, void *arg)
817{
818   char buf[COMMAND_BUFFER_SIZE];
819   IPSocket *socketTelnet = arg;
820   IPSocket *socketPing;
821   (void)socket;
822
823   sprintf(buf, "ip=%d.%d.%d.%d\r\n",
824      (uint8)(ip >> 24), (uint8)(ip >> 16), (uint8)(ip >> 8), (uint8)ip);
825   IPPrintf(socketTelnet, buf);
826   socketPing = IPOpen(IP_MODE_PING, ip, 0, PingCallback);
827   socketPing->userPtr = socketTelnet;
828   buf[0] = 'A';
829   IPWrite(socketPing, (uint8*)buf, 1);
830}
831
832
833static void ConsolePing(IPSocket *socket, char *argv[])
834{
835   int ip0, ip1, ip2, ip3;
836
837   if('0' <= argv[1][0] && argv[1][0] <= '9')
838   {
839      sscanf(argv[1], "%d.%d.%d.%d", &ip0, &ip1, &ip2, &ip3);
840      ip0 = (ip0 << 24) | (ip1 << 16) | (ip2 << 8) | ip3;
841      DnsResultCallback(socket, ip0, socket);
842   }
843   else
844   {
845      IPResolve(argv[1], DnsResultCallback, socket);
846      IPPrintf(socket, "Sent DNS request");
847   }
848}
849
850
851static void ConsoleTransferDone(uint8 *data, int length)
852{
853   FILE *file;
854   IPPrintf(socketTelnet, "Transfer Done");
855   file = fopen(storageFilename, "w");
856   if(file)
857   {
858      fwrite(data, 1, length, file);
859      fclose(file);
860   }
861   if(myStorage)
862      free(myStorage);
863   myStorage = NULL;
864}
865
866
867static void ConsoleFtp(IPSocket *socket, char *argv[])
868{
869   int ip0, ip1, ip2, ip3;
870   if(argv[1][0] == 0)
871   {
872      IPPrintf(socket, "ftp #.#.#.# User Password File");
873      return;
874   }
875   sscanf(argv[1], "%d.%d.%d.%d", &ip0, &ip1, &ip2, &ip3);
876   ip0 = (ip0 << 24) | (ip1 << 16) | (ip2 << 8) | ip3;
877   socketTelnet = socket;
878   if(myStorage == NULL)
879      myStorage = (uint8*)malloc(STORAGE_SIZE);
880   if(myStorage == NULL)
881      return;
882   strcpy(storageFilename, argv[4]);
883   FtpTransfer(ip0, argv[2], argv[3], argv[4], myStorage, STORAGE_SIZE-1,
884      0, ConsoleTransferDone);
885}
886
887
888static void ConsoleTftp(IPSocket *socket, char *argv[])
889{
890   int ip0, ip1, ip2, ip3;
891   if(argv[1][0] == 0)
892   {
893      IPPrintf(socket, "tftp #.#.#.# File");
894      return;
895   }
896   sscanf(argv[1], "%d.%d.%d.%d", &ip0, &ip1, &ip2, &ip3);
897   ip0 = (ip0 << 24) | (ip1 << 16) | (ip2 << 8) | ip3;
898   socketTelnet = socket;
899   if(myStorage == NULL)
900      myStorage = (uint8*)malloc(STORAGE_SIZE);
901   if(myStorage == NULL)
902      return;
903   strcpy(storageFilename, argv[2]);
904   TftpTransfer(ip0, argv[2], myStorage, STORAGE_SIZE-1, ConsoleTransferDone);
905}
906
907
908static void ConsoleMkfile(IPSocket *socket, char *argv[])
909{
910   OS_FILE *file;
911   (void)argv;
912   file = fopen("myfile.txt", "w");
913   fwrite("Hello World!", 1, 12, file);
914   fclose(file);
915   IPPrintf(socket, "Created myfile.txt");
916}
917
918
919static void ConsoleUptime(IPSocket *socket, char *argv[])
920{
921   int days, hours, minutes, seconds;
922   (void)argv;
923   //ticks per sec = 25E6/2^18 = 95.36743 -> 10.48576 ms/tick
924   seconds = OS_ThreadTime() / 95;
925   minutes = seconds / 60 % 60;
926   hours = seconds / 3600 % 24;
927   days = seconds / 3600 / 24;
928   seconds %= 60;
929   IPPrintf(socket, "%d days %2d:%2d:%2d\n", days, hours, minutes, seconds);
930}
931
932
933static void ConsoleDump(IPSocket *socket, char *argv[])
934{
935   FILE *fileIn;
936   uint8 buf[16];
937   int bytes, i, j;
938
939   fileIn = fopen(argv[1], "r");
940   if(fileIn == NULL)
941      return;
942   for(j = 0; j < 1024*1024*16; j += 16)
943   {
944      bytes = fread(buf, 1, 16, fileIn);
945      if(bytes == 0)
946         break;
947      IPPrintf(socket, "%8x ", j);
948      for(i = 0; i < bytes; ++i)
949         IPPrintf(socket, "%2x ", buf[i]);
950      for( ; i < 16; ++i)
951         IPPrintf(socket, " ");
952      for(i = 0; i < bytes; ++i)
953      {
954         if(isprint(buf[i]))
955            IPPrintf(socket, "%c", buf[i]);
956         else
957            IPPrintf(socket, ".");
958      }
959      IPPrintf(socket, "\n");
960   }
961   fclose(fileIn);
962}
963
964
965static void ConsoleGrep(IPSocket *socket, char *argv[])
966{
967   FILE *fileIn;
968   char buf[200];
969   int bytes;
970   char *ptr, *ptrEnd;
971
972   if(argv[1][0] == 0 || argv[2][0] == 0)
973   {
974      IPPrintf(socket, "Usage: grep pattern file\n");
975      return;
976   }
977   fileIn = fopen(argv[2], "r");
978   if(fileIn == NULL)
979      return;
980   bytes = 0;
981   for(;;)
982   {
983      bytes += fread(buf + bytes, 1, sizeof(buf) - bytes - 1, fileIn);
984      if(bytes == 0)
985         break;
986      buf[bytes] = 0;
987      ptrEnd = strstr(buf, "\r");
988      if(ptrEnd == NULL)
989         ptrEnd = strstr(buf, "\n");
990      if(ptrEnd)
991      {
992         *ptrEnd = 0;
993         if(*++ptrEnd == '\n')
994            ++ptrEnd;
995      }
996      ptr = strstr(buf, argv[1]);
997      if(ptr)
998         IPPrintf(socket, "%s\n", buf);
999      if(ptrEnd)
1000      {
1001         bytes = strlen(ptrEnd);
1002         memcpy(buf, ptrEnd, bytes);
1003      }
1004      else
1005      {
1006         bytes = 0;
1007      }
1008   }
1009   fclose(fileIn);
1010}
1011
1012
1013#ifdef DLL_SETUP
1014#include "dll.h"
1015
1016static void ConsoleRun(IPSocket *socket, char *argv[])
1017{
1018   FILE *file;
1019   int bytes, i;
1020   uint8 code[128];
1021   DllFunc funcPtr;
1022   char *command, *ptr;
1023
1024   if(strcmp(argv[0], "run") == 0)
1025      ++argv;
1026   file = fopen(argv[0], "r");
1027   if(file == NULL)
1028   {
1029      IPPrintf(socket, "Can't find %s", argv[0]);
1030      return;
1031   }
1032
1033   bytes = fread(code, 1, sizeof(code), file); //load first 128 bytes
1034   if(code[0] >= ' ')
1035   {
1036      socket->fileIn = file; //script file
1037      fseek(file, 0, 0);
1038      return;
1039   }
1040
1041   funcPtr = (DllFunc)code;
1042   ptr = funcPtr(NULL); //determine load address
1043
1044   memcpy(ptr, code, bytes); //copy to correct address
1045   bytes += fread(ptr + bytes, 1, 1024*1024*8, file);
1046   fclose(file);
1047   printf("address=0x%x bytes=%d\n", (int)ptr, bytes);
1048   funcPtr = (DllFunc)ptr;
1049   funcPtr = (DllFunc)funcPtr(DllFuncList); //initialize DLL, find Start()
1050
1051   //Register new command
1052   command = argv[0];
1053   for(;;)
1054   {
1055      ptr = strstr(command, "/");
1056      if(ptr == NULL)
1057         break;
1058      command = ptr + 1;
1059   }
1060   for(i = 0; TelnetFuncList[i].name; ++i)
1061   {
1062      if(TelnetFuncList[i].name[0] == 0 ||
1063         strcmp(TelnetFuncList[i].name, command) == 0)
1064      {
1065         TelnetFuncList[i].name = (char*)malloc(40);
1066         strcpy(TelnetFuncList[i].name, command);
1067         TelnetFuncList[i].func = (ConsoleFunc)funcPtr;
1068         break;
1069      }
1070   }
1071
1072   socket->userFunc = socket->funcPtr;
1073   funcPtr(socket, argv);
1074}
1075
1076
1077typedef struct NameValue_t {
1078   struct NameValue_t *next;
1079   void *value;
1080   char name[1];
1081} NameValue_t;
1082
1083//Find the value associated with the name
1084void *IPNameValue(const char *name, void *value)
1085{
1086   static NameValue_t *head;
1087   NameValue_t *node;
1088   for(node = head; node; node = node->next)
1089   {
1090      if(strcmp(node->name, name) == 0)
1091         break;
1092   }
1093   if(node == NULL)
1094   {
1095      node = (NameValue_t*)malloc(sizeof(NameValue_t) + (int)strlen(name));
1096      if(node == NULL)
1097         return NULL;
1098      strcpy(node->name, name);
1099      node->value = value;
1100      node->next = head;
1101      head = node;
1102   }
1103   if(value)
1104      node->value = value;
1105   return node->value;
1106}
1107#endif
1108
1109
1110#ifdef EDIT_FILE
1111extern void EditFile(IPSocket *socket, char *argv[]);
1112#endif
1113
1114static TelnetFunc_t MyFuncs[] = {
1115   {"cat", ConsoleCat},
1116   {"cp", ConsoleCp},
1117   {"dump", ConsoleDump},
1118   {"exit", ConsoleExit},
1119#ifdef INCLUDE_FLASH
1120   {"flashErase", ConsoleFlashErase},
1121#endif
1122   {"ftp", ConsoleFtp},
1123   {"grep", ConsoleGrep},
1124   {"help", ConsoleHelp},
1125   {"ls", ConsoleLs},
1126   {"math", ConsoleMath},
1127   {"mkdir", ConsoleMkdir},
1128   {"mkfile", ConsoleMkfile},
1129   {"ping", ConsolePing},
1130   {"rm", ConsoleRm},
1131   {"tftp", ConsoleTftp},
1132   {"uptime", ConsoleUptime},
1133#ifdef DLL_SETUP
1134   {"run", ConsoleRun},
1135#endif
1136#ifdef EDIT_FILE
1137   {"edit", EditFile},
1138#endif
1139   {"", NULL},
1140   {"", NULL},
1141   {"", NULL},
1142   {"", NULL},
1143   {"", NULL},
1144   {"", NULL},
1145   {"", NULL},
1146   {"", NULL},
1147   {"", NULL},
1148   {"", NULL},
1149   {"", NULL},
1150   {NULL, NULL}
1151};
1152
1153
1154void ConsoleInit(void)
1155{
1156   FtpdInit(1);
1157   TftpdInit();
1158   TelnetInit(MyFuncs);
1159}
plasma/kernel/os_stubs.c
1/*--------------------------------------------------------------------
2 * TITLE: OS stubs
3 * AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4 * DATE CREATED: 2/18/08
5 * FILENAME: os_stubs.c
6 * PROJECT: Plasma CPU core
7 * COPYRIGHT: Software placed into the public domain by the author.
8 * Software 'as is' without warranty. Author liable for nothing.
9 * DESCRIPTION:
10 *--------------------------------------------------------------------*/
11#include <stdlib.h>
12#include "plasma.h"
13#include "rtos.h"
14
15unsigned char *flash;
16int beenInit;
17
18
19void FlashRead(uint16 *dst, uint32 byteOffset, int bytes)
20{
21   if(beenInit == 0)
22   {
23      beenInit = 1;
24      flash = (unsigned char*)malloc(1024*1024*16);
25      memset(flash, 0xff, sizeof(flash));
26   }
27   memcpy(dst, flash+byteOffset, bytes);
28}
29
30
31void FlashWrite(uint16 *src, uint32 byteOffset, int bytes)
32{
33   memcpy(flash+byteOffset, src, bytes);
34}
35
36
37void FlashErase(uint32 byteOffset)
38{
39   memset(flash+byteOffset, 0xff, 1024*128);
40}
41
42
43//Stub out RTOS functions
44void UartPrintfCritical(const char *format, ...) {(void)format;}
45uint32 OS_AsmInterruptEnable(uint32 state) {(void)state; return 0;}
46void OS_Assert(void) {}
47OS_Thread_t *OS_ThreadSelf(void) {return NULL;}
48void OS_ThreadSleep(int ticks) {(void)ticks;}
49uint32 OS_ThreadTime(void) {return 0;}
50OS_Mutex_t *OS_MutexCreate(const char *name) {(void)name; return NULL; }
51void OS_MutexDelete(OS_Mutex_t *semaphore) {(void)semaphore;}
52void OS_MutexPend(OS_Mutex_t *semaphore) {(void)semaphore;}
53void OS_MutexPost(OS_Mutex_t *semaphore) {(void)semaphore;}
54
55OS_MQueue_t *OS_MQueueCreate(const char *name,
56                             int messageCount,
57                             int messageBytes)
58{(void)name;(void)messageCount;(void)messageBytes; return NULL;}
59
60void OS_MQueueDelete(OS_MQueue_t *mQueue) {(void)mQueue;}
61
62int OS_MQueueSend(OS_MQueue_t *mQueue, void *message)
63{(void)mQueue;(void)message; return 0;}
64
65int OS_MQueueGet(OS_MQueue_t *mQueue, void *message, int ticks)
66{(void)mQueue;(void)message;(void)ticks; return 0;}
67
68void OS_Job(void (*funcPtr)(), void *arg0, void *arg1, void *arg2)
69{funcPtr(arg0, arg1, arg2);}
70
71
plasma/kernel/rtos.c
1/*--------------------------------------------------------------------
2 * TITLE: Plasma Real Time Operating System
3 * AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4 * DATE CREATED: 12/17/05
5 * FILENAME: rtos.c
6 * PROJECT: Plasma CPU core
7 * COPYRIGHT: Software placed into the public domain by the author.
8 * Software 'as is' without warranty. Author liable for nothing.
9 * DESCRIPTION:
10 * Plasma Real Time Operating System
11 * Fully pre-emptive RTOS with support for:
12 * Heaps, Threads, Semaphores, Mutexes, Message Queues, and Timers.
13 * This file tries to be hardware independent except for calls to:
14 * MemoryRead() and MemoryWrite() for interrupts.
15 * Partial support for multiple CPUs using symmetric multiprocessing.
16 *--------------------------------------------------------------------*/
17#include "plasma.h"
18#include "rtos.h"
19
20#define HEAP_MAGIC 0x1234abcd
21#define THREAD_MAGIC 0x4321abcd
22#define SEM_RESERVED_COUNT 2
23#define INFO_COUNT 4
24#define HEAP_COUNT 8
25
26
27/*************** Structures ***************/
28#ifdef WIN32
29   #define setjmp _setjmp
30   //x86 registers
31   typedef struct jmp_buf2 {
32      uint32 Ebp, Ebx, Edi, Esi, sp, pc, extra[10];
33   } jmp_buf2;
34#elif defined(ARM_CPU)
35   //ARM registers
36   typedef struct jmp_buf2 {
37      uint32 r[13], sp, lr, pc, cpsr, extra[5];
38   } jmp_buf2;
39#else
40   //Plasma registers
41   typedef struct jmp_buf2 {
42      uint32 s[9], gp, sp, pc;
43   } jmp_buf2;
44#endif
45
46typedef struct HeapNode_s {
47   struct HeapNode_s *next;
48   int size;
49} HeapNode_t;
50
51struct OS_Heap_s {
52   uint32 magic;
53   const char *name;
54   OS_Semaphore_t *semaphore;
55   HeapNode_t *available;
56   HeapNode_t base;
57   struct OS_Heap_s *alternate;
58};
59//typedef struct OS_Heap_s OS_Heap_t;
60
61typedef enum {
62   THREAD_PEND = 0, //Thread in semaphore's linked list
63   THREAD_READY = 1, //Thread in ThreadHead linked list
64   THREAD_RUNNING = 2 //Thread == ThreadCurrent[cpu]
65} OS_ThreadState_e;
66
67struct OS_Thread_s {
68   const char *name; //Name of thread
69   OS_ThreadState_e state; //Pending, ready, or running
70   int cpuIndex; //Which CPU is running the thread
71   int cpuLock; //Lock the thread to a specific CPU
72   jmp_buf env; //Registers saved during context swap
73   OS_FuncPtr_t funcPtr; //First function called
74   void *arg; //Argument to first function called
75   uint32 priority; //Priority of thread (0=low, 255=high)
76   uint32 ticksTimeout; //Tick value when semaphore pend times out
77   void *info[INFO_COUNT]; //User storage
78   OS_Semaphore_t *semaphorePending; //Semaphore thread is blocked on
79   int returnCode; //Return value from semaphore pend
80   uint32 processId; //Process ID if using MMU
81   OS_Heap_t *heap; //Heap used if no heap specified
82   struct OS_Thread_s *next; //Linked list of threads by priority
83   struct OS_Thread_s *prev;
84   struct OS_Thread_s *nextTimeout; //Linked list of threads by timeout
85   struct OS_Thread_s *prevTimeout;
86   uint32 magic[1]; //Bottom of stack to detect stack overflow
87};
88//typedef struct OS_Thread_s OS_Thread_t;
89
90struct OS_Semaphore_s {
91   const char *name;
92   struct OS_Thread_s *threadHead; //threads pending on semaphore
93   int count;
94};
95//typedef struct OS_Semaphore_s OS_Semaphore_t;
96
97struct OS_Mutex_s {
98   OS_Semaphore_t *semaphore;
99   OS_Thread_t *thread;
100   int count;
101};
102//typedef struct OS_Mutex_s OS_Mutex_t;
103
104struct OS_MQueue_s {
105   const char *name;
106   OS_Semaphore_t *semaphore;
107   int count, size, used, read, write;
108};
109//typedef struct OS_MQueue_s OS_MQueue_t;
110
111struct OS_Timer_s {
112   const char *name;
113   struct OS_Timer_s *next, *prev;
114   uint32 ticksTimeout;
115   uint32 ticksRestart;
116   int active;
117   OS_TimerFuncPtr_t callback;
118   OS_MQueue_t *mqueue;
119   uint32 info;
120};
121//typedef struct OS_Timer_s OS_Timer_t;
122
123
124/*************** Globals ******************/
125static OS_Heap_t *HeapArray[HEAP_COUNT];
126static int InterruptInside[OS_CPU_COUNT];
127static int ThreadNeedReschedule[OS_CPU_COUNT];
128static OS_Thread_t *ThreadCurrent[OS_CPU_COUNT]; //Currently running thread(s)
129static OS_Thread_t *ThreadHead; //Linked list of threads sorted by priority
130static OS_Thread_t *TimeoutHead; //Linked list of threads sorted by timeout
131static int ThreadSwapEnabled;
132static uint32 ThreadTime;
133static void *NeedToFree;
134static OS_Semaphore_t SemaphoreReserved[SEM_RESERVED_COUNT];
135static OS_Semaphore_t *SemaphoreSleep;
136static OS_Semaphore_t *SemaphoreRelease;
137static OS_Semaphore_t *SemaphoreLock;
138static OS_Semaphore_t *SemaphoreTimer;
139static OS_Timer_t *TimerHead; //Linked list of timers sorted by timeout
140static OS_FuncPtr_t Isr[32];
141
142
143/***************** Heap *******************/
144/******************************************/
145OS_Heap_t *OS_HeapCreate(const char *name, void *memory, uint32 size)
146{
147   OS_Heap_t *heap;
148
149   assert(((uint32)memory & 3) == 0);
150   heap = (OS_Heap_t*)memory;
151   heap->magic = HEAP_MAGIC;
152   heap->name = name;
153   heap->semaphore = OS_SemaphoreCreate(name, 1);
154   heap->available = (HeapNode_t*)(heap + 1);
155   heap->available->next = &heap->base;
156   heap->available->size = (size - sizeof(OS_Heap_t)) / sizeof(HeapNode_t);
157   heap->base.next = heap->available;
158   heap->base.size = 0;
159   return heap;
160}
161
162
163/******************************************/
164void OS_HeapDestroy(OS_Heap_t *heap)
165{
166   OS_SemaphoreDelete(heap->semaphore);
167}
168
169
170/******************************************/
171//Modified from K&R
172void *OS_HeapMalloc(OS_Heap_t *heap, int bytes)
173{
174   HeapNode_t *node, *prevp;
175   int nunits;
176
177   if(heap == NULL && OS_ThreadSelf())
178      heap = OS_ThreadSelf()->heap;
179   if((uint32)heap < HEAP_COUNT)
180      heap = HeapArray[(int)heap];
181   nunits = (bytes + sizeof(HeapNode_t) - 1) / sizeof(HeapNode_t) + 1;
182   OS_SemaphorePend(heap->semaphore, OS_WAIT_FOREVER);
183   prevp = heap->available;
184   for(node = prevp->next; ; prevp = node, node = node->next)
185   {
186      if(node->size >= nunits) //Big enough?
187      {
188         if(node->size == nunits) //Exactly
189            prevp->next = node->next;
190         else
191         { //Allocate tail end
192            node->size -= nunits;
193            node += node->size;
194            node->size = nunits;
195         }
196         heap->available = prevp;
197         node->next = (HeapNode_t*)heap;
198         OS_SemaphorePost(heap->semaphore);
199         return (void*)(node + 1);
200      }
201      if(node == heap->available) //Wrapped around free list
202      {
203         OS_SemaphorePost(heap->semaphore);
204         if(heap->alternate)
205            return OS_HeapMalloc(heap->alternate, bytes);
206         return NULL;
207      }
208   }
209}
210
211
212/******************************************/
213//Modified from K&R
214void OS_HeapFree(void *block)
215{
216   OS_Heap_t *heap;
217   HeapNode_t *bp, *node;
218
219   assert(block);
220   bp = (HeapNode_t*)block - 1; //point to block header
221   heap = (OS_Heap_t*)bp->next;
222   assert(heap->magic == HEAP_MAGIC);
223   if(heap->magic != HEAP_MAGIC)
224      return;
225   OS_SemaphorePend(heap->semaphore, OS_WAIT_FOREVER);
226   for(node = heap->available; !(node < bp && bp < node->next); node = node->next)
227   {
228      if(node >= node->next && (bp > node || bp < node->next))
229         break; //freed block at start or end of area
230   }
231
232   if(bp + bp->size == node->next) //join to upper
233   {
234      bp->size += node->next->size;
235      bp->next = node->next->next;
236   }
237   else
238   {
239      bp->next = node->next;
240   }
241
242   if(node + node->size == bp) //join to lower
243   {
244      node->size += bp->size;
245      node->next = bp->next;
246   }
247   else
248      node->next = bp;
249   heap->available = node;
250   OS_SemaphorePost(heap->semaphore);
251}
252
253
254/******************************************/
255void OS_HeapAlternate(OS_Heap_t *heap, OS_Heap_t *alternate)
256{
257   heap->alternate = alternate;
258}
259
260
261/******************************************/
262void OS_HeapRegister(void *index, OS_Heap_t *heap)
263{
264   if((uint32)index < HEAP_COUNT)
265      HeapArray[(int)index] = heap;
266}
267
268
269
270/***************** Thread *****************/
271/******************************************/
272//Linked list of threads sorted by priority
273//The listed list is either ThreadHead (ready to run threads not including
274//the currently running thread) or a list of threads waiting on a semaphore.
275//Must be called with interrupts disabled
276static void OS_ThreadPriorityInsert(OS_Thread_t **head, OS_Thread_t *thread)
277{
278   OS_Thread_t *node, *prev;
279
280   prev = NULL;
281   for(node = *head; node; node = node->next)
282   {
283      if(node->priority < thread->priority)
284         break;
285      prev = node;
286   }
287
288   if(prev == NULL)
289   {
290      thread->next = *head;
291      thread->prev = NULL;
292      if(*head)
293         (*head)->prev = thread;
294      *head = thread;
295   }
296   else
297   {
298      if(prev->next)
299         prev->next->prev = thread;
300      thread->next = prev->next;
301      thread->prev = prev;
302      prev->next = thread;
303   }
304   assert(ThreadHead);
305   thread->state = THREAD_READY;
306}
307
308
309/******************************************/
310//Must be called with interrupts disabled
311static void OS_ThreadPriorityRemove(OS_Thread_t **head, OS_Thread_t *thread)
312{
313   assert(thread->magic[0] == THREAD_MAGIC); //check stack overflow
314   if(thread->prev == NULL)
315      *head = thread->next;
316   else
317      thread->prev->next = thread->next;
318   if(thread->next)
319      thread->next->prev = thread->prev;
320   thread->next = NULL;
321   thread->prev = NULL;
322}
323
324
325/******************************************/
326//Linked list of threads sorted by timeout value
327//Must be called with interrupts disabled
328static void OS_ThreadTimeoutInsert(OS_Thread_t *thread)
329{
330   OS_Thread_t *node, *prev;
331   int diff;
332
333   prev = NULL;
334   for(node = TimeoutHead; node; node = node->nextTimeout)
335   {
336      diff = thread->ticksTimeout - node->ticksTimeout;
337      if(diff <= 0)
338         break;
339      prev = node;
340   }
341
342   if(prev == NULL)
343   {
344      thread->nextTimeout = TimeoutHead;
345      thread->prevTimeout = NULL;
346      if(TimeoutHead)
347         TimeoutHead->prevTimeout = thread;
348      TimeoutHead = thread;
349   }
350   else
351   {
352      if(prev->nextTimeout)
353         prev->nextTimeout->prevTimeout = thread;
354      thread->nextTimeout = prev->nextTimeout;
355      thread->prevTimeout = prev;
356      prev->nextTimeout = thread;
357   }
358}
359
360
361/******************************************/
362//Must be called with interrupts disabled
363static void OS_ThreadTimeoutRemove(OS_Thread_t *thread)
364{
365   if(thread->prevTimeout == NULL && TimeoutHead != thread)
366      return; //not in list
367   if(thread->prevTimeout == NULL)
368      TimeoutHead = thread->nextTimeout;
369   else
370      thread->prevTimeout->nextTimeout = thread->nextTimeout;
371   if(thread->nextTimeout)
372      thread->nextTimeout->prevTimeout = thread->prevTimeout;
373   thread->nextTimeout = NULL;
374   thread->prevTimeout = NULL;
375}
376
377
378/******************************************/
379//Loads highest priority thread from the ThreadHead linked list
380//The currently running thread isn't in the ThreadHead list
381//Must be called with interrupts disabled
382static void OS_ThreadReschedule(int roundRobin)
383{
384   OS_Thread_t *threadNext, *threadCurrent;
385   int rc, cpuIndex = OS_CpuIndex();
386
387   if(ThreadSwapEnabled == 0 || InterruptInside[cpuIndex])
388   {
389      ThreadNeedReschedule[cpuIndex] |= 2 + roundRobin; //Reschedule later
390      return;
391   }
392
393   //Determine which thread should run
394   threadNext = ThreadHead;
395   while(threadNext && threadNext->cpuLock != -1 &&
396         threadNext->cpuLock != cpuIndex)
397      threadNext = threadNext->next;
398   if(threadNext == NULL)
399      return;
400   threadCurrent = ThreadCurrent[cpuIndex];
401
402   if(threadCurrent == NULL ||
403      threadCurrent->state == THREAD_PEND ||
404      threadCurrent->priority < threadNext->priority ||
405      (roundRobin && threadCurrent->priority == threadNext->priority))
406   {
407      //Swap threads
408      ThreadCurrent[cpuIndex] = threadNext;
409      if(threadCurrent)
410      {
411         assert(threadCurrent->magic[0] == THREAD_MAGIC); //check stack overflow
412         if(threadCurrent->state == THREAD_RUNNING)
413            OS_ThreadPriorityInsert(&ThreadHead, threadCurrent);
414         rc = setjmp(threadCurrent->env); //ANSI C call to save registers
415         if(rc)
416            return; //Returned from longjmp()
417      }
418
419      //Remove the new running thread from the ThreadHead linked list
420      threadNext = ThreadCurrent[OS_CpuIndex()]; //removed warning
421      assert(threadNext->state == THREAD_READY);
422      OS_ThreadPriorityRemove(&ThreadHead, threadNext);
423      threadNext->state = THREAD_RUNNING;
424      threadNext->cpuIndex = OS_CpuIndex();
425      longjmp(threadNext->env, 1); //ANSI C call to restore registers
426   }
427}
428
429
430/******************************************/
431void OS_ThreadCpuLock(OS_Thread_t *thread, int cpuIndex)
432{
433   thread->cpuLock = cpuIndex;
434   if(thread == OS_ThreadSelf() && cpuIndex != (int)OS_CpuIndex())
435      OS_ThreadSleep(1);
436}
437
438
439/******************************************/
440static void OS_ThreadInit(void *arg)
441{
442   uint32 cpuIndex = OS_CpuIndex();
443   (void)arg;
444
445   OS_CriticalEnd(1);
446   ThreadCurrent[cpuIndex]->funcPtr(ThreadCurrent[cpuIndex]->arg);
447   OS_ThreadExit();
448}
449
450
451/******************************************/
452//Stops warning "argument X might be clobbered by `longjmp'"
453static void OS_ThreadRegsInit(jmp_buf env)
454{
455   setjmp(env); //ANSI C call to save registers
456}
457
458
459/******************************************/
460OS_Thread_t *OS_ThreadCreate(const char *name,
461                             OS_FuncPtr_t funcPtr,
462                             void *arg,
463                             uint32 priority,
464                             uint32 stackSize)
465{
466   OS_Thread_t *thread;
467   uint8 *stack;
468   jmp_buf2 *env;
469   uint32 state;
470
471   OS_SemaphorePend(SemaphoreRelease, OS_WAIT_FOREVER);
472   if(NeedToFree)
473      OS_HeapFree(NeedToFree);
474   NeedToFree = NULL;
475   OS_SemaphorePost(SemaphoreRelease);
476
477   if(stackSize == 0)
478      stackSize = STACK_SIZE_DEFAULT;
479   if(stackSize < STACK_SIZE_MINIMUM)
480      stackSize = STACK_SIZE_MINIMUM;
481   thread = (OS_Thread_t*)OS_HeapMalloc(NULL, sizeof(OS_Thread_t) + stackSize);
482   assert(thread);
483   if(thread == NULL)
484      return NULL;
485   memset(thread, 0, sizeof(OS_Thread_t));
486   stack = (uint8*)(thread + 1);
487   memset(stack, 0xcd, stackSize);
488
489   thread->name = name;
490   thread->state = THREAD_READY;
491   thread->cpuLock = -1;
492   thread->funcPtr = funcPtr;
493   thread->arg = arg;
494   thread->priority = priority;
495   thread->semaphorePending = NULL;
496   thread->returnCode = 0;
497   if(OS_ThreadSelf())
498   {
499      thread->processId = OS_ThreadSelf()->processId;
500      thread->heap = OS_ThreadSelf()->heap;
501   }
502   else
503   {
504      thread->processId = 0;
505      thread->heap = NULL;
506   }
507   thread->next = NULL;
508   thread->prev = NULL;
509   thread->nextTimeout = NULL;
510   thread->prevTimeout = NULL;
511   thread->magic[0] = THREAD_MAGIC;
512
513   OS_ThreadRegsInit(thread->env);
514   env = (jmp_buf2*)thread->env;
515   env->sp = (uint32)stack + stackSize - 24; //minimum stack frame size
516   env->pc = (uint32)OS_ThreadInit;
517
518   state = OS_CriticalBegin();
519   OS_ThreadPriorityInsert(&ThreadHead, thread);
520   OS_ThreadReschedule(0);
521   OS_CriticalEnd(state);
522   return thread;
523}
524
525
526/******************************************/
527void OS_ThreadExit(void)
528{
529   uint32 state, cpuIndex = OS_CpuIndex();
530
531   for(;;)
532   {
533      OS_SemaphorePend(SemaphoreRelease, OS_WAIT_FOREVER);
534      if(NeedToFree)
535         OS_HeapFree(NeedToFree);
536      NeedToFree = NULL;
537      OS_SemaphorePost(SemaphoreRelease);
538
539      state = OS_CriticalBegin();
540      if(NeedToFree)
541      {
542         OS_CriticalEnd(state);
543         continue;
544      }
545      ThreadCurrent[cpuIndex]->state = THREAD_PEND;
546      NeedToFree = ThreadCurrent[cpuIndex];
547      OS_ThreadReschedule(0);
548      OS_CriticalEnd(state);
549   }
550}
551
552
553/******************************************/
554OS_Thread_t *OS_ThreadSelf(void)
555{
556   return ThreadCurrent[OS_CpuIndex()];
557}
558
559
560/******************************************/
561void OS_ThreadSleep(int ticks)
562{
563   OS_SemaphorePend(SemaphoreSleep, ticks);
564}
565
566
567/******************************************/
568uint32 OS_ThreadTime(void)
569{
570   return ThreadTime;
571}
572
573
574/******************************************/
575void OS_ThreadInfoSet(OS_Thread_t *thread, uint32 index, void *Info)
576{
577   if(index < INFO_COUNT)
578      thread->info[index] = Info;
579}
580
581
582/******************************************/
583void *OS_ThreadInfoGet(OS_Thread_t *thread, uint32 index)
584{
585   if(index < INFO_COUNT)
586      return thread->info[index];
587   return NULL;
588}
589
590
591/******************************************/
592uint32 OS_ThreadPriorityGet(OS_Thread_t *thread)
593{
594   return thread->priority;
595}
596
597
598/******************************************/
599void OS_ThreadPrioritySet(OS_Thread_t *thread, uint32 priority)
600{
601   uint32 state;
602   state = OS_CriticalBegin();
603   thread->priority = priority;
604   if(thread->state == THREAD_READY)
605   {
606      OS_ThreadPriorityRemove(&ThreadHead, thread);
607      OS_ThreadPriorityInsert(&ThreadHead, thread);
608      OS_ThreadReschedule(0);
609   }
610   OS_CriticalEnd(state);
611}
612
613
614/******************************************/
615void OS_ThreadProcessId(OS_Thread_t *thread, uint32 processId, OS_Heap_t *heap)
616{
617   thread->processId = processId;
618   thread->heap = heap;
619}
620
621
622/******************************************/
623//Must be called with interrupts disabled
624void OS_ThreadTick(void *Arg)
625{
626   OS_Thread_t *thread;
627   OS_Semaphore_t *semaphore;
628   int diff;
629   (void)Arg;
630
631   ++ThreadTime;
632   while(TimeoutHead)
633   {
634      thread = TimeoutHead;
635      diff = ThreadTime - thread->ticksTimeout;
636      if(diff < 0)
637         break;
638      OS_ThreadTimeoutRemove(thread);
639      semaphore = thread->semaphorePending;
640      ++semaphore->count;
641      thread->semaphorePending = NULL;
642      thread->returnCode = -1;
643      OS_ThreadPriorityRemove(&semaphore->threadHead, thread);
644      OS_ThreadPriorityInsert(&ThreadHead, thread);
645   }
646   OS_ThreadReschedule(1);
647}
648
649
650
651/***************** Semaphore **************/
652/******************************************/
653OS_Semaphore_t *OS_SemaphoreCreate(const char *name, uint32 count)
654{
655   OS_Semaphore_t *semaphore;
656   static int semCount = 0;
657
658   if(semCount < SEM_RESERVED_COUNT)
659      semaphore = &SemaphoreReserved[semCount++]; //Heap not ready yet
660   else
661      semaphore = (OS_Semaphore_t*)OS_HeapMalloc(HEAP_SYSTEM, sizeof(OS_Semaphore_t));
662   assert(semaphore);
663   if(semaphore == NULL)
664      return NULL;
665
666   semaphore->name = name;
667   semaphore->threadHead = NULL;
668   semaphore->count = count;
669   return semaphore;
670}
671
672
673/******************************************/
674void OS_SemaphoreDelete(OS_Semaphore_t *semaphore)
675{
676   while(semaphore->threadHead)
677      OS_SemaphorePost(semaphore);
678   OS_HeapFree(semaphore);
679}
680
681
682/******************************************/
683int OS_SemaphorePend(OS_Semaphore_t *semaphore, int ticks)
684{
685   uint32 state, cpuIndex;
686   OS_Thread_t *thread;
687   int returnCode=0;
688
689   assert(semaphore);
690   assert(InterruptInside[OS_CpuIndex()] == 0);
691   state = OS_CriticalBegin();
692   if(--semaphore->count < 0)
693   {
694      if(ticks == 0)
695      {
696         ++semaphore->count;
697         OS_CriticalEnd(state);
698         return -1;
699      }
700      cpuIndex = OS_CpuIndex();
701      thread = ThreadCurrent[cpuIndex];
702      assert(thread);
703      thread->semaphorePending = semaphore;
704      thread->ticksTimeout = ticks + OS_ThreadTime();
705      //FYI: The current thread isn't in the ThreadHead linked list
706      OS_ThreadPriorityInsert(&semaphore->threadHead, thread);
707      thread->state = THREAD_PEND;
708      if(ticks != OS_WAIT_FOREVER)
709         OS_ThreadTimeoutInsert(thread);
710      assert(ThreadHead);
711      OS_ThreadReschedule(0);
712      returnCode = thread->returnCode;
713   }
714   OS_CriticalEnd(state);
715   return returnCode;
716}
717
718
719/******************************************/
720void OS_SemaphorePost(OS_Semaphore_t *semaphore)
721{
722   uint32 state;
723   OS_Thread_t *thread;
724
725   assert(semaphore);
726   state = OS_CriticalBegin();
727   if(++semaphore->count <= 0)
728   {
729      thread = semaphore->threadHead;
730      OS_ThreadTimeoutRemove(thread);
731      OS_ThreadPriorityRemove(&semaphore->threadHead, thread);
732      OS_ThreadPriorityInsert(&ThreadHead, thread);
733      thread->semaphorePending = NULL;
734      thread->returnCode = 0;
735      OS_ThreadReschedule(0);
736   }
737   OS_CriticalEnd(state);
738}
739
740
741
742/***************** Mutex ******************/
743/******************************************/
744OS_Mutex_t *OS_MutexCreate(const char *name)
745{
746   OS_Mutex_t *mutex;
747
748   mutex = (OS_Mutex_t*)OS_HeapMalloc(HEAP_SYSTEM, sizeof(OS_Mutex_t));
749   if(mutex == NULL)
750      return NULL;
751   mutex->semaphore = OS_SemaphoreCreate(name, 1);
752   if(mutex->semaphore == NULL)
753      return NULL;
754   mutex->thread = NULL;
755   mutex->count = 0;
756   return mutex;
757}
758
759
760/******************************************/
761void OS_MutexDelete(OS_Mutex_t *mutex)
762{
763   OS_SemaphoreDelete(mutex->semaphore);
764   OS_HeapFree(mutex);
765}
766
767
768/******************************************/
769void OS_MutexPend(OS_Mutex_t *mutex)
770{
771   OS_Thread_t *thread;
772
773   assert(mutex);
774   thread = OS_ThreadSelf();
775   if(thread == mutex->thread)
776   {
777      ++mutex->count;
778      return;
779   }
780   OS_SemaphorePend(mutex->semaphore, OS_WAIT_FOREVER);
781   mutex->thread = thread;
782   mutex->count = 1;
783}
784
785
786/******************************************/
787void OS_MutexPost(OS_Mutex_t *mutex)
788{
789   assert(mutex);
790   assert(mutex->thread == OS_ThreadSelf());
791   assert(mutex->count > 0);
792   if(--mutex->count <= 0)
793   {
794      mutex->thread = NULL;
795      OS_SemaphorePost(mutex->semaphore);
796   }
797}
798
799
800
801/***************** MQueue *****************/
802/******************************************/
803OS_MQueue_t *OS_MQueueCreate(const char *name,
804                             int messageCount,
805                             int messageBytes)
806{
807   OS_MQueue_t *queue;
808   int size;
809
810   size = messageBytes / sizeof(uint32);
811   queue = (OS_MQueue_t*)OS_HeapMalloc(HEAP_SYSTEM, sizeof(OS_MQueue_t) +
812      messageCount * size * 4);
813   if(queue == NULL)
814      return queue;
815   queue->name = name;
816   queue->semaphore = OS_SemaphoreCreate(name, 0);
817   if(queue->semaphore == NULL)
818      return NULL;
819   queue->count = messageCount;
820   queue->size = size;
821   queue->used = 0;
822   queue->read = 0;
823   queue->write = 0;
824   return queue;
825}
826
827
828/******************************************/
829void OS_MQueueDelete(OS_MQueue_t *mQueue)
830{
831   OS_SemaphoreDelete(mQueue->semaphore);
832   OS_HeapFree(mQueue);
833}
834
835
836/******************************************/
837int OS_MQueueSend(OS_MQueue_t *mQueue, void *message)
838{
839   uint32 state, *dst, *src;
840   int i;
841
842   assert(mQueue);
843   src = (uint32*)message;
844   state = OS_CriticalBegin();
845   if(++mQueue->used > mQueue->count)
846   {
847      --mQueue->used;
848      OS_CriticalEnd(state);
849      return -1;
850   }
851   dst = (uint32*)(mQueue + 1) + mQueue->write * mQueue->size;
852   for(i = 0; i < mQueue->size; ++i)
853      dst[i] = src[i];
854   if(++mQueue->write >= mQueue->count)
855      mQueue->write = 0;
856   OS_CriticalEnd(state);
857   OS_SemaphorePost(mQueue->semaphore);
858   return 0;
859}
860
861
862/******************************************/
863int OS_MQueueGet(OS_MQueue_t *mQueue, void *message, int ticks)
864{
865   uint32 state, *dst, *src;
866   int i, rc;
867
868   assert(mQueue);
869   dst = (uint32*)message;
870   rc = OS_SemaphorePend(mQueue->semaphore, ticks);
871   if(rc)
872      return rc;
873   state = OS_CriticalBegin();
874   --mQueue->used;
875   src = (uint32*)(mQueue + 1) + mQueue->read * mQueue->size;
876   for(i = 0; i < mQueue->size; ++i)
877      dst[i] = src[i];
878   if(++mQueue->read >= mQueue->count)
879      mQueue->read = 0;
880   OS_CriticalEnd(state);
881   return 0;
882}
883
884
885
886/***************** Jobs *******************/
887/******************************************/
888typedef void (*JobFunc_t)();
889static OS_MQueue_t *jobQueue;
890static OS_Thread_t *jobThread;
891
892static void JobThread(void *arg)
893{
894   uint32 message[4];
895   JobFunc_t funcPtr;
896   (void)arg;
897   for(;;)
898   {
899      OS_MQueueGet(jobQueue, message, OS_WAIT_FOREVER);
900      funcPtr = (JobFunc_t)message[0];
901      funcPtr(message[1], message[2], message[3]);
902   }
903}
904
905
906/******************************************/
907void OS_Job(void (*funcPtr)(), void *arg0, void *arg1, void *arg2)
908{
909   uint32 message[4];
910   int rc;
911
912   OS_SemaphorePend(SemaphoreLock, OS_WAIT_FOREVER);
913   if(jobThread == NULL)
914   {
915      jobQueue = OS_MQueueCreate("job", 100, 16);
916      jobThread = OS_ThreadCreate("job", JobThread, NULL, 150, 4000);
917   }
918   OS_SemaphorePost(SemaphoreLock);
919
920   message[0] = (uint32)funcPtr;
921   message[1] = (uint32)arg0;
922   message[2] = (uint32)arg1;
923   message[3] = (uint32)arg2;
924   rc = OS_MQueueSend(jobQueue, message);
925}
926
927
928/***************** Timer ******************/
929/******************************************/
930static void OS_TimerThread(void *arg)
931{
932   uint32 timeNow;
933   int diff, ticks;
934   uint32 message[8];
935   OS_Timer_t *timer;
936   (void)arg;
937
938   timeNow = OS_ThreadTime();
939   for(;;)
940   {
941      //Determine how long to sleep
942      OS_SemaphorePend(SemaphoreLock, OS_WAIT_FOREVER);
943      if(TimerHead)
944         ticks = TimerHead->ticksTimeout - timeNow;
945      else
946         ticks = OS_WAIT_FOREVER;
947      OS_SemaphorePost(SemaphoreLock);
948      OS_SemaphorePend(SemaphoreTimer, ticks);
949
950      //Send messages for all timed out timers
951      timeNow = OS_ThreadTime();
952      for(;;)
953      {
954         timer = NULL;
955         OS_SemaphorePend(SemaphoreLock, OS_WAIT_FOREVER);
956         if(TimerHead)
957         {
958            diff = timeNow - TimerHead->ticksTimeout;
959            if(diff >= 0)
960               timer = TimerHead;
961         }
962         OS_SemaphorePost(SemaphoreLock);
963         if(timer == NULL)
964            break;
965         if(timer->ticksRestart)
966            OS_TimerStart(timer, timer->ticksRestart, timer->ticksRestart);
967         else
968            OS_TimerStop(timer);
969
970         if(timer->callback)
971            timer->callback(timer, timer->info);
972         else
973         {
974            //Send message
975            message[0] = MESSAGE_TYPE_TIMER;
976            message[1] = (uint32)timer;
977            message[2] = timer->info;
978            OS_MQueueSend(timer->mqueue, message);
979         }
980      }
981   }
982}
983
984
985/******************************************/
986OS_Timer_t *OS_TimerCreate(const char *name, OS_MQueue_t *mQueue, uint32 info)
987{
988   OS_Timer_t *timer;
989
990   OS_SemaphorePend(SemaphoreLock, OS_WAIT_FOREVER);
991   if(SemaphoreTimer == NULL)
992   {
993      SemaphoreTimer = OS_SemaphoreCreate("Timer", 0);
994      OS_ThreadCreate("Timer", OS_TimerThread, NULL, 250, 2000);
995   }
996   OS_SemaphorePost(SemaphoreLock);
997
998   timer = (OS_Timer_t*)OS_HeapMalloc(HEAP_SYSTEM, sizeof(OS_Timer_t));
999   if(timer == NULL)
1000      return NULL;
1001   timer->name = name;
1002   timer->callback = NULL;
1003   timer->mqueue = mQueue;
1004   timer->next = NULL;
1005   timer->prev = NULL;
1006   timer->info = info;
1007   timer->active = 0;
1008   return timer;
1009}
1010
1011
1012/******************************************/
1013void OS_TimerDelete(OS_Timer_t *timer)
1014{
1015   OS_TimerStop(timer);
1016   OS_HeapFree(timer);
1017}
1018
1019
1020/******************************************/
1021void OS_TimerCallback(OS_Timer_t *timer, OS_TimerFuncPtr_t callback)
1022{
1023   timer->callback = callback;
1024}
1025
1026
1027/******************************************/
1028//Must not be called from an ISR
1029void OS_TimerStart(OS_Timer_t *timer, uint32 ticks, uint32 ticksRestart)
1030{
1031   OS_Timer_t *node, *prev;
1032   int diff, check=0;
1033
1034   assert(timer);
1035   assert(InterruptInside[OS_CpuIndex()] == 0);
1036   ticks += OS_ThreadTime();
1037   if(timer->active)
1038      OS_TimerStop(timer);
1039   OS_SemaphorePend(SemaphoreLock, OS_WAIT_FOREVER);
1040   if(timer->active)
1041   {
1042      //Prevent race condition
1043      OS_SemaphorePost(SemaphoreLock);
1044      return;
1045   }
1046   timer->ticksTimeout = ticks;
1047   timer->ticksRestart = ticksRestart;
1048   timer->active = 1;
1049   prev = NULL;
1050   for(node = TimerHead; node; node = node->next)
1051   {
1052      diff = ticks - node->ticksTimeout;
1053      if(diff <= 0)
1054         break;
1055      prev = node;
1056   }
1057   timer->next = node;
1058   timer->prev = prev;
1059   if(node)
1060      node->prev = timer;
1061   if(prev == NULL)
1062   {
1063      TimerHead = timer;
1064      check = 1;
1065   }
1066   else
1067      prev->next = timer;
1068   OS_SemaphorePost(SemaphoreLock);
1069   if(check)
1070      OS_SemaphorePost(SemaphoreTimer);
1071}
1072
1073
1074/******************************************/
1075//Must not be called from an ISR
1076void OS_TimerStop(OS_Timer_t *timer)
1077{
1078   assert(timer);
1079   assert(InterruptInside[OS_CpuIndex()] == 0);
1080   OS_SemaphorePend(SemaphoreLock, OS_WAIT_FOREVER);
1081   if(timer->active)
1082   {
1083      timer->active = 0;
1084      if(timer->prev == NULL)
1085         TimerHead = timer->next;
1086      else
1087         timer->prev->next = timer->next;
1088      if(timer->next)
1089         timer->next->prev = timer->prev;
1090   }
1091   OS_SemaphorePost(SemaphoreLock);
1092}
1093
1094
1095/***************** ISR ********************/
1096/******************************************/
1097void OS_InterruptServiceRoutine(uint32 status, uint32 *stack)
1098{
1099   int i;
1100   uint32 state, cpuIndex = OS_CpuIndex();
1101
1102   if(status == 0 && Isr[31])
1103      Isr[31](stack); //SYSCALL or BREAK
1104
1105   InterruptInside[cpuIndex] = 1;
1106   i = 0;
1107   do
1108   {
1109      if(status & 1)
1110      {
1111         if(Isr[i])
1112            Isr[i](stack);
1113         else
1114            OS_InterruptMaskClear(1 << i);
1115      }
1116      status >>= 1;
1117      ++i;
1118   } while(status);
1119   InterruptInside[cpuIndex] = 0;
1120
1121   state = OS_SpinLock();
1122   if(ThreadNeedReschedule[cpuIndex])
1123      OS_ThreadReschedule(ThreadNeedReschedule[cpuIndex] & 1);
1124   OS_SpinUnlock(state);
1125}
1126
1127
1128/******************************************/
1129void OS_InterruptRegister(uint32 mask, OS_FuncPtr_t funcPtr)
1130{
1131   int i;
1132
1133   for(i = 0; i < 32; ++i)
1134   {
1135      if(mask & (1 << i))
1136         Isr[i] = funcPtr;
1137   }
1138}
1139
1140
1141/******************************************/
1142//Plasma hardware dependent
1143uint32 OS_InterruptStatus(void)
1144{
1145   return MemoryRead(IRQ_STATUS);
1146}
1147
1148
1149/******************************************/
1150//Plasma hardware dependent
1151uint32 OS_InterruptMaskSet(uint32 mask)
1152{
1153   uint32 state;
1154   state = OS_CriticalBegin();
1155   mask |= MemoryRead(IRQ_MASK);
1156   MemoryWrite(IRQ_MASK, mask);
1157   OS_CriticalEnd(state);
1158   return mask;
1159}
1160
1161
1162/******************************************/
1163//Plasma hardware dependent
1164uint32 OS_InterruptMaskClear(uint32 mask)
1165{
1166   uint32 state;
1167   state = OS_CriticalBegin();
1168   mask = MemoryRead(IRQ_MASK) & ~mask;
1169   MemoryWrite(IRQ_MASK, mask);
1170   OS_CriticalEnd(state);
1171   return mask;
1172}
1173
1174
1175/**************** Init ********************/
1176/******************************************/
1177static volatile uint32 IdleCount;
1178static void OS_IdleThread(void *arg)
1179{
1180   (void)arg;
1181
1182   //Don't block in the idle thread!
1183   for(;;)
1184   {
1185      ++IdleCount;
1186   }
1187}
1188
1189
1190/******************************************/
1191#ifndef DISABLE_IRQ_SIM
1192static void OS_IdleSimulateIsr(void *arg)
1193{
1194   uint32 count=0, value;
1195   (void)arg;
1196
1197   for(;;)
1198   {
1199      MemoryRead(IRQ_MASK + 4); //calls Sleep(10)
1200#if WIN32
1201      while(OS_InterruptMaskSet(0) & IRQ_UART_WRITE_AVAILABLE)
1202         OS_InterruptServiceRoutine(IRQ_UART_WRITE_AVAILABLE, 0);
1203#endif
1204      value = OS_InterruptMaskSet(0) & 0xf;
1205      if(value)
1206         OS_InterruptServiceRoutine(value, 0);
1207      ++count;
1208   }
1209}
1210#endif //DISABLE_IRQ_SIM
1211
1212
1213/******************************************/
1214//Plasma hardware dependent
1215static void OS_ThreadTickToggle(void *arg)
1216{
1217   uint32 status, mask, state;
1218
1219   //Toggle looking for IRQ_COUNTER18 or IRQ_COUNTER18_NOT
1220   state = OS_SpinLock();
1221   status = MemoryRead(IRQ_STATUS) & (IRQ_COUNTER18 | IRQ_COUNTER18_NOT);
1222   mask = MemoryRead(IRQ_MASK) | IRQ_COUNTER18 | IRQ_COUNTER18_NOT;
1223   mask &= ~status;
1224   MemoryWrite(IRQ_MASK, mask);
1225   OS_ThreadTick(arg);
1226   OS_SpinUnlock(state);
1227}
1228
1229
1230/******************************************/
1231void OS_Init(uint32 *heapStorage, uint32 bytes)
1232{
1233   int i;
1234   OS_AsmInterruptInit(); //Patch interrupt vector
1235   OS_InterruptMaskClear(0xffffffff); //Disable interrupts
1236   HeapArray[0] = OS_HeapCreate("Default", heapStorage, bytes);
1237   HeapArray[1] = HeapArray[0];
1238   SemaphoreSleep = OS_SemaphoreCreate("Sleep", 0);
1239   SemaphoreRelease = OS_SemaphoreCreate("Release", 1);
1240   SemaphoreLock = OS_SemaphoreCreate("Lock", 1);
1241   for(i = 0; i < OS_CPU_COUNT; ++i)
1242      OS_ThreadCreate("Idle", OS_IdleThread, NULL, 0, 256);
1243#ifndef DISABLE_IRQ_SIM
1244   if((OS_InterruptStatus() & (IRQ_COUNTER18 | IRQ_COUNTER18_NOT)) == 0)
1245   {
1246      //Detected that running in simulator so create SimIsr thread
1247      UartPrintfCritical("SimIsr\n");
1248      OS_ThreadCreate("SimIsr", OS_IdleSimulateIsr, NULL, 1, 0);
1249   }
1250#endif //DISABLE_IRQ_SIM
1251   //Plasma hardware dependent
1252   OS_InterruptRegister(IRQ_COUNTER18 | IRQ_COUNTER18_NOT, OS_ThreadTickToggle);
1253   OS_InterruptMaskSet(IRQ_COUNTER18 | IRQ_COUNTER18_NOT);
1254}
1255
1256
1257/******************************************/
1258void OS_Start(void)
1259{
1260   ThreadSwapEnabled = 1;
1261   (void)OS_SpinLock();
1262   OS_ThreadReschedule(1);
1263}
1264
1265
1266/******************************************/
1267//Place breakpoint here
1268void OS_Assert(void)
1269{
1270}
1271
1272
1273#if OS_CPU_COUNT > 1
1274static uint8 SpinLockArray[OS_CPU_COUNT];
1275/******************************************/
1276uint32 OS_CpuIndex(void)
1277{
1278   return 0; //0 to OS_CPU_COUNT-1
1279}
1280
1281
1282/******************************************/
1283//Symmetric Multiprocessing Spin Lock Mutex
1284uint32 OS_SpinLock(void)
1285{
1286   uint32 state, cpuIndex, i, j, ok, delay;
1287
1288   cpuIndex = OS_CpuIndex();
1289   delay = cpuIndex + 8;
1290   state = OS_AsmInterruptEnable(0);
1291   do
1292   {
1293      ok = 1;
1294      if(++SpinLockArray[cpuIndex] == 1)
1295      {
1296         for(i = 0; i < OS_CPU_COUNT; ++i)
1297         {
1298            if(i != cpuIndex && SpinLockArray[i])
1299               ok = 0;
1300         }
1301         if(ok == 0)
1302         {
1303            SpinLockArray[cpuIndex] = 0;
1304            for(j = 0; j < delay; ++j) //wait a bit
1305               ++i;
1306            if(delay < 128)
1307               delay <<= 1;
1308         }
1309      }
1310   } while(ok == 0);
1311   return state;
1312}
1313
1314
1315/******************************************/
1316void OS_SpinUnlock(uint32 state)
1317{
1318   uint32 cpuIndex;
1319   cpuIndex = OS_CpuIndex();
1320   if(--SpinLockArray[cpuIndex] == 0)
1321      OS_AsmInterruptEnable(state);
1322
1323   assert(SpinLockArray[cpuIndex] < 10);
1324}
1325#endif //OS_CPU_COUNT > 1
1326
1327
1328/************** WIN32/Linux Support *************/
1329#ifdef WIN32
1330#ifdef LINUX
1331#define putch putchar
1332#undef _LIBC
1333#undef kbhit
1334#undef getch
1335#define UartPrintf UartPrintf2
1336#define UartScanf UartScanf2
1337#include <stdio.h>
1338#include <stdlib.h>
1339#include <termios.h>
1340#include <unistd.h>
1341void Sleep(unsigned int value)
1342{
1343   usleep(value * 1000);
1344}
1345
1346int kbhit(void)
1347{
1348   struct termios oldt, newt;
1349   struct timeval tv;
1350   fd_set read_fd;
1351
1352   tcgetattr(STDIN_FILENO, &oldt);
1353   newt = oldt;
1354   newt.c_lflag &= ~(ICANON | ECHO);
1355   tcsetattr(STDIN_FILENO, TCSANOW, &newt);
1356   tv.tv_sec=0;
1357   tv.tv_usec=0;
1358   FD_ZERO(&read_fd);
1359   FD_SET(0,&read_fd);
1360   if(select(1, &read_fd, NULL, NULL, &tv) == -1)
1361      return 0;
1362   if(FD_ISSET(0,&read_fd))
1363      return 1;
1364   return 0;
1365}
1366
1367int getch(void)
1368{
1369   struct termios oldt, newt;
1370   int ch;
1371
1372   tcgetattr(STDIN_FILENO, &oldt);
1373   newt = oldt;
1374   newt.c_lflag &= ~(ICANON | ECHO);
1375   tcsetattr(STDIN_FILENO, TCSANOW, &newt);
1376   ch = getchar();
1377   return ch;
1378}
1379#else
1380//Support RTOS inside Windows
1381#undef kbhit
1382#undef getch
1383#undef putch
1384extern int kbhit();
1385extern int getch(void);
1386extern int putch(int);
1387extern void __stdcall Sleep(unsigned long value);
1388#endif
1389
1390static uint32 Memory[8];
1391
1392uint32 MemoryRead(uint32 address)
1393{
1394   Memory[2] |= IRQ_UART_WRITE_AVAILABLE; //IRQ_STATUS
1395   switch(address)
1396   {
1397   case UART_READ:
1398      if(kbhit())
1399         Memory[0] = getch(); //UART_READ
1400      Memory[2] &= ~IRQ_UART_READ_AVAILABLE; //clear bit
1401      return Memory[0];
1402   case IRQ_MASK:
1403      return Memory[1]; //IRQ_MASK
1404   case IRQ_MASK + 4:
1405      Sleep(10);
1406      return 0;
1407   case IRQ_STATUS:
1408      if(kbhit())
1409         Memory[2] |= IRQ_UART_READ_AVAILABLE;
1410      return Memory[2];
1411   }
1412   return 0;
1413}
1414
1415void MemoryWrite(uint32 address, uint32 value)
1416{
1417   switch(address)
1418   {
1419   case UART_WRITE:
1420      putch(value);
1421      break;
1422   case IRQ_MASK:
1423      Memory[1] = value;
1424      break;
1425   case IRQ_STATUS:
1426      Memory[2] = value;
1427      break;
1428   }
1429}
1430
1431uint32 OS_AsmInterruptEnable(uint32 enableInterrupt)
1432{
1433   return enableInterrupt;
1434}
1435
1436void OS_AsmInterruptInit(void)
1437{
1438}
1439#endif //WIN32
1440
1441
1442/**************** Example *****************/
1443#ifndef NO_MAIN
1444#ifdef WIN32
1445static uint8 HeapSpace[1024*512];
1446#endif
1447
1448int main(int programEnd, char *argv[])
1449{
1450   (void)programEnd; //Pointer to end of used memory
1451   (void)argv;
1452
1453   UartPrintfCritical("Starting RTOS\n");
1454#ifdef WIN32
1455   OS_Init((uint32*)HeapSpace, sizeof(HeapSpace));
1456#else
1457   //Remaining space after program in 1MB external RAM
1458   OS_Init((uint32*)programEnd,
1459           RAM_EXTERNAL_BASE + RAM_EXTERNAL_SIZE - programEnd);
1460#endif
1461   UartInit();
1462   OS_ThreadCreate("Main", MainThread, NULL, 100, 4000);
1463   OS_Start();
1464   return 0;
1465}
1466#endif //NO_MAIN
1467
plasma/kernel/rtos.h
1/*--------------------------------------------------------------------
2 * TITLE: Plasma Real Time Operating System
3 * AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4 * DATE CREATED: 12/17/05
5 * FILENAME: rtos.h
6 * PROJECT: Plasma CPU core
7 * COPYRIGHT: Software placed into the public domain by the author.
8 * Software 'as is' without warranty. Author liable for nothing.
9 * DESCRIPTION:
10 * Plasma Real Time Operating System
11 *--------------------------------------------------------------------*/
12#ifndef __RTOS_H__
13#define __RTOS_H__
14
15// Symmetric Multi-Processing
16#define OS_CPU_COUNT 1
17
18// Typedefs
19typedef unsigned int uint32;
20typedef unsigned short uint16;
21typedef unsigned char uint8;
22
23// Memory Access
24#ifdef WIN32
25   uint32 MemoryRead(uint32 Address);
26   void MemoryWrite(uint32 Address, uint32 Value);
27#else
28   #define MemoryRead(A) (*(volatile uint32*)(A))
29   #define MemoryWrite(A,V) *(volatile uint32*)(A)=(V)
30#endif
31
32/***************** LibC ******************/
33#if !defined(_LIBC) && !defined(_CTYPE_DEFINED)
34#define printf UartPrintf
35//#define printf UartPrintfPoll
36#define scanf UartScanf
37#ifndef WIN32
38   #define malloc(S) OS_HeapMalloc(NULL, S)
39   #define free(S) OS_HeapFree(S)
40#endif
41
42#ifndef NULL
43#define NULL (void*)0
44#endif
45
46#define assert(A) if((A)==0){OS_Assert();UartPrintfCritical("\r\nAssert %s:%d\r\n", __FILE__, __LINE__);}
47
48#define isprint(c) (' '<=(c)&&(c)<='~')
49#define isspace(c) ((c)==' '||(c)=='\t'||(c)=='\n'||(c)=='\r')
50#define isdigit(c) ('0'<=(c)&&(c)<='9')
51#define islower(c) ('a'<=(c)&&(c)<='z')
52#define isupper(c) ('A'<=(c)&&(c)<='Z')
53#define isalpha(c) (islower(c)||isupper(c))
54#define isalnum(c) (isalpha(c)||isdigit(c))
55#undef min
56#define min(a,b) ((a)<(b)?(a):(b))
57#define strcpy strcpy2 //don't use intrinsic functions
58#define strcat strcat2
59#define strncat strncat2
60#define strcmp strcmp2
61#define strlen strlen2
62#define memcpy memcpy2
63#define memcmp memcmp2
64#define memset memset2
65#define abs abs2
66#define atoi atoi2
67
68char *strcpy(char *dst, const char *src);
69char *strncpy(char *dst, const char *src, int count);
70char *strcat(char *dst, const char *src);
71char *strncat(char *dst, const char *src, int count);
72int strcmp(const char *string1, const char *string2);
73int strncmp(const char *string1, const char *string2, int count);
74char *strstr(const char *string, const char *find);
75int strlen(const char *string);
76void *memcpy(void *dst, const void *src, unsigned long bytes);
77void *memmove(void *dst, const void *src, unsigned long bytes);
78int memcmp(const void *cs, const void *ct, unsigned long bytes);
79void *memset(void *dst, int c, unsigned long bytes);
80int abs(int n);
81int rand(void);
82void srand(unsigned int seed);
83long strtol(const char *s, char **end, int base);
84int atoi(const char *s);
85char *itoa(int num, char *dst, int base);
86#ifndef NO_ELLIPSIS
87   int sprintf(char *s, const char *format, ...);
88   int sscanf(const char *s, const char *format, ...);
89#endif
90#ifdef INCLUDE_DUMP
91   void dump(const unsigned char *data, int length);
92#endif
93#ifdef INCLUDE_QSORT
94   void qsort(void *base,
95              long n,
96              long size,
97              int (*cmp)(const void *,const void *));
98   void *bsearch(const void *key,
99                 const void *base,
100                 long n,
101                 long size,
102                 int (*cmp)(const void *,const void *));
103#endif
104#ifdef INCLUDE_TIMELIB
105   #define difftime(time2,time1) (time2-time1)
106   typedef unsigned long time_t; //start at 1/1/80
107   struct tm {
108      int tm_sec; //(0,59)
109      int tm_min; //(0,59)
110      int tm_hour; //(0,23)
111      int tm_mday; //(1,31)
112      int tm_mon; //(0,11)
113      int tm_year; //(0,n) from 1900
114      int tm_wday; //(0,6) calculated
115      int tm_yday; //(0,365) calculated
116      int tm_isdst; // calculated
117   };
118   time_t mktime(struct tm *tp);
119   void gmtime_r(const time_t *tp, struct tm *out);
120   void gmtimeDst(time_t dstTimeIn, time_t dstTimeOut);
121   void gmtimeDstSet(time_t *tp, time_t *dstTimeIn, time_t *dstTimeOut);
122#endif
123#define _LIBC
124#endif //_LIBC
125
126/***************** Assembly **************/
127typedef uint32 jmp_buf[20];
128extern uint32 OS_AsmInterruptEnable(uint32 state);
129extern void OS_AsmInterruptInit(void);
130extern int setjmp(jmp_buf env);
131extern void longjmp(jmp_buf env, int val);
132extern uint32 OS_AsmMult(uint32 a, uint32 b, unsigned long *hi);
133extern void *OS_Syscall();
134
135/***************** Heap ******************/
136#define HEAP_USER (void*)0
137#define HEAP_SYSTEM (void*)1
138#define HEAP_SMALL (void*)2
139#define HEAP_UI (void*)3
140typedef struct OS_Heap_s OS_Heap_t;
141OS_Heap_t *OS_HeapCreate(const char *name, void *memory, uint32 size);
142void OS_HeapDestroy(OS_Heap_t *heap);
143void *OS_HeapMalloc(OS_Heap_t *heap, int bytes);
144void OS_HeapFree(void *block);
145void OS_HeapAlternate(OS_Heap_t *heap, OS_Heap_t *alternate);
146void OS_HeapRegister(void *index, OS_Heap_t *heap);
147
148/***************** Critical Sections *****************/
149#if OS_CPU_COUNT <= 1
150   // Single CPU
151   #define OS_CpuIndex() 0
152   #define OS_CriticalBegin() OS_AsmInterruptEnable(0)
153   #define OS_CriticalEnd(S) OS_AsmInterruptEnable(S)
154   #define OS_SpinLock() 0
155   #define OS_SpinUnlock(S)
156#else
157   // Symmetric multiprocessing
158   uint32 OS_CpuIndex(void);
159   #define OS_CriticalBegin() OS_SpinLock()
160   #define OS_CriticalEnd(S) OS_SpinUnlock(S)
161   uint32 OS_SpinLock(void);
162   void OS_SpinUnlock(uint32 state);
163#endif
164
165/***************** Thread *****************/
166#ifdef WIN32
167   #define STACK_SIZE_MINIMUM (1024*4)
168#else
169   #define STACK_SIZE_MINIMUM (1024*1)
170#endif
171#define STACK_SIZE_DEFAULT 1024*2
172#undef THREAD_PRIORITY_IDLE
173#define THREAD_PRIORITY_IDLE 0
174#define THREAD_PRIORITY_MAX 255
175
176typedef void (*OS_FuncPtr_t)(void *arg);
177typedef struct OS_Thread_s OS_Thread_t;
178OS_Thread_t *OS_ThreadCreate(const char *name,
179                             OS_FuncPtr_t funcPtr,
180                             void *arg,
181                             uint32 priority,
182                             uint32 stackSize);
183void OS_ThreadExit(void);
184OS_Thread_t *OS_ThreadSelf(void);
185void OS_ThreadSleep(int ticks);
186uint32 OS_ThreadTime(void);
187void OS_ThreadInfoSet(OS_Thread_t *thread, uint32 index, void *info);
188void *OS_ThreadInfoGet(OS_Thread_t *thread, uint32 index);
189uint32 OS_ThreadPriorityGet(OS_Thread_t *thread);
190void OS_ThreadPrioritySet(OS_Thread_t *thread, uint32 priority);
191void OS_ThreadProcessId(OS_Thread_t *thread, uint32 processId, OS_Heap_t *heap);
192void OS_ThreadTick(void *arg);
193void OS_ThreadCpuLock(OS_Thread_t *thread, int cpuIndex);
194
195/***************** Semaphore **************/
196#define OS_SUCCESS 0
197#define OS_ERROR -1
198#define OS_WAIT_FOREVER -1
199#define OS_NO_WAIT 0
200typedef struct OS_Semaphore_s OS_Semaphore_t;
201OS_Semaphore_t *OS_SemaphoreCreate(const char *name, uint32 count);
202void OS_SemaphoreDelete(OS_Semaphore_t *semaphore);
203int OS_SemaphorePend(OS_Semaphore_t *semaphore, int ticks); //tick ~= 10ms
204void OS_SemaphorePost(OS_Semaphore_t *semaphore);
205
206/***************** Mutex ******************/
207typedef struct OS_Mutex_s OS_Mutex_t;
208OS_Mutex_t *OS_MutexCreate(const char *name);
209void OS_MutexDelete(OS_Mutex_t *semaphore);
210void OS_MutexPend(OS_Mutex_t *semaphore);
211void OS_MutexPost(OS_Mutex_t *semaphore);
212
213/***************** MQueue *****************/
214enum {
215   MESSAGE_TYPE_USER = 0,
216   MESSAGE_TYPE_TIMER = 5
217};
218typedef struct OS_MQueue_s OS_MQueue_t;
219OS_MQueue_t *OS_MQueueCreate(const char *name,
220                             int messageCount,
221                             int messageBytes);
222void OS_MQueueDelete(OS_MQueue_t *mQueue);
223int OS_MQueueSend(OS_MQueue_t *mQueue, void *message);
224int OS_MQueueGet(OS_MQueue_t *mQueue, void *message, int ticks);
225
226/***************** Job ********************/
227void OS_Job(void (*funcPtr)(), void *arg0, void *arg1, void *arg2);
228
229/***************** Timer ******************/
230typedef struct OS_Timer_s OS_Timer_t;
231typedef void (*OS_TimerFuncPtr_t)(OS_Timer_t *timer, uint32 info);
232OS_Timer_t *OS_TimerCreate(const char *name, OS_MQueue_t *mQueue, uint32 info);
233void OS_TimerDelete(OS_Timer_t *timer);
234void OS_TimerCallback(OS_Timer_t *timer, OS_TimerFuncPtr_t callback);
235void OS_TimerStart(OS_Timer_t *timer, uint32 ticks, uint32 ticksRestart);
236void OS_TimerStop(OS_Timer_t *timer);
237
238/***************** ISR ********************/
239#define STACK_EPC 88/4
240void OS_InterruptServiceRoutine(uint32 status, uint32 *stack);
241void OS_InterruptRegister(uint32 mask, OS_FuncPtr_t funcPtr);
242uint32 OS_InterruptStatus(void);
243uint32 OS_InterruptMaskSet(uint32 mask);
244uint32 OS_InterruptMaskClear(uint32 mask);
245
246/***************** Init ******************/
247void OS_Init(uint32 *heapStorage, uint32 bytes);
248void OS_Start(void);
249void OS_Assert(void);
250void OS_DebuggerInit(void);
251void MainThread(void *Arg);
252
253/***************** MMU ******************/
254typedef struct {
255   const char *name;
256   OS_FuncPtr_t funcPtr;
257   void *arg;
258   uint32 priority;
259   uint32 stackSize;
260   uint32 heapSize;
261   uint32 processId;
262   OS_Semaphore_t *semaphoreDone;
263   uint8 *memory; //private
264   OS_Heap_t *heap; //private
265   OS_Thread_t *thread; //private
266} OS_Process_t;
267void OS_MMUInit(void);
268void OS_MMUMemoryRegister(uint32 processId,
269                          uint32 virtualAddress,
270                          uint32 physicalAddress,
271                          uint32 size,
272                          uint32 writable);
273OS_Process_t *OS_MMUProcessCreate(OS_Process_t *process);
274void OS_MMUProcessDelete(OS_Process_t *process);
275void OS_MMUUartPrintf();
276void OS_MMUUartScanf();
277void OS_MMUUartPrintfCritical();
278
279/***************** UART ******************/
280typedef uint8* (*PacketGetFunc_t)(void);
281void UartInit(void);
282void UartWrite(int ch);
283uint8 UartRead(void);
284void UartWriteData(uint8 *data, int length);
285void UartReadData(uint8 *data, int length);
286#ifndef NO_ELLIPSIS2
287void UartPrintf(const char *format, ...);
288void UartPrintfPoll(const char *format, ...);
289void UartPrintfCritical(const char *format, ...);
290void UartPrintfNull(const char *format, ...);
291void UartScanf(const char *format, ...);
292#endif
293void UartPacketConfig(PacketGetFunc_t packetGetFunc,
294                      int packetSize,
295                      OS_MQueue_t *mQueue);
296void UartPacketSend(uint8 *data, int bytes);
297#ifdef WIN32
298#define puts puts2
299#define getch getch2
300#define kbhit kbhit2
301#endif
302int puts(const char *string);
303int getch(void);
304int kbhit(void);
305void LogWrite(int a);
306void LogDump(void);
307void Led(int mask, int value);
308
309/***************** Keyboard **************/
310#define KEYBOARD_RAW 0x100
311#define KEYBOARD_E0 0x200
312#define KEYBOARD_RELEASE 0x400
313void KeyboardInit(void);
314int KeyboardGetch(void);
315
316/***************** Math ******************/
317//IEEE single precision floating point math
318#ifndef WIN32
319#define FP_Neg __negsf2
320#define FP_Add __addsf3
321#define FP_Sub __subsf3
322#define FP_Mult __mulsf3
323#define FP_Div __divsf3
324#define FP_ToLong __fixsfsi
325#define FP_ToFloat __floatsisf
326#define sqrt FP_Sqrt
327#define cos FP_Cos
328#define sin FP_Sin
329#define atan FP_Atan
330#define log FP_Log
331#define exp FP_Exp
332#endif
333float FP_Neg(float a_fp);
334float FP_Add(float a_fp, float b_fp);
335float FP_Sub(float a_fp, float b_fp);
336float FP_Mult(float a_fp, float b_fp);
337float FP_Div(float a_fp, float b_fp);
338long FP_ToLong(float a_fp);
339float FP_ToFloat(long af);
340int FP_Cmp(float a_fp, float b_fp);
341float FP_Sqrt(float a);
342float FP_Cos(float rad);
343float FP_Sin(float rad);
344float FP_Atan(float x);
345float FP_Atan2(float y, float x);
346float FP_Exp(float x);
347float FP_Log(float x);
348float FP_Pow(float x, float y);
349
350/***************** Filesys ******************/
351#ifdef INCLUDE_FILESYS
352#define FILE OS_FILE
353#define fopen OS_fopen
354#define fclose OS_fclose
355#define fread OS_fread
356#define fwrite OS_fwrite
357#define fseek OS_fseek
358#endif
359#define _FILESYS_
360typedef struct OS_FILE_s OS_FILE;
361OS_FILE *OS_fopen(char *name, char *mode);
362void OS_fclose(OS_FILE *file);
363int OS_fread(void *buffer, int size, int count, OS_FILE *file);
364int OS_fwrite(void *buffer, int size, int count, OS_FILE *file);
365int OS_fseek(OS_FILE *file, int offset, int mode);
366int OS_fmkdir(char *name);
367int OS_fdir(OS_FILE *dir, char name[64]);
368void OS_fdelete(char *name);
369int OS_flength(char *entry);
370
371/***************** Flash ******************/
372void FlashRead(uint16 *dst, uint32 byteOffset, int bytes);
373void FlashWrite(uint16 *src, uint32 byteOffset, int bytes);
374void FlashErase(uint32 byteOffset);
375
376#endif //__RTOS_H__
377
plasma/kernel/rtos_test.c
1/*--------------------------------------------------------------------
2 * TITLE: Test Plasma Real Time Operating System
3 * AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4 * DATE CREATED: 1/1/06
5 * FILENAME: rtos_test.c
6 * PROJECT: Plasma CPU core
7 * COPYRIGHT: Software placed into the public domain by the author.
8 * Software 'as is' without warranty. Author liable for nothing.
9 * DESCRIPTION:
10 * Test Plasma Real Time Operating System
11 *--------------------------------------------------------------------*/
12#include "plasma.h"
13#include "rtos.h"
14#include "tcpip.h"
15
16/* Including mmu.h will cause all OS calls to use SYSCALL */
17//#include "mmu.h"
18
19//#define DLL_SETUP
20//#define DLL_CALL
21//#include "dll.h"
22
23#define SEMAPHORE_COUNT 50
24#define TIMER_COUNT 10
25
26extern void TestMathFull(void);
27
28typedef struct {
29   OS_Thread_t *MyThread[TIMER_COUNT];
30   OS_Semaphore_t *MySemaphore[SEMAPHORE_COUNT];
31   OS_Mutex_t *MyMutex;
32   OS_Timer_t *MyTimer[TIMER_COUNT];
33   OS_MQueue_t *MyQueue[TIMER_COUNT];
34   int TimerDone;
35} TestInfo_t;
36
37int Global;
38
39//******************************************************************
40static void TestCLib(void)
41{
42   char s1[80], s2[80], *ptr;
43   int rc, v1, v2, v3;
44
45   printf("TestCLib\n");
46   strcpy(s1, "Hello ");
47   memset(s2, 0, sizeof(s2));
48   strncpy(s2, "World wide", 5);
49   strcat(s1, s2);
50   strncat(s1, "!\nthing", 14);
51   printf("%s", s1);
52   rc = strcmp(s1, "Hello World!\n");
53   assert(rc == 0);
54   rc = strcmp(s1, "Hello WOrld!\n");
55   assert(rc > 0);
56   rc = strcmp(s1, "Hello world!\n");
57   assert(rc < 0);
58   rc = strncmp(s1, "Hellx", 4);
59   assert(rc == 0);
60   ptr = strstr(s1, "orl");
61   assert(ptr[0] = 'o');
62   rc = strlen(s1);
63   assert(rc == 13);
64   memcpy(s2, s1, rc+1);
65   rc = memcmp(s1, s2, 8);
66   assert(rc == 0);
67   s2[5] = 'z';
68   rc = memcmp(s1, s2, 8);
69   assert(rc != 0);
70   memset(s2, 0, 5);
71   memset(s2, 'a', 3);
72   rc = abs(-5);
73   itoa(1234, s1, 10);
74   itoa(0, s1, 10);
75   itoa(-1234, s1, 10);
76   itoa(0xabcd, s1, 16);
77   itoa(0x12ab, s1, 16);
78   sprintf(s1, "test c%c d%d 0x%x s%s End\n", 'C', 1234, 0xabcd, "String");
79   printf("%s", s1);
80   sprintf(s1, "test c%c d%6d 0x%6x s%8s End\n", 'C', 1234, 0xabcd, "String");
81   printf("%s", s1);
82   sscanf("1234 -1234 0xabcd text h", "%d %d %x %s", &v1, &v2, &v3, s1);
83   assert(v1 == 1234 && v2 == -1234 && v3 == 0xabcd);
84   assert(strcmp(s1, "text") == 0);
85   //UartScanf("%d %d", &v1, &v2);
86   //printf("v1 = %d v2 = %d\n", v1, v2);
87   printf("Done.\n");
88}
89
90//******************************************************************
91static void TestHeap(void)
92{
93   uint8 *ptrs[256], size[256], *ptr;
94   int i, j, k, value;
95
96   printf("TestHeap\n");
97   memset(ptrs, 0, sizeof(ptrs));
98   for(i = 0; i < 1000; ++i)
99   {
100      j = rand() & 255;
101      if(ptrs[j])
102      {
103         ptr = ptrs[j];
104         value = size[j];
105         for(k = 0; k < value; ++k)
106         {
107            if(ptr[k] != value)
108               printf("Error\n");
109         }
110         OS_HeapFree(ptrs[j]);
111      }
112      size[j] = (uint8)(rand() & 255);
113      ptrs[j] = OS_HeapMalloc(NULL, size[j]);
114      if(ptrs[j] == NULL)
115         printf("malloc NULL\n");
116      else
117         memset(ptrs[j], size[j], size[j]);
118   }
119   for(i = 0; i < 256; ++i)
120   {
121      if(ptrs[i])
122         OS_HeapFree(ptrs[i]);
123   }
124   printf("Done.\n");
125}
126
127//******************************************************************
128static void MyThreadMain(void *arg)
129{
130   OS_Thread_t *thread;
131   int priority;
132
133   thread = OS_ThreadSelf();
134   priority = OS_ThreadPriorityGet(thread);
135   OS_ThreadSleep(10);
136   printf("Arg=%d thread=0x%x info=0x%x priority=%d\n",
137      (uint32)arg, thread, OS_ThreadInfoGet(thread, 0), priority);
138   OS_ThreadExit();
139}
140
141static void TestThread(void)
142{
143   OS_Thread_t *thread;
144   int i, priority;
145
146   printf("TestThread\n");
147   for(i = 0; i < 32; ++i)
148   {
149      priority = 50 + i;
150      thread = OS_ThreadCreate("MyThread", MyThreadMain, (uint32*)i, priority, 0);
151      OS_ThreadInfoSet(thread, 0, (void*)(0xabcd + i));
152      //printf("Created thread 0x%x\n", thread);
153   }
154
155   thread = OS_ThreadSelf();
156   priority = OS_ThreadPriorityGet(thread);
157   printf("Priority = %d\n", priority);
158   OS_ThreadPrioritySet(thread, 200);
159   printf("Priority = %d\n", OS_ThreadPriorityGet(thread));
160   OS_ThreadPrioritySet(thread, priority);
161
162   printf("Thread time = %d\n", OS_ThreadTime());
163   OS_ThreadSleep(100);
164   printf("Thread time = %d\n", OS_ThreadTime());
165}
166
167//******************************************************************
168static void TestSemThread(void *arg)
169{
170   int i;
171   TestInfo_t *info = (TestInfo_t*)arg;
172
173   for(i = 0; i < SEMAPHORE_COUNT/2; ++i)
174   {
175      printf("s");
176      OS_SemaphorePend(info->MySemaphore[i], OS_WAIT_FOREVER);
177      OS_SemaphorePost(info->MySemaphore[i + SEMAPHORE_COUNT/2]);
178   }
179   OS_ThreadExit();
180}
181
182static void TestSemaphore(void)
183{
184   int i, rc;
185   TestInfo_t info;
186   printf("TestSemaphore\n");
187   for(i = 0; i < SEMAPHORE_COUNT; ++i)
188   {
189      info.MySemaphore[i] = OS_SemaphoreCreate("MySem", 0);
190      //printf("sem[%d]=0x%x\n", i, MySemaphore[i]);
191   }
192
193   OS_ThreadCreate("TestSem", TestSemThread, &info, 50, 0);
194
195   for(i = 0; i < SEMAPHORE_COUNT/2; ++i)
196   {
197      printf("S");
198      OS_SemaphorePost(info.MySemaphore[i]);
199      rc = OS_SemaphorePend(info.MySemaphore[i + SEMAPHORE_COUNT/2], 500);
200      assert(rc == 0);
201   }
202
203   printf(":");
204   rc = OS_SemaphorePend(info.MySemaphore[0], 10);
205   assert(rc != 0);
206   printf(":");
207   OS_SemaphorePend(info.MySemaphore[0], 100);
208   printf(":");
209
210   for(i = 0; i < SEMAPHORE_COUNT; ++i)
211      OS_SemaphoreDelete(info.MySemaphore[i]);
212
213   printf("\nDone.\n");
214}
215
216//******************************************************************
217static void TestMutexThread(void *arg)
218{
219   TestInfo_t *info = (TestInfo_t*)arg;
220
221   printf("Waiting for mutex\n");
222   OS_MutexPend(info->MyMutex);
223   printf("Have Mutex1\n");
224   OS_MutexPend(info->MyMutex);
225   printf("Have Mutex2\n");
226   OS_MutexPend(info->MyMutex);
227   printf("Have Mutex3\n");
228
229   OS_ThreadSleep(100);
230
231   OS_MutexPost(info->MyMutex);
232   OS_MutexPost(info->MyMutex);
233   OS_MutexPost(info->MyMutex);
234
235   OS_ThreadExit();
236}
237
238static void TestMutex(void)
239{
240   TestInfo_t info;
241   printf("TestMutex\n");
242   info.MyMutex = OS_MutexCreate("MyMutex");
243   OS_MutexPend(info.MyMutex);
244   OS_MutexPend(info.MyMutex);
245   OS_MutexPend(info.MyMutex);
246
247   OS_ThreadSleep(100);
248
249   OS_ThreadCreate("TestMutex", TestMutexThread, &info, 50, 0);
250
251   OS_ThreadSleep(50);
252   OS_MutexPost(info.MyMutex);
253   OS_MutexPost(info.MyMutex);
254   OS_MutexPost(info.MyMutex);
255
256   printf("Try get mutex\n");
257   OS_MutexPend(info.MyMutex);
258   printf("Gotit\n");
259
260   OS_MutexDelete(info.MyMutex);
261   printf("Done.\n");
262}
263
264//******************************************************************
265static void TestMQueue(void)
266{
267   OS_MQueue_t *mqueue;
268   char data[16];
269   int i, rc;
270
271   printf("TestMQueue\n");
272   mqueue = OS_MQueueCreate("MyMQueue", 10, 16);
273   strcpy(data, "Test0");
274   for(i = 0; i < 16; ++i)
275   {
276      data[4] = (char)('0' + i);
277      OS_MQueueSend(mqueue, data);
278   }
279   for(i = 0; i < 16; ++i)
280   {
281      memset(data, 0, sizeof(data));
282      rc = OS_MQueueGet(mqueue, data, 20);
283      if(rc == 0)
284         printf("message=(%s)\n", data);
285      else
286         printf("timeout\n");
287   }
288
289   OS_MQueueDelete(mqueue);
290   printf("Done.\n");
291}
292
293//******************************************************************
294static void TestTimerThread(void *arg)
295{
296   int index;
297   uint32 data[4];
298   OS_Timer_t *timer;
299   TestInfo_t *info = (TestInfo_t*)arg;
300
301   //printf("TestTimerThread\n");
302
303   OS_ThreadSleep(1);
304   index = (int)OS_ThreadInfoGet(OS_ThreadSelf(), 0);
305   //printf("index=%d\n", index);
306   OS_MQueueGet(info->MyQueue[index], data, 1000);
307   timer = (OS_Timer_t*)data[1];
308   printf("%d ", data[2]);
309   OS_MQueueGet(info->MyQueue[index], data, 1000);
310   printf("%d ", data[2]);
311   ++info->TimerDone;
312   OS_ThreadExit();
313}
314
315static void TestTimer(void)
316{
317   int i;
318   TestInfo_t info;
319
320   printf("TestTimer\n");
321   info.TimerDone = 0;
322   for(i = 0; i < TIMER_COUNT; ++i)
323   {
324      info.MyQueue[i] = OS_MQueueCreate("MyQueue", 10, 16);
325      info.MyTimer[i] = OS_TimerCreate("MyTimer", info.MyQueue[i], i);
326      info.MyThread[i] = OS_ThreadCreate("TimerTest", TestTimerThread, &info, 50, 0);
327      OS_ThreadInfoSet(info.MyThread[i], 0, (void*)i);
328      OS_TimerStart(info.MyTimer[i], 10+i*2, 220+i);
329   }
330
331   while(info.TimerDone < TIMER_COUNT)
332      OS_ThreadSleep(10);
333
334   for(i = 0; i < TIMER_COUNT; ++i)
335   {
336      OS_MQueueDelete(info.MyQueue[i]);
337      OS_TimerDelete(info.MyTimer[i]);
338   }
339
340   printf("Done.\n");
341}
342
343//******************************************************************
344#if 1
345void TestMath(void)
346{
347   int i;
348   float a, b, sum, diff, mult, div;
349   uint32 compare;
350
351   //Check add subtract multiply and divide
352   for(i = -4; i < 4; ++i)
353   {
354      a = (float)(i * 10 + (float)63.2);
355      b = (float)(-i * 5 + (float)3.5);
356      sum = a + b;
357      diff = a - b;
358      mult = a * b;
359      div = a / b;
360      printf("a=%dE-3 b=%dE-3 sum=%dE-3 diff=%dE-3 mult=%dE-3 div=%dE-3\n",
361         (int)(a*(float)1000), (int)(b*(float)1000),
362         (int)(sum*(float)1000), (int)(diff*(float)1000),
363         (int)(mult*(float)1000), (int)(div*(float)1000));
364   }
365
366   //Comparisons
367   b = (float)2.0;
368   compare = 0;
369   for(i = 1; i < 4; ++i)
370   {
371      a = (float)i;
372      compare = (compare << 1) | (a == b);
373      compare = (compare << 1) | (a != b);
374      compare = (compare << 1) | (a < b);
375      compare = (compare << 1) | (a <= b);
376      compare = (compare << 1) | (a > b);
377      compare = (compare << 1) | (a >= b);
378   }
379   printf("Compare = %8x %s\n", compare,
380      compare==0x1c953 ? "OK" : "ERROR");
381
382   //Cosine
383   for(a = (float)0.0; a <= (float)(3.1415); a += (float)(3.1415/16.0))
384   {
385      b = FP_Cos(a);
386      printf("cos(%4dE-3) = %4dE-3\n",
387         (int)(a*(float)1000.0), (int)(b*(float)1000.0));
388   }
389}
390#endif
391
392//******************************************************************
393#ifndef WIN32
394static void MySyscall(void *arg)
395{
396   uint32 *stack = arg;
397   stack[STACK_EPC] += 4; //skip over SYSCALL
398   printf("Inside MySyscall %d\n", stack[28/4]);
399}
400
401void TestSyscall(void)
402{
403   OS_InterruptRegister((uint32)(1<<31), MySyscall);
404   OS_Syscall(57);
405   OS_ThreadSleep(1);
406   printf("Done\n");
407}
408#endif
409
410#ifdef __MMU_ENUM_H__
411void TestProcess(void)
412{
413   OS_Process_t *process;
414   process = (OS_Process_t*)OS_HeapMalloc(NULL, sizeof(OS_Process_t));
415   process->name = "test";
416   process->funcPtr = MainThread;
417   process->arg = NULL;
418   process->priority = 200;
419   process->stackSize = 1024*32;
420   process->heapSize = 1024*128;
421   process->processId = 1;
422   process->semaphoreDone = OS_SemaphoreCreate("processDone", 0);
423   printf("Creating process\n");
424   OS_MMUProcessCreate(process);
425   OS_SemaphorePend(process->semaphoreDone, OS_WAIT_FOREVER);
426   printf("Process done\n");
427   OS_MMUProcessDelete(process);
428}
429#endif
430
431
432//******************************************************************
433void MMUTest(void);
434void HtmlThread(void *arg);
435void ConsoleInit(void);
436void exit(int);
437uint8 macAddress[] = {0x00, 0x10, 0xdd, 0xce, 0x15, 0xd4};
438
439
440void MainThread(void *Arg)
441{
442   int ch, i, display=1;
443   (void)Arg;
444#ifdef __MMU_ENUM_H__
445   OS_MMUInit();
446#endif
447
448#ifdef INCLUDE_ETH
449   EthernetInit(macAddress);
450   IPInit(EthernetTransmit, macAddress, "plasma");
451   HtmlInit(1);
452#endif
453
454#ifdef INCLUDE_HTML
455   IPInit(NULL, macAddress, "plasma");
456   HtmlInit(1);
457#endif
458
459#ifdef INCLUDE_CONSOLE
460   ConsoleInit();
461#endif
462
463   for(;;)
464   {
465      if(display)
466      {
467         printf("\n");
468         printf("1 CLib\n");
469         printf("2 Heap\n");
470         printf("3 Thread\n");
471         printf("4 Semaphore\n");
472         printf("5 Mutex\n");
473         printf("6 MQueue\n");
474         printf("7 Timer\n");
475         printf("8 Math\n");
476         printf("9 Syscall\n");
477#ifdef __MMU_ENUM_H__
478         printf("p MMU Process\n");
479#endif
480      }
481      printf("> ");
482      display = 1;
483      ch = UartRead();
484      printf("%c\n", ch);
485      switch(ch)
486      {
487#ifdef WIN32
488      case '0': exit(0);
489#endif
490      case '1': TestCLib(); break;
491      case '2': TestHeap(); break;
492      case '3': TestThread(); break;
493      case '4': TestSemaphore(); break;
494      case '5': TestMutex(); break;
495      case '6': TestMQueue(); break;
496      case '7': TestTimer(); break;
497      case '8': TestMath(); break;
498#ifndef WIN32
499      case '9': TestSyscall(); break;
500#endif
501#ifdef __MMU_ENUM_H__
502      case 'p': TestProcess(); break;
503#endif
504#ifdef WIN32
505      case 'm': TestMathFull(); break;
506#endif
507      case 'g': printf("Global=%d\n", ++Global); break;
508      default:
509         printf("E");
510         display = 0;
511         for(i = 0; i < 30; ++i)
512         {
513            while(kbhit())
514               ch = UartRead();
515            OS_ThreadSleep(1);
516         }
517         break;
518      }
519   }
520}
521
522
plasma/kernel/tcpip.c
1/*--------------------------------------------------------------------
2 * TITLE: Plasma TCP/IP Protocol Stack
3 * AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4 * DATE CREATED: 4/22/06
5 * FILENAME: tcpip.c
6 * PROJECT: Plasma CPU core
7 * COPYRIGHT: Software placed into the public domain by the author.
8 * Software 'as is' without warranty. Author liable for nothing.
9 * DESCRIPTION:
10 * Plasma TCP/IP Protocol Stack
11 *
12 * Possible call stack when receiving a packet:
13 * IPMainThread()
14 * IPProcessEthernetPacket()
15 * IPProcessTCPPacket()
16 * TCPSendPacket()
17 * IPSendPacket()
18 * IPChecksum()
19 * IPSendFrame()
20 * FrameInsert()
21 *--------------------------------------------------------------------*/
22#ifdef WIN32
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <assert.h>
27#define _LIBC
28#endif
29#include "rtos.h"
30#define IPPRINTF
31#include "tcpip.h"
32
33
34//ETHER FIELD OFFSET LENGTH VALUE
35#define ETHERNET_DEST 0 //6
36#define ETHERNET_SOURCE 6 //6
37#define ETHERNET_FRAME_TYPE 12 //2 IP=0x0800; ARP=0x0806
38
39//ARP FIELD OFFSET LENGTH VALUE
40#define ARP_HARD_TYPE 14 //2 0x0001
41#define ARP_PROT_TYPE 16 //2 0x0800
42#define ARP_HARD_SIZE 18 //1 0x06
43#define ARP_PROT_SIZE 19 //1 0x04
44#define ARP_OP 20 //2 ARP=1;ARPreply=2
45#define ARP_ETHERNET_SENDER 22 //6
46#define ARP_IP_SENDER 28 //4
47#define ARP_ETHERNET_TARGET 32 //6
48#define ARP_IP_TARGET 38 //4
49#define ARP_PAD 42 //18 0
50
51//IP FIELD OFFSET LENGTH VALUE
52#define IP_VERSION_LENGTH 14 //1 0x45
53#define IP_TYPE_OF_SERVICE 15 //1 0x00
54#define IP_LENGTH 16 //2
55#define IP_ID16 18 //2
56#define IP_FRAG_OFFSET 20 //2
57#define IP_TIME_TO_LIVE 22 //1 0x80
58#define IP_PROTOCOL 23 //1 TCP=0x06;PING=0x01;UDP=0x11
59#define IP_CHECKSUM 24 //2
60#define IP_SOURCE 26 //4
61#define IP_DEST 30 //4
62
63//PSEUDO FIELD OFFSET LENGTH VALUE
64#define PSEUDO_IP_SOURCE 0 //4
65#define PSEUDO_IP_DEST 4 //4
66#define PSEUDO_ZERO 8 //1 0
67#define PSEUDO_IP_PROTOCOL 9 //1
68#define PSEUDO_LENGTH 10 //2
69
70//UDP FIELD OFFSET LENGTH VALUE
71#define UDP_SOURCE_PORT 34 //2
72#define UDP_DEST_PORT 36 //2
73#define UDP_LENGTH 38 //2
74#define UDP_CHECKSUM 40 //2
75#define UDP_DATA 42
76
77//DHCP FIELD OFFSET LENGTH VALUE
78#define DHCP_OPCODE 42 //1 REQUEST=1;REPLY=2
79#define DHCP_HW_TYPE 43 //1 1
80#define DHCP_HW_LEN 44 //1 6
81#define DHCP_HOP_COUNT 45 //1 0
82#define DHCP_TRANS_ID 46 //4
83#define DHCP_NUM_SEC 50 //2 0
84#define DHCP_UNUSED 52 //2
85#define DHCP_CLIENT_IP 54 //4
86#define DHCP_YOUR_IP 58 //4
87#define DHCP_SERVER_IP 62 //4
88#define DHCP_GATEWAY_IP 66 //4
89#define DHCP_CLIENT_ETHERNET 70 //16
90#define DHCP_SERVER_NAME 86 //64
91#define DHCP_BOOT_FILENAME 150 //128
92#define DHCP_MAGIC_COOKIE 278 //4 0x63825363
93#define DHCP_OPTIONS 282 //N
94
95#define DHCP_MESSAGE_TYPE 53 //1 type
96#define DHCP_DISCOVER 1
97#define DHCP_OFFER 2
98#define DHCP_REQUEST 3
99#define DHCP_ACK 5
100#define DHCP_REQUEST_IP 50 //4 ip
101#define DHCP_REQUEST_SERV_IP 54 //4 ip
102#define DHCP_CLIENT_ID 61 //7 1 ethernet
103#define DHCP_HOST_NAME 12 //6 plasma
104#define DHCP_PARAMS 55 //4 1=subnet; 15=domain_name; 3=router; 6=dns
105#define DHCP_PARAM_SUBNET 1
106#define DHCP_PARAM_ROUTER 3
107#define DHCP_PARAM_DNS 6
108#define DHCP_END_OPTION 0xff
109
110//DHCP FIELD OFFSET LENGTH VALUE
111#define DNS_ID 0 //2
112#define DNS_FLAGS 2 //2
113#define DNS_NUM_QUESTIONS 4 //2 1
114#define DNS_NUM_ANSWERS_RR 6 //2 0/1
115#define DNS_NUM_AUTHORITY_RR 8 //2 0
116#define DNS_NUM_ADDITIONAL_RR 10 //2 0
117#define DNS_QUESTIONS 12 //2
118
119#define DNS_FLAGS_RESPONSE 0x8000
120#define DNS_FLAGS_RECURSIVE 0x0100
121#define DNS_FLAGS_ERROR 0x0003
122#define DNS_FLAGS_OK 0x0000
123#define DNS_QUERY_TYPE_IP 1
124#define DNS_QUERY_CLASS 1
125#define DNS_PORT 53
126
127//TCP FIELD OFFSET LENGTH VALUE
128#define TCP_SOURCE_PORT 34 //2
129#define TCP_DEST_PORT 36 //2
130#define TCP_SEQ 38 //4
131#define TCP_ACK 42 //4
132#define TCP_HEADER_LENGTH 46 //1 0x50
133#define TCP_FLAGS 47 //1 SYNC=0x2;ACK=0x10;FIN=0x1
134#define TCP_WINDOW_SIZE 48 //2
135#define TCP_CHECKSUM 50 //2
136#define TCP_URGENT_POINTER 52 //2
137#define TCP_DATA 54 //length-N
138
139#define TCP_FLAGS_FIN 1
140#define TCP_FLAGS_SYN 2
141#define TCP_FLAGS_RST 4
142#define TCP_FLAGS_PSH 8
143#define TCP_FLAGS_ACK 16
144
145//PING FIELD OFFSET LENGTH VALUE
146#define PING_TYPE 34 //1 SEND=8;REPLY=0
147#define PING_CODE 35 //1 0
148#define PING_CHECKSUM 36 //2
149#define PING_ID 38 //2
150#define PING_SEQUENCE 40 //2
151#define PING_DATA 44
152
153static void IPClose2(IPSocket *Socket);
154
155static uint8 ethernetAddressGateway[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
156#ifndef WIN32
157static uint8 ethernetAddressPlasma[] = {0x00, 0x10, 0xdd, 0xce, 0x15, 0xd4};
158#else
159static uint8 ethernetAddressPlasma[] = {0x00, 0x10, 0xdd, 0xce, 0x15, 0xd5};
160#endif
161
162static uint8 ipAddressPlasma[] = {0x9d, 0xfe, 0x28, 10}; //changed by DHCP
163static uint8 ipAddressGateway[] = {0xff, 0xff, 0xff, 0xff}; //changed by DHCP
164static uint32 ipAddressDns; //changed by DHCP
165
166static OS_Mutex_t *IPMutex;
167static int FrameFreeCount;
168static IPFrame *FrameFreeHead;
169static IPFrame *FrameSendHead;
170static IPFrame *FrameSendTail;
171static IPFrame *FrameResendHead;
172static IPFrame *FrameResendTail;
173static IPSocket *SocketHead;
174static uint32 Seconds;
175static int DhcpRetrySeconds;
176static IPFuncPtr FrameSendFunc;
177static OS_MQueue_t *IPMQueue;
178static OS_Thread_t *IPThread;
179int IPVerbose=1;
180
181static const unsigned char dhcpDiscover[] = {
182   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, //dest
183   0x00, 0x10, 0xdd, 0xce, 0x15, 0xd4, //src
184   0x08, 0x00,
185   0x45, 0x00, 0x01, 0x48, 0x2e, 0xf5, 0x00, 0x00, //ip
186   0x80, 0x11, 0x0a, 0xb1, 0x00, 0x00, 0x00, 0x00,
187   0xff, 0xff, 0xff, 0xff,
188   0x00, 0x44, 0x00, 0x43, 0x01, 0x34, 0x45, 0x66, //udp
189   0x01, 0x01, 0x06, 0x00, 0x69, 0x26, 0xb5, 0x52 //dhcp
190};
191
192static unsigned char dhcpOptions[] = {
193   0x63, 0x82, 0x53, 0x63, //cookie
194   0x35, 0x01, 0x01, //DHCP Discover
195   0x3d, 0x07, 0x01, 0x00, 0x10, 0xdd, 0xce, 0x15, 0xd4, //Client identifier
196#ifndef WIN32
197   0x0c, 0x06, 'p', 'l', 'a', 's', 'm', 'a', //Host name
198#else
199   0x0c, 0x06, 'p', 'l', 'a', 's', 'm', 'b', //Host name
200#endif
201   0x37, 0x03, DHCP_PARAM_SUBNET, DHCP_PARAM_ROUTER, DHCP_PARAM_DNS, //Parameters
202   DHCP_END_OPTION
203};
204
205
206//Get a free frame; can be called from an ISR
207IPFrame *IPFrameGet(int freeCount)
208{
209   IPFrame *frame=NULL;
210   uint32 state;
211
212   state = OS_CriticalBegin();
213   if(FrameFreeCount > freeCount)
214   {
215      frame = FrameFreeHead;
216      if(FrameFreeHead)
217      {
218         FrameFreeHead = FrameFreeHead->next;
219         --FrameFreeCount;
220      }
221   }
222   OS_CriticalEnd(state);
223   if(frame)
224   {
225      assert(frame->state == 0);
226      frame->state = 1;
227   }
228   return frame;
229}
230
231
232static void FrameFree(IPFrame *frame)
233{
234   uint32 state;
235
236   assert(frame->state == 1);
237   frame->state = 0;
238   state = OS_CriticalBegin();
239   frame->next = FrameFreeHead;
240   FrameFreeHead = frame;
241   ++FrameFreeCount;
242   OS_CriticalEnd(state);
243}
244
245
246static void FrameInsert(IPFrame **head, IPFrame **tail, IPFrame *frame)
247{
248   assert(frame->state == 1);
249   frame->state = 2;
250   OS_MutexPend(IPMutex);
251   frame->prev = NULL;
252   frame->next = *head;
253   if(*head)
254      (*head)->prev = frame;
255   *head = frame;
256   if(*tail == NULL)
257      *tail = frame;
258   OS_MutexPost(IPMutex);
259}
260
261
262static void FrameRemove(IPFrame **head, IPFrame **tail, IPFrame *frame)
263{
264   assert(frame->state == 2);
265   frame->state = 1;
266   if(frame->prev)
267      frame->prev->next = frame->next;
268   else
269      *head = frame->next;
270   if(frame->next)
271      frame->next->prev = frame->prev;
272   else
273      *tail = frame->prev;
274   frame->prev = NULL;
275   frame->next = NULL;
276}
277
278
279static int IPChecksum(int checksum, const unsigned char *data, int length)
280{
281   int i;
282   checksum = ~checksum & 0xffff;
283   for(i = 0; i < length-1; i += 2)
284   {
285      checksum += (data[i] << 8) | data[i+1];
286   }
287   if(i < length)
288      checksum += data[i] << 8;
289   while(checksum >> 16)
290      checksum = (checksum & 0xffff) + (checksum >> 16);
291   checksum = ~checksum & 0xffff;
292   return checksum;
293}
294
295
296static int EthernetVerifyChecksums(const unsigned char *packet, int length)
297{
298   int checksum, length2;
299   unsigned char pseudo[12];
300
301   //Calculate checksums
302   if(packet[ETHERNET_FRAME_TYPE+1] == 0x00) //IP
303   {
304      checksum = IPChecksum(0xffff, packet+IP_VERSION_LENGTH, 20);
305      if(checksum)
306         return -1;
307      if(packet[IP_PROTOCOL] == 0x01) //PING
308      {
309         checksum = IPChecksum(0xffff, packet+PING_TYPE, length-PING_TYPE);
310      }
311      else if(packet[IP_PROTOCOL] == 0x11) //UDP
312      {
313         if(packet[UDP_CHECKSUM] == 0 && packet[UDP_CHECKSUM+1] == 0)
314            return 0;
315         memcpy(pseudo+PSEUDO_IP_SOURCE, packet+IP_SOURCE, 4);
316         memcpy(pseudo+PSEUDO_IP_DEST, packet+IP_DEST, 4);
317         pseudo[PSEUDO_ZERO] = 0;
318         pseudo[PSEUDO_IP_PROTOCOL] = packet[IP_PROTOCOL];
319         memcpy(pseudo+PSEUDO_LENGTH, packet+UDP_LENGTH, 2);
320         checksum = IPChecksum(0xffff, pseudo, 12);
321         length2 = (packet[UDP_LENGTH] << 8) + packet[UDP_LENGTH+1];
322         checksum = IPChecksum(checksum, packet+UDP_SOURCE_PORT, length);
323      }
324      else if(packet[IP_PROTOCOL] == 0x06) //TCP
325      {
326         memcpy(pseudo+PSEUDO_IP_SOURCE, packet+IP_SOURCE, 4);
327         memcpy(pseudo+PSEUDO_IP_DEST, packet+IP_DEST, 4);
328         pseudo[PSEUDO_ZERO] = 0;
329         pseudo[PSEUDO_IP_PROTOCOL] = packet[IP_PROTOCOL];
330         length = (packet[IP_LENGTH] << 8) + packet[IP_LENGTH+1];
331         length2 = length - 20;
332         pseudo[PSEUDO_LENGTH] = (unsigned char)(length2 >> 8);
333         pseudo[PSEUDO_LENGTH+1] = (unsigned char)length2;
334         checksum = IPChecksum(0xffff, pseudo, 12);
335         checksum = IPChecksum(checksum, packet+TCP_SOURCE_PORT, length2);
336      }
337      if(checksum)
338         return -1;
339   }
340   return 0;
341}
342
343
344static void IPFrameReschedule(IPFrame *frame)
345{
346   int length;
347   length = frame->length - TCP_DATA;
348   if(frame->packet[TCP_FLAGS] & (TCP_FLAGS_FIN | TCP_FLAGS_SYN))
349      ++length;
350   if(frame->socket == NULL || frame->socket->state == IP_UDP || length == 0 ||
351      frame->socket->state == IP_PING || ++frame->retryCnt > 4)
352   {
353      FrameFree(frame); //can't be ACK'ed
354   }
355#ifdef WIN32
356   else if(FrameFreeCount < FRAME_COUNT_SYNC)
357   {
358      FrameFree(frame); //can't be ACK'ed
359   }
360#endif
361   else
362   {
363      //Put on resend list until TCP ACK'ed
364      frame->timeout = (short)(RETRANSMIT_TIME * frame->retryCnt);
365      FrameInsert(&FrameResendHead, &FrameResendTail, frame);
366   }
367}
368
369
370static void IPSendFrame(IPFrame *frame)
371{
372   uint32 message[4];
373
374   if(FrameSendFunc)
375   {
376      //Single threaded
377      FrameSendFunc(frame->packet, frame->length);
378      IPFrameReschedule(frame);
379   }
380   else
381   {
382      //Add Packet to send queue
383      FrameInsert(&FrameSendHead, &FrameSendTail, frame);
384
385      //Wakeup sender thread
386      message[0] = 2;
387      OS_MQueueSend(IPMQueue, message);
388   }
389}
390
391
392static void IPSendPacket(IPSocket *socket, IPFrame *frame, int length)
393{
394   int checksum, length2=length;
395   unsigned char pseudo[12], *packet=frame->packet;
396
397   frame->length = (uint16)length;
398
399   //Calculate checksums
400   if(packet[ETHERNET_FRAME_TYPE+1] == 0x00) //IP
401   {
402      length2 = length - IP_VERSION_LENGTH;
403      packet[IP_LENGTH] = (uint8)(length2 >> 8);
404      packet[IP_LENGTH+1] = (uint8)length2;
405      memset(packet+IP_CHECKSUM, 0, 2);
406      checksum = IPChecksum(0xffff, packet+IP_VERSION_LENGTH, 20);
407      packet[IP_CHECKSUM] = (unsigned char)(checksum >> 8);
408      packet[IP_CHECKSUM+1] = (unsigned char)checksum;
409      if(packet[IP_PROTOCOL] == 0x01) //ICMP & PING
410      {
411         memset(packet+PING_CHECKSUM, 0, 2);
412         checksum = IPChecksum(0xffff, packet+PING_TYPE, length-PING_TYPE);
413         packet[PING_CHECKSUM] = (unsigned char)(checksum >> 8);
414         packet[PING_CHECKSUM+1] = (unsigned char)checksum;
415      }
416      else if(packet[IP_PROTOCOL] == 0x11) //UDP
417      {
418         length2 = length - UDP_SOURCE_PORT;
419         packet[UDP_LENGTH] = (uint8)(length2 >> 8);
420         packet[UDP_LENGTH+1] = (uint8)length2;
421         memcpy(pseudo+PSEUDO_IP_SOURCE, packet+IP_SOURCE, 4);
422         memcpy(pseudo+PSEUDO_IP_DEST, packet+IP_DEST, 4);
423         pseudo[PSEUDO_ZERO] = 0;
424         pseudo[PSEUDO_IP_PROTOCOL] = packet[IP_PROTOCOL];
425         memcpy(pseudo+PSEUDO_LENGTH, packet+UDP_LENGTH, 2);
426         checksum = IPChecksum(0xffff, pseudo, 12);
427         memset(packet+UDP_CHECKSUM, 0, 2);
428         length2 = (packet[UDP_LENGTH] << 8) + packet[UDP_LENGTH+1];
429         checksum = IPChecksum(checksum, packet+UDP_SOURCE_PORT, length2);
430         packet[UDP_CHECKSUM] = (unsigned char)(checksum >> 8);
431         packet[UDP_CHECKSUM+1] = (unsigned char)checksum;
432      }
433      else if(packet[IP_PROTOCOL] == 0x06) //TCP
434      {
435         memcpy(pseudo+PSEUDO_IP_SOURCE, packet+IP_SOURCE, 4);
436         memcpy(pseudo+PSEUDO_IP_DEST, packet+IP_DEST, 4);
437         pseudo[PSEUDO_ZERO] = 0;
438         pseudo[PSEUDO_IP_PROTOCOL] = packet[IP_PROTOCOL];
439         length2 = (packet[IP_LENGTH] << 8) + packet[IP_LENGTH+1];
440         length2 = length2 - 20;
441         pseudo[PSEUDO_LENGTH] = (unsigned char)(length2 >> 8);
442         pseudo[PSEUDO_LENGTH+1] = (unsigned char)length2;
443         checksum = IPChecksum(0xffff, pseudo, 12);
444         memset(packet+TCP_CHECKSUM, 0, 2);
445         checksum = IPChecksum(checksum, packet+TCP_SOURCE_PORT, length2);
446         packet[TCP_CHECKSUM] = (unsigned char)(checksum >> 8);
447         packet[TCP_CHECKSUM+1] = (unsigned char)checksum;
448      }
449   }
450
451   length2 = length - TCP_DATA;
452   if(socket && (packet[TCP_FLAGS] & (TCP_FLAGS_FIN | TCP_FLAGS_SYN)))
453      length2 = 1;
454   frame->socket = socket;
455   frame->timeout = 0;
456   frame->retryCnt = 0;
457   if(socket)
458      frame->seqEnd = socket->seq + length2;
459   IPSendFrame(frame);
460}
461
462
463static void TCPSendPacket(IPSocket *socket, IPFrame *frame, int length)
464{
465   uint8 *packet = frame->packet;
466   int flags, count;
467
468   flags = packet[TCP_FLAGS];
469   memcpy(packet, socket->headerSend, TCP_SEQ);
470   packet[TCP_FLAGS] = (uint8)flags;
471   if(flags & TCP_FLAGS_SYN)
472      packet[TCP_HEADER_LENGTH] = 0x60; //set maximum segment size
473   else
474      packet[TCP_HEADER_LENGTH] = 0x50;
475   packet[TCP_SEQ] = (uint8)(socket->seq >> 24);
476   packet[TCP_SEQ+1] = (uint8)(socket->seq >> 16);
477   packet[TCP_SEQ+2] = (uint8)(socket->seq >> 8);
478   packet[TCP_SEQ+3] = (uint8)socket->seq;
479   packet[TCP_ACK] = (uint8)(socket->ack >> 24);
480   packet[TCP_ACK+1] = (uint8)(socket->ack >> 16);
481   packet[TCP_ACK+2] = (uint8)(socket->ack >> 8);
482   packet[TCP_ACK+3] = (uint8)socket->ack;
483   count = RECEIVE_WINDOW - (socket->ack - socket->ackProcessed);
484   if(count < 0)
485      count = 0;
486   packet[TCP_WINDOW_SIZE] = (uint8)(count >> 8);
487   packet[TCP_WINDOW_SIZE+1] = (uint8)count;
488   packet[TCP_URGENT_POINTER] = 0;
489   packet[TCP_URGENT_POINTER+1] = 0;
490   IPSendPacket(socket, frame, length);
491}
492
493
494static void EthernetCreateResponse(unsigned char *packetOut,
495                                   const unsigned char *packet,
496                                   int length)
497{
498   //Swap destination and source fields
499   memcpy(packetOut, packet, length);
500   memcpy(packetOut+ETHERNET_DEST, packet+ETHERNET_SOURCE, 6);
501   memcpy(packetOut+ETHERNET_SOURCE, packet+ETHERNET_DEST, 6);
502   if(packet[ETHERNET_FRAME_TYPE+1] == 0x00) //IP
503   {
504      memcpy(packetOut+IP_SOURCE, packet+IP_DEST, 4);
505      memcpy(packetOut+IP_DEST, packet+IP_SOURCE, 4);
506      if(packet[IP_PROTOCOL] == 0x06 || packet[IP_PROTOCOL] == 0x11) //TCP/UDP
507      {
508         memcpy(packetOut+TCP_SOURCE_PORT, packet+TCP_DEST_PORT, 2);
509         memcpy(packetOut+TCP_DEST_PORT, packet+TCP_SOURCE_PORT, 2);
510      }
511   }
512}
513
514
515static void IPDhcp(const unsigned char *packet, int length, int state)
516{
517   uint8 *packetOut, *ptr;
518   const uint8 *ptr2;
519   IPFrame *frame;
520   static int request=0;
521
522   if(state == 1)
523   {
524      //Create DHCP Discover
525      frame = IPFrameGet(0);
526      if(frame == NULL)
527         return;
528      packetOut = frame->packet;
529      memset(packetOut, 0, 512);
530      memcpy(packetOut, dhcpDiscover, sizeof(dhcpDiscover));
531      memcpy(packetOut+ETHERNET_SOURCE, ethernetAddressPlasma, 6);
532      memcpy(packetOut+DHCP_CLIENT_ETHERNET, ethernetAddressPlasma, 6);
533      memcpy(packetOut+DHCP_MAGIC_COOKIE, dhcpOptions, sizeof(dhcpOptions));
534      memcpy(packetOut+DHCP_MAGIC_COOKIE+10, ethernetAddressPlasma, 6);
535      IPSendPacket(NULL, frame, 400);
536      request = DHCP_DISCOVER;
537      DhcpRetrySeconds = 2;
538   }
539   else if(state == 2 && memcmp(packet+DHCP_CLIENT_ETHERNET, ethernetAddressPlasma, 6) == 0)
540   {
541      if(packet[DHCP_MAGIC_COOKIE+6] == DHCP_OFFER && request == DHCP_DISCOVER)
542      {
543         //Process DHCP Offer and send DHCP Request
544         frame = IPFrameGet(0);
545         if(frame == NULL)
546            return;
547         packetOut = frame->packet;
548         memset(packetOut, 0, 512);
549         memcpy(packetOut, dhcpDiscover, sizeof(dhcpDiscover));
550         memcpy(packetOut+ETHERNET_SOURCE, ethernetAddressPlasma, 6);
551         memcpy(packetOut+DHCP_CLIENT_ETHERNET, ethernetAddressPlasma, 6);
552         memcpy(packetOut+DHCP_MAGIC_COOKIE, dhcpOptions, sizeof(dhcpOptions));
553         memcpy(packetOut+DHCP_MAGIC_COOKIE+10, ethernetAddressPlasma, 6);
554         request = DHCP_REQUEST;
555         packetOut[DHCP_MAGIC_COOKIE+6] = DHCP_REQUEST;
556         ptr = packetOut+DHCP_MAGIC_COOKIE+sizeof(dhcpOptions)-1;
557         ptr[0] = DHCP_REQUEST_IP;
558         ptr[1] = 4;
559         memcpy(ptr+2, packet+DHCP_YOUR_IP, 4);
560         ptr[6] = DHCP_REQUEST_SERV_IP;
561         ptr[7] = 4;
562         memcpy(ptr+8, packet+DHCP_SERVER_IP, 4);
563         ptr[12] = DHCP_END_OPTION;
564         IPSendPacket(NULL, frame, 400);
565      }
566      else if(packet[DHCP_MAGIC_COOKIE+6] == DHCP_ACK && request == DHCP_REQUEST)
567      {
568         //Process DHCP Ack
569         request = 0;
570         DhcpRetrySeconds = 3600*4;
571         memcpy(ipAddressPlasma, packet+DHCP_YOUR_IP, 4);
572         printf("IP=%d.%d.%d.%d ", ipAddressPlasma[0], ipAddressPlasma[1],
573            ipAddressPlasma[2], ipAddressPlasma[3]);
574         memcpy(ipAddressGateway, packet+DHCP_GATEWAY_IP, 4);
575         if(ipAddressGateway[0] == 0 && ipAddressGateway[1] == 0 &&
576            ipAddressGateway[2] == 0 && ipAddressGateway[3] == 0)
577            memcpy(ipAddressGateway, packet+DHCP_SERVER_IP, 4);
578         printf("GW=%d.%d.%d.%d ", ipAddressGateway[0], ipAddressGateway[1],
579            ipAddressGateway[2], ipAddressGateway[3]);
580         memcpy(ethernetAddressGateway, packet+ETHERNET_SOURCE, 6);
581         ptr2 = packet+DHCP_MAGIC_COOKIE+4;
582         while(ptr2[0] != DHCP_END_OPTION && (int)(ptr2 - packet) < length)
583         {
584            if(ptr2[0] == DHCP_PARAM_DNS)
585            {
586               ipAddressDns = (ptr2[2] << 24) | (ptr2[3] << 16) | (ptr2[4] << 8) | ptr2[5];
587               printf("DNS=%d.%d.%d.%d ", ptr2[2], ptr2[3], ptr2[4], ptr2[5]);
588            }
589            ptr2 += ptr2[1] + 2;
590         }
591
592         //Check if DHCP reply came from gateway
593         if(memcmp(packet+IP_SOURCE, ipAddressGateway, 4))
594         {
595            //Send ARP to gateway
596            frame = IPFrameGet(0);
597            if(frame == NULL)
598               return;
599            packetOut = frame->packet;
600            memset(packetOut, 0, 512);
601            memset(packetOut+ETHERNET_DEST, 0xff, 6);
602            memcpy(packetOut+ETHERNET_SOURCE, ethernetAddressPlasma, 6);
603            packetOut[ETHERNET_FRAME_TYPE] = 0x08;
604            packetOut[ETHERNET_FRAME_TYPE+1] = 0x06;
605            packetOut[ARP_HARD_TYPE+1] = 0x01;
606            packetOut[ARP_PROT_TYPE] = 0x08;
607            packetOut[ARP_HARD_SIZE] = 0x06;
608            packetOut[ARP_PROT_SIZE] = 0x04;
609            packetOut[ARP_OP+1] = 1;
610            memcpy(packetOut+ARP_ETHERNET_SENDER, ethernetAddressPlasma, 6);
611            memcpy(packetOut+ARP_IP_SENDER, ipAddressPlasma, 4);
612            memcpy(packetOut+ARP_IP_TARGET, ipAddressGateway, 4);
613            IPSendPacket(NULL, frame, 60);
614         }
615      }
616   }
617}
618
619
620uint32 IPAddressSelf(void)
621{
622   return (ipAddressPlasma[0] << 24) | (ipAddressPlasma[1] << 16) |
623          (ipAddressPlasma[2] << 8) | ipAddressPlasma[3];
624}
625
626
627static int IPProcessTCPPacket(IPFrame *frameIn)
628{
629   uint32 seq, ack;
630   int length, ip_length, bytes, rc=0, notify=0;
631   IPSocket *socket, *socketNew;
632   IPFrame *frameOut, *frame2, *framePrev;
633   uint8 *packet, *packetOut;
634
635   packet = frameIn->packet;
636   length = frameIn->length;
637
638   ip_length = (packet[IP_LENGTH] << 8) | packet[IP_LENGTH+1];
639   seq = (packet[TCP_SEQ] << 24) | (packet[TCP_SEQ+1] << 16) |
640         (packet[TCP_SEQ+2] << 8) | packet[TCP_SEQ+3];
641   ack = (packet[TCP_ACK] << 24) | (packet[TCP_ACK+1] << 16) |
642         (packet[TCP_ACK+2] << 8) | packet[TCP_ACK+3];
643
644   //Check if start of connection
645   if((packet[TCP_FLAGS] & (TCP_FLAGS_SYN | TCP_FLAGS_ACK)) == TCP_FLAGS_SYN)
646   {
647      if(IPVerbose)
648         printf("S");
649      //Check if duplicate SYN
650      for(socket = SocketHead; socket; socket = socket->next)
651      {
652         if(socket->state != IP_LISTEN &&
653            packet[IP_PROTOCOL] == socket->headerRcv[IP_PROTOCOL] &&
654            memcmp(packet+IP_SOURCE, socket->headerRcv+IP_SOURCE, 8) == 0 &&
655            memcmp(packet+TCP_SOURCE_PORT, socket->headerRcv+TCP_SOURCE_PORT, 4) == 0)
656         {
657            if(IPVerbose)
658               printf("s");
659            return 0;
660         }
661      }
662
663      //Find an open port
664      for(socket = SocketHead; socket; socket = socket->next)
665      {
666         if(socket->state == IP_LISTEN &&
667            packet[IP_PROTOCOL] == socket->headerRcv[IP_PROTOCOL] &&
668            memcmp(packet+TCP_DEST_PORT, socket->headerRcv+TCP_DEST_PORT, 2) == 0)
669         {
670            //Create a new socket
671            frameOut = IPFrameGet(FRAME_COUNT_SYNC);
672            if(frameOut == NULL)
673               return 0;
674            socketNew = (IPSocket*)malloc(sizeof(IPSocket));
675            if(socketNew == NULL)
676               return 0;
677            memcpy(socketNew, socket, sizeof(IPSocket));
678            socketNew->state = IP_TCP;
679            socketNew->timeout = SOCKET_TIMEOUT;
680            socketNew->ack = seq;
681            socketNew->ackProcessed = seq + 1;
682            socketNew->seq = socketNew->ack + 0x12345678;
683            socketNew->seqReceived = socketNew->seq;
684            socketNew->seqWindow = (packet[TCP_WINDOW_SIZE] << 8) | packet[TCP_WINDOW_SIZE+1];
685
686            //Send ACK
687            packetOut = frameOut->packet;
688            EthernetCreateResponse(packetOut, packet, length);
689            memcpy(socketNew->headerRcv, packet, TCP_SEQ);
690            memcpy(socketNew->headerSend, packetOut, TCP_SEQ);
691            packetOut[TCP_FLAGS] = TCP_FLAGS_SYN | TCP_FLAGS_ACK;
692            ++socketNew->ack;
693            packetOut[TCP_DATA] = 2; //maximum segment size = 536
694            packetOut[TCP_DATA+1] = 4;
695            packetOut[TCP_DATA+2] = 2;
696            packetOut[TCP_DATA+3] = 24;
697            TCPSendPacket(socketNew, frameOut, TCP_DATA+4);
698            ++socketNew->seq;
699
700            //Add socket to linked list
701            OS_MutexPend(IPMutex);
702            socketNew->next = SocketHead;
703            socketNew->prev = NULL;
704            if(SocketHead)
705               SocketHead->prev = socketNew;
706            SocketHead = socketNew;
707            OS_MutexPost(IPMutex);
708            if(socketNew->funcPtr)
709               OS_Job(socketNew->funcPtr, socketNew, 0, 0);
710            return 0;
711         }
712      }
713
714      //Send reset
715      frameOut = IPFrameGet(0);
716      if(frameOut == NULL)
717         return 0;
718      packetOut = frameOut->packet;
719      EthernetCreateResponse(packetOut, packet, TCP_DATA);
720      memset(packetOut+TCP_SEQ, 0, 4);
721      ++seq;
722      packetOut[TCP_ACK] = (uint8)(seq >> 24);
723      packetOut[TCP_ACK+1] = (uint8)(seq >> 16);
724      packetOut[TCP_ACK+2] = (uint8)(seq >> 8);
725      packetOut[TCP_ACK+3] = (uint8)seq;
726      packetOut[TCP_HEADER_LENGTH] = 0x50;
727      packetOut[TCP_FLAGS] = TCP_FLAGS_RST;
728      IPSendPacket(NULL, frameOut, TCP_DATA);
729      return 0;
730   }
731
732   //Find an open socket
733   for(socket = SocketHead; socket; socket = socket->next)
734   {
735      if(packet[IP_PROTOCOL] == socket->headerRcv[IP_PROTOCOL] &&
736         memcmp(packet+IP_SOURCE, socket->headerRcv+IP_SOURCE, 8) == 0 &&
737         memcmp(packet+TCP_SOURCE_PORT, socket->headerRcv+TCP_SOURCE_PORT, 4) == 0)
738      {
739         break;
740      }
741   }
742   if(socket == NULL)
743   {
744      return 0;
745   }
746
747   //Determine window
748   socket->seqWindow = (packet[TCP_WINDOW_SIZE] << 8) | packet[TCP_WINDOW_SIZE+1];
749   bytes = ip_length - (TCP_DATA - IP_VERSION_LENGTH);
750
751   //Check if packets can be removed from retransmition list
752   if(packet[TCP_FLAGS] & TCP_FLAGS_ACK)
753   {
754      if(ack != socket->seqReceived)
755      {
756         OS_MutexPend(IPMutex);
757         for(frame2 = FrameResendHead; frame2; )
758         {
759            framePrev = frame2;
760            frame2 = frame2->next;
761            if(framePrev->socket == socket && (int)(ack - framePrev->seqEnd) >= 0)
762            {
763               //Remove packet from retransmition queue
764               if(socket->timeout)
765                  socket->timeout = socket->timeoutReset;
766               FrameRemove(&FrameResendHead, &FrameResendTail, framePrev);
767               FrameFree(framePrev);
768            }
769         }
770         OS_MutexPost(IPMutex);
771         socket->seqReceived = ack;
772         socket->resentDone = 0;
773      }
774      else if(ack == socket->seqReceived && bytes == 0 &&
775         (packet[TCP_FLAGS] & (TCP_FLAGS_RST | TCP_FLAGS_FIN)) == 0 &&
776         socket->resentDone == 0)
777      {
778         //Detected that packet was lost, resend all
779         if(IPVerbose)
780            printf("A");
781         OS_MutexPend(IPMutex);
782         for(frame2 = FrameResendHead; frame2; )
783         {
784            framePrev = frame2;
785            frame2 = frame2->next;
786            if(framePrev->socket == socket)
787            {
788               //Remove packet from retransmition queue
789               FrameRemove(&FrameResendHead, &FrameResendTail, framePrev);
790               IPSendFrame(framePrev);
791            }
792         }
793         OS_MutexPost(IPMutex);
794         socket->resentDone = 1;
795      }
796   }
797
798   //Check if SYN/ACK
799   if((packet[TCP_FLAGS] & (TCP_FLAGS_SYN | TCP_FLAGS_ACK)) ==
800      (TCP_FLAGS_SYN | TCP_FLAGS_ACK))
801   {
802      //Ack SYN/ACK
803      socket->ack = seq + 1;
804      socket->ackProcessed = seq + 1;
805      frameOut = IPFrameGet(FRAME_COUNT_SEND);
806      if(frameOut)
807      {
808         frameOut->packet[TCP_FLAGS] = TCP_FLAGS_ACK;
809         TCPSendPacket(socket, frameOut, TCP_DATA);
810      }
811      if(socket->funcPtr)
812         OS_Job(socket->funcPtr, socket, 0, 0);
813      return 0;
814   }
815   if(packet[TCP_HEADER_LENGTH] != 0x50)
816   {
817      if(IPVerbose)
818         printf("length error\n");
819      return 0;
820   }
821
822   //Check if RST flag set
823   if(packet[TCP_FLAGS] & TCP_FLAGS_RST)
824   {
825      notify = 1;
826      if(socket->state == IP_FIN_SERVER)
827         IPClose2(socket);
828      else if(socket->state == IP_TCP)
829         socket->state = IP_FIN_CLIENT;
830   }
831   //Copy packet into socket
832   else if(socket->ack == seq && bytes > 0)
833   {
834      //Insert packet into socket linked list
835      notify = 1;
836      if(socket->timeout)
837         socket->timeout = socket->timeoutReset;
838      if(IPVerbose)
839         printf("D");
840      if(frameIn->length > ip_length + IP_VERSION_LENGTH)
841         frameIn->length = (uint16)(ip_length + IP_VERSION_LENGTH);
842      FrameInsert(&socket->frameReadHead, &socket->frameReadTail, frameIn);
843      socket->ack += bytes;
844
845      //Ack data
846      frameOut = IPFrameGet(FRAME_COUNT_SEND);
847      if(frameOut)
848      {
849         frameOut->packet[TCP_FLAGS] = TCP_FLAGS_ACK;
850         TCPSendPacket(socket, frameOut, TCP_DATA);
851      }
852
853      //Using frame
854      rc = 1;
855   }
856   else if(bytes)
857   {
858      //Ack with current offset since data missing
859      frameOut = IPFrameGet(FRAME_COUNT_SEND);
860      if(frameOut)
861      {
862         frameOut->packet[TCP_FLAGS] = TCP_FLAGS_ACK;
863         TCPSendPacket(socket, frameOut, TCP_DATA);
864      }
865   }
866
867   //Check if FIN flag set
868   if(packet[TCP_FLAGS] & TCP_FLAGS_FIN && socket->ack >= seq)
869   {
870      notify = 1;
871      socket->timeout = SOCKET_TIMEOUT;
872      if(IPVerbose)
873         printf("F");
874      frameOut = IPFrameGet(0);
875      if(frameOut == NULL)
876         return 0;
877      packetOut = frameOut->packet;
878      packetOut[TCP_FLAGS] = TCP_FLAGS_ACK;
879      ++socket->ack;
880      TCPSendPacket(socket, frameOut, TCP_DATA);
881      if(socket->state == IP_FIN_SERVER)
882         IPClose2(socket);
883      else if(socket->state == IP_TCP)
884         socket->state = IP_FIN_CLIENT;
885   }
886
887   //Notify application
888   if(socket->funcPtr && notify)
889      OS_Job(socket->funcPtr, socket, 0, 0);
890   return rc;
891}
892
893
894int IPProcessEthernetPacket(IPFrame *frameIn, int length)
895{
896   int ip_length, rc;
897   IPSocket *socket;
898   IPFrame *frameOut;
899   uint8 *packet, *packetOut;
900
901   packet = frameIn->packet;
902   frameIn->length = (uint16)length;
903
904   if(packet[ETHERNET_FRAME_TYPE] != 0x08 || frameIn->length > PACKET_SIZE)
905      return 0; //wrong ethernet type, packet not used
906
907   //ARP?
908   if(packet[ETHERNET_FRAME_TYPE+1] == 0x06)
909   {
910      //Check if ARP reply
911      if(memcmp(packet+ETHERNET_DEST, ethernetAddressPlasma, 6) == 0 &&
912         packet[ARP_OP+1] == 2 && memcmp(packet+ARP_IP_SENDER, ipAddressGateway, 4) == 0)
913      {
914         //Found MAC address for gateway
915         memcpy(ethernetAddressGateway, packet+ARP_ETHERNET_SENDER, 6);
916         return 0;
917      }
918
919      //Check if ARP request
920      if(packet[ARP_OP] != 0 || packet[ARP_OP+1] != 1 ||
921         memcmp(packet+ARP_IP_TARGET, ipAddressPlasma, 4))
922         return 0;
923      //Create ARP response
924      frameOut = IPFrameGet(0);
925      if(frameOut == NULL)
926         return 0;
927      packetOut = frameOut->packet;
928      memcpy(packetOut, packet, frameIn->length);
929      memcpy(packetOut+ETHERNET_DEST, packet+ETHERNET_SOURCE, 6);
930      memcpy(packetOut+ETHERNET_SOURCE, ethernetAddressPlasma, 6);
931      packetOut[ARP_OP+1] = 2; //ARP reply
932      memcpy(packetOut+ARP_ETHERNET_SENDER, ethernetAddressPlasma, 6);
933      memcpy(packetOut+ARP_IP_SENDER, packet+ARP_IP_TARGET, 4);
934      memcpy(packetOut+ARP_ETHERNET_TARGET, packet+ARP_ETHERNET_SENDER, 6);
935      memcpy(packetOut+ARP_IP_TARGET, packet+ARP_IP_SENDER, 4);
936      IPSendPacket(NULL, frameOut, frameIn->length);
937      return 0;
938   }
939
940   //Check if proper type of packet
941   ip_length = (packet[IP_LENGTH] << 8) | packet[IP_LENGTH+1];
942   if(frameIn->length < UDP_DATA || ip_length > frameIn->length - IP_VERSION_LENGTH)
943      return 0;
944   if(packet[ETHERNET_FRAME_TYPE+1] != 0x00 ||
945      packet[IP_VERSION_LENGTH] != 0x45)
946      return 0;
947
948   //Check if DHCP reply
949   if(packet[IP_PROTOCOL] == 0x11 &&
950      packet[UDP_SOURCE_PORT] == 0 && packet[UDP_SOURCE_PORT+1] == 67 &&
951      packet[UDP_DEST_PORT] == 0 && packet[UDP_DEST_PORT+1] == 68)
952   {
953      IPDhcp(packet, frameIn->length, 2); //DHCP reply
954      return 0;
955   }
956
957   //Check if correct destination address
958   if(memcmp(packet+ETHERNET_DEST, ethernetAddressPlasma, 6) ||
959      memcmp(packet+IP_DEST, ipAddressPlasma, 4))
960      return 0;
961   rc = EthernetVerifyChecksums(packet, frameIn->length);
962#ifndef WIN32
963   if(rc && FrameSendFunc)
964   {
965      printf("C ");
966      return 0;
967   }
968#endif
969
970   //PING request?
971   if(packet[IP_PROTOCOL] == 1)
972   {
973      if(packet[PING_TYPE] == 0) //PING reply
974      {
975         for(socket = SocketHead; socket; socket = socket->next)
976         {
977            if(socket->state == IP_PING &&
978               memcmp(packet+IP_SOURCE, socket->headerSend+IP_DEST, 4) == 0)
979            {
980               OS_Job(socket->funcPtr, socket, 0, 0);
981               return 0;
982            }
983         }
984      }
985      if(packet[PING_TYPE] != 8)
986         return 0;
987      frameOut = IPFrameGet(FRAME_COUNT_SEND);
988      if(frameOut == NULL)
989         return 0;
990      packetOut = frameOut->packet;
991      EthernetCreateResponse(packetOut, packet, frameIn->length);
992      frameOut->packet[PING_TYPE] = 0; //PING reply
993      IPSendPacket(NULL, frameOut, frameIn->length);
994      return 0;
995   }
996
997   //TCP packet?
998   if(packet[IP_PROTOCOL] == 0x06)
999   {
1000      return IPProcessTCPPacket(frameIn);
1001   }
1002
1003   //UDP packet?
1004   if(packet[IP_PROTOCOL] == 0x11)
1005   {
1006      //Find open socket
1007      for(socket = SocketHead; socket; socket = socket->next)
1008      {
1009         if(packet[IP_PROTOCOL] == socket->headerRcv[IP_PROTOCOL] &&
1010            memcmp(packet+IP_SOURCE, socket->headerRcv+IP_SOURCE, 8) == 0 &&
1011            memcmp(packet+UDP_SOURCE_PORT, socket->headerRcv+UDP_SOURCE_PORT, 2) == 0)
1012         {
1013            break;
1014         }
1015      }
1016
1017      if(socket == NULL)
1018      {
1019         //Find listening socket
1020         for(socket = SocketHead; socket; socket = socket->next)
1021         {
1022            if(packet[IP_PROTOCOL] == socket->headerRcv[IP_PROTOCOL] &&
1023               memcmp(packet+UDP_DEST_PORT, socket->headerRcv+UDP_DEST_PORT, 2) == 0)
1024            {
1025               EthernetCreateResponse(socket->headerSend, packet, UDP_DATA);
1026               break;
1027            }
1028         }
1029      }
1030
1031      if(socket)
1032      {
1033         if(IPVerbose)
1034            printf("U");
1035         FrameInsert(&socket->frameReadHead, &socket->frameReadTail, frameIn);
1036         OS_Job(socket->funcPtr, socket, 0, 0);
1037         return 1;
1038      }
1039   }
1040   return 0;
1041}
1042
1043
1044#ifndef WIN32
1045static void IPMainThread(void *arg)
1046{
1047   uint32 message[4];
1048   int rc;
1049   IPFrame *frame, *frameOut=NULL;
1050   uint32 ticks, ticksLast;
1051   (void)arg;
1052
1053   ticksLast = OS_ThreadTime();
1054   memset(message, 0, sizeof(message));
1055
1056   for(;;)
1057   {
1058      Led(7, 0);
1059      rc = OS_MQueueGet(IPMQueue, message, 10);
1060      if(rc == 0)
1061      {
1062         frame = (IPFrame*)message[1];
1063         if(message[0] == 0) //frame received
1064         {
1065            Led(7, 1);
1066            frame->length = (uint16)message[2];
1067            rc = IPProcessEthernetPacket(frame, frame->length);
1068            if(rc == 0)
1069               FrameFree(frame);
1070         }
1071         else if(message[0] == 1) //frame sent
1072         {
1073            Led(7, 2);
1074            assert(frame == frameOut);
1075            IPFrameReschedule(frame);
1076            frameOut = NULL;
1077         }
1078         else if(message[0] == 2) //frame ready to send
1079         {
1080         }
1081      }
1082
1083      if(frameOut == NULL)
1084      {
1085         OS_MutexPend(IPMutex);
1086         frameOut = FrameSendTail;
1087         if(frameOut)
1088            FrameRemove(&FrameSendHead, &FrameSendTail, frameOut);
1089         OS_MutexPost(IPMutex);
1090         if(frameOut)
1091         {
1092            Led(7, 4);
1093            UartPacketSend(frameOut->packet, frameOut->length);
1094         }
1095      }
1096
1097      ticks = OS_ThreadTime();
1098      if(ticks - ticksLast > 100)
1099      {
1100         IPTick();
1101         ticksLast = ticks;
1102      }
1103   }
1104}
1105#endif
1106
1107
1108uint8 *MyPacketGet(void)
1109{
1110   return (uint8*)IPFrameGet(FRAME_COUNT_RCV);
1111}
1112
1113
1114//Set FrameSendFunction only if single threaded
1115void IPInit(IPFuncPtr frameSendFunction, uint8 macAddress[6], char name[6])
1116{
1117   int i;
1118   IPFrame *frame;
1119
1120   if(macAddress)
1121      memcpy(ethernetAddressPlasma, macAddress, 6);
1122   if(name)
1123      memcpy(dhcpOptions+18, name, 6);
1124   FrameSendFunc = frameSendFunction;
1125   IPMutex = OS_MutexCreate("IPSem");
1126   IPMQueue = OS_MQueueCreate("IPMQ", FRAME_COUNT*2, 32);
1127   for(i = 0; i < FRAME_COUNT; ++i)
1128   {
1129      frame = (IPFrame*)malloc(sizeof(IPFrame));
1130      memset(frame, 0, sizeof(IPFrame));
1131      frame->next = FrameFreeHead;
1132      frame->prev = NULL;
1133      FrameFreeHead = frame;
1134   }
1135   FrameFreeCount = FRAME_COUNT;
1136#ifndef WIN32
1137   UartPacketConfig(MyPacketGet, PACKET_SIZE, IPMQueue);
1138   if(frameSendFunction == NULL)
1139      IPThread = OS_ThreadCreate("TCP/IP", IPMainThread, NULL, 240, 6000);
1140#endif
1141   IPDhcp(NULL, 360, 1); //Send DHCP request
1142}
1143
1144
1145//To open a socket for listen set ipAddress to 0
1146IPSocket *IPOpen(IPMode_e mode, uint32 ipAddress, uint32 port, IPFuncPtr funcPtr)
1147{
1148   IPSocket *socket;
1149   uint8 *ptrSend, *ptrRcv;
1150   IPFrame *frame;
1151   static int portSource=0x1007;
1152
1153   socket = (IPSocket*)malloc(sizeof(IPSocket));
1154   if(socket == NULL)
1155      return socket;
1156   memset(socket, 0, sizeof(IPSocket));
1157   socket->prev = NULL;
1158   socket->state = IP_LISTEN;
1159   socket->timeout = 0;
1160   socket->timeoutReset = SOCKET_TIMEOUT;
1161   socket->frameReadHead = NULL;
1162   socket->frameReadTail = NULL;
1163   socket->readOffset = 0;
1164   socket->funcPtr = funcPtr;
1165   socket->userData = 0;
1166   socket->userFunc = NULL;
1167   socket->userPtr = NULL;
1168   socket->seqWindow = 2048;
1169   ptrSend = socket->headerSend;
1170   ptrRcv = socket->headerRcv;
1171
1172   if(ipAddress == 0)
1173   {
1174      //Setup listing port
1175      socket->headerRcv[TCP_DEST_PORT] = (uint8)(port >> 8);
1176      socket->headerRcv[TCP_DEST_PORT+1] = (uint8)port;
1177   }
1178   else
1179   {
1180      //Setup sending packet
1181      memset(ptrSend, 0, UDP_LENGTH);
1182      memset(ptrRcv, 0, UDP_LENGTH);
1183
1184      //Setup Ethernet
1185      if(ipAddress != IPAddressSelf())
1186         memcpy(ptrSend+ETHERNET_DEST, ethernetAddressGateway, 6);
1187      else
1188         memcpy(ptrSend+ETHERNET_DEST, ethernetAddressPlasma, 6);
1189      memcpy(ptrSend+ETHERNET_SOURCE, ethernetAddressPlasma, 6);
1190      ptrSend[ETHERNET_FRAME_TYPE] = 0x08;
1191
1192      //Setup IP
1193      ptrSend[IP_VERSION_LENGTH] = 0x45;
1194      ptrSend[IP_TIME_TO_LIVE] = 0x80;
1195
1196      //Setup IP addresses
1197      memcpy(ptrSend+IP_SOURCE, ipAddressPlasma, 4);
1198      ptrSend[IP_DEST] = (uint8)(ipAddress >> 24);
1199      ptrSend[IP_DEST+1] = (uint8)(ipAddress >> 16);
1200      ptrSend[IP_DEST+2] = (uint8)(ipAddress >> 8);
1201      ptrSend[IP_DEST+3] = (uint8)ipAddress;
1202      ptrRcv[IP_SOURCE] = (uint8)(ipAddress >> 24);
1203      ptrRcv[IP_SOURCE+1] = (uint8)(ipAddress >> 16);
1204      ptrRcv[IP_SOURCE+2] = (uint8)(ipAddress >> 8);
1205      ptrRcv[IP_SOURCE+3] = (uint8)ipAddress;
1206      memcpy(ptrRcv+IP_DEST, ipAddressPlasma, 4);
1207
1208      //Setup ports
1209      ptrSend[TCP_SOURCE_PORT] = (uint8)(portSource >> 8);
1210      ptrSend[TCP_SOURCE_PORT+1] = (uint8)portSource;
1211      ptrSend[TCP_DEST_PORT] = (uint8)(port >> 8);
1212      ptrSend[TCP_DEST_PORT+1] = (uint8)port;
1213      ptrRcv[TCP_SOURCE_PORT] = (uint8)(port >> 8);
1214      ptrRcv[TCP_SOURCE_PORT+1] = (uint8)port;
1215      ptrRcv[TCP_DEST_PORT] = (uint8)(portSource >> 8);
1216      ptrRcv[TCP_DEST_PORT+1] = (uint8)portSource;
1217      ++portSource;
1218   }
1219
1220   if(mode == IP_MODE_TCP)
1221   {
1222      if(ipAddress)
1223         socket->state = IP_TCP;
1224      else
1225         socket->state = IP_LISTEN;
1226      ptrSend[IP_PROTOCOL] = 0x06; //TCP
1227      ptrRcv[IP_PROTOCOL] = 0x06;
1228   }
1229   else if(mode == IP_MODE_UDP)
1230   {
1231      socket->state = IP_UDP;
1232      ptrSend[IP_PROTOCOL] = 0x11; //UDP
1233      ptrRcv[IP_PROTOCOL] = 0x11;
1234   }
1235   else if(mode == IP_MODE_PING)
1236   {
1237      socket->state = IP_PING;
1238      ptrSend[IP_PROTOCOL] = 0x01; //PING
1239      memset(ptrSend+PING_TYPE, 0, 8);
1240      ptrSend[PING_TYPE] = 8; //SEND
1241   }
1242
1243   //Add socket to linked list
1244   OS_MutexPend(IPMutex);
1245   socket->next = SocketHead;
1246   socket->prev = NULL;
1247   if(SocketHead)
1248      SocketHead->prev = socket;
1249   SocketHead = socket;
1250   OS_MutexPost(IPMutex);
1251
1252   if(mode == IP_MODE_TCP && ipAddress)
1253   {
1254      //Send TCP SYN
1255      socket->seq = 0x01234567;
1256      frame = IPFrameGet(0);
1257      if(frame)
1258      {
1259         frame->packet[TCP_FLAGS] = TCP_FLAGS_SYN;
1260         frame->packet[TCP_DATA] = 2; //maximum segment size = 536
1261         frame->packet[TCP_DATA+1] = 4;
1262         frame->packet[TCP_DATA+2] = 2;
1263         frame->packet[TCP_DATA+3] = 24;
1264         TCPSendPacket(socket, frame, TCP_DATA+4);
1265         ++socket->seq;
1266      }
1267   }
1268   return socket;
1269}
1270
1271
1272void IPWriteFlush(IPSocket *socket)
1273{
1274   uint8 *packetOut;
1275   if(socket->frameSend && socket->state != IP_UDP &&
1276      socket->state != IP_PING)
1277   {
1278      packetOut = socket->frameSend->packet;
1279      packetOut[TCP_FLAGS] = TCP_FLAGS_ACK | TCP_FLAGS_PSH;
1280      TCPSendPacket(socket, socket->frameSend, TCP_DATA + socket->sendOffset);
1281      socket->seq += socket->sendOffset;
1282      socket->frameSend = NULL;
1283      socket->sendOffset = 0;
1284   }
1285}
1286
1287
1288uint32 IPWrite(IPSocket *socket, const uint8 *buf, uint32 length)
1289{
1290   IPFrame *frameOut;
1291   uint8 *packetOut;
1292   uint32 bytes, count=0, tries=0;
1293   int offset;
1294   OS_Thread_t *self;
1295
1296   if(socket->timeout)
1297      socket->timeout = socket->timeoutReset;
1298
1299#ifdef INCLUDE_FILESYS
1300   if(socket->fileOut) //override stdout
1301      return fwrite((char*)buf, 1, length, socket->fileOut);
1302#endif
1303
1304   //printf("IPWrite(0x%x, %d)", Socket, Length);
1305   self = OS_ThreadSelf();
1306   while(length)
1307   {
1308      //Rate limit output
1309      if(socket->seq - socket->seqReceived >= SEND_WINDOW)
1310      {
1311         //printf("l(%d,%d,%d) ", socket->seq - socket->seqReceived, socket->seq, socket->seqReceived);
1312         if(self != IPThread && ++tries < 200)
1313         {
1314            OS_ThreadSleep(1);
1315            continue;
1316         }
1317      }
1318      tries = 0;
1319      while(socket->frameSend == NULL)
1320      {
1321         socket->frameSend = IPFrameGet(FRAME_COUNT_SEND);
1322         socket->sendOffset = 0;
1323         if(socket->frameSend == NULL)
1324         {
1325            //printf("L");
1326            if(self == IPThread || ++tries > 200)
1327               break;
1328            else
1329               OS_ThreadSleep(1);
1330         }
1331      }
1332      frameOut = socket->frameSend;
1333      offset = socket->sendOffset;
1334      if(frameOut == NULL)
1335         break;
1336      packetOut = frameOut->packet;
1337
1338      if(socket->state == IP_PING)
1339      {
1340         bytes = length;
1341         memcpy(packetOut, socket->headerSend, PING_DATA);
1342         memcpy(packetOut+PING_DATA, buf, bytes);
1343         IPSendPacket(socket, socket->frameSend, PING_DATA + bytes);
1344         socket->frameSend = NULL;
1345      }
1346      else if(socket->state != IP_UDP)
1347      {
1348         bytes = 512 - offset;
1349         if(bytes > length)
1350            bytes = length;
1351         socket->sendOffset += bytes;
1352         memcpy(packetOut+TCP_DATA+offset, buf, bytes);
1353         if(socket->sendOffset >= 512)
1354            IPWriteFlush(socket);
1355         //if(Socket->seq - Socket->seqReceived > Socket->seqWindow)
1356         //{
1357         // printf("W");
1358         // OS_ThreadSleep(10);
1359         //}
1360      }
1361      else //UDP
1362      {
1363         bytes = length;
1364         memcpy(packetOut+UDP_DATA+offset, buf, bytes);
1365         memcpy(packetOut, socket->headerSend, UDP_LENGTH);
1366         IPSendPacket(socket, socket->frameSend, UDP_DATA + bytes);
1367         socket->frameSend = NULL;
1368      }
1369      count += bytes;
1370      buf += bytes;
1371      length -= bytes;
1372   }
1373   return count;
1374}
1375
1376
1377uint32 IPRead(IPSocket *socket, uint8 *buf, uint32 length)
1378{
1379   IPFrame *frame, *frame2;
1380   int count=0, bytes, offset;
1381
1382#ifdef INCLUDE_FILESYS
1383   if(socket->fileIn) //override stdin
1384   {
1385      bytes = fread(buf, 1, 1, socket->fileIn);
1386      if(bytes == 0)
1387      {
1388         buf[0] = 0;
1389         fclose(socket->fileIn);
1390         socket->fileIn = NULL;
1391         bytes = 1;
1392      }
1393      return bytes;
1394   }
1395#endif
1396
1397   if(socket->state == IP_UDP)
1398      offset = UDP_DATA;
1399   else
1400      offset = TCP_DATA;
1401
1402   OS_MutexPend(IPMutex);
1403   for(frame = socket->frameReadTail; length && frame; )
1404   {
1405      bytes = frame->length - offset - socket->readOffset;
1406      if(bytes > (int)length)
1407         bytes = length;
1408      memcpy(buf, frame->packet + offset + socket->readOffset, bytes);
1409      buf += bytes;
1410      socket->readOffset += bytes;
1411      length -= bytes;
1412      count += bytes;
1413
1414      //Check if done with packet
1415      frame2 = frame;
1416      frame = frame->prev;
1417      if(socket->readOffset == frame2->length - offset)
1418      {
1419         //Remove packet from socket linked list
1420         socket->readOffset = 0;
1421         FrameRemove(&socket->frameReadHead, &socket->frameReadTail, frame2);
1422         socket->ackProcessed += frame2->length - offset;
1423         if(socket->state == IP_TCP &&
1424            socket->ack - socket->ackProcessed > RECEIVE_WINDOW - 2048)
1425         {
1426            //Update receive window for flow control
1427            frame2->packet[TCP_FLAGS] = TCP_FLAGS_ACK;
1428            TCPSendPacket(socket, frame2, TCP_DATA);
1429         }
1430         else
1431            FrameFree(frame2);
1432      }
1433   }
1434   OS_MutexPost(IPMutex);
1435   return count;
1436}
1437
1438
1439static void IPClose2(IPSocket *socket)
1440{
1441   IPFrame *frame, *framePrev;
1442
1443   OS_MutexPend(IPMutex);
1444
1445   //Mark packets as don't retransmit
1446   for(frame = FrameSendHead; frame; frame = frame->next)
1447   {
1448      if(frame->socket == socket)
1449         frame->socket = NULL;
1450   }
1451
1452   //Remove packets from retransmision list
1453   for(frame = FrameResendHead; frame; )
1454   {
1455      framePrev = frame;
1456      frame = frame->next;
1457      if(framePrev->socket == socket)
1458      {
1459         FrameRemove(&FrameResendHead, &FrameResendTail, framePrev);
1460         FrameFree(framePrev);
1461      }
1462   }
1463
1464   //Remove packets from socket read linked list
1465   for(frame = socket->frameReadHead; frame; )
1466   {
1467      framePrev = frame;
1468      frame = frame->next;
1469      FrameRemove(&socket->frameReadHead, &socket->frameReadTail, framePrev);
1470      FrameFree(framePrev);
1471   }
1472
1473   //Remove socket
1474   if(socket->state == IP_CLOSED || socket->state <= IP_UDP)
1475   {
1476      if(socket->prev == NULL)
1477         SocketHead = socket->next;
1478      else
1479         socket->prev->next = socket->next;
1480      if(socket->next)
1481         socket->next->prev = socket->prev;
1482      free(socket);
1483   }
1484   else
1485   {
1486      //Give application 10 seconds to stop using socket
1487      if(socket->state > IP_UDP)
1488         socket->state = IP_CLOSED;
1489      socket->timeout = 10;
1490   }
1491   OS_MutexPost(IPMutex);
1492}
1493
1494
1495void IPClose(IPSocket *socket)
1496{
1497   IPFrame *frameOut;
1498
1499   IPWriteFlush(socket);
1500   if(socket->state <= IP_UDP)
1501   {
1502      IPClose2(socket);
1503      return;
1504   }
1505   frameOut = IPFrameGet(0);
1506   if(frameOut == NULL)
1507      return;
1508   frameOut->packet[TCP_FLAGS] = TCP_FLAGS_FIN | TCP_FLAGS_ACK;
1509   TCPSendPacket(socket, frameOut, TCP_DATA);
1510   ++socket->seq;
1511   if(socket->state == IP_FIN_CLIENT)
1512      IPClose2(socket);
1513   else
1514      socket->state = IP_FIN_SERVER;
1515}
1516
1517
1518void IPPrintf(IPSocket *socket, char *message,
1519              int arg0, int arg1, int arg2, int arg3)
1520{
1521   char buf[500];
1522   if(socket == NULL)
1523   {
1524      printf(message, arg0, arg1, arg2, arg3);
1525      return;
1526   }
1527   if(strcmp(message, "%s") == 0)
1528      IPWrite(socket, (uint8*)arg0, (int)strlen((char*)arg0));
1529   else
1530   {
1531      sprintf(buf, message, arg0, arg1, arg2, arg3, 0, 0, 0, 0);
1532      IPWrite(socket, (uint8*)buf, (int)strlen(buf));
1533   }
1534   if(socket->dontFlush == 0 || strstr(message, "\n"))
1535      IPWriteFlush(socket);
1536}
1537
1538
1539void IPTick(void)
1540{
1541   IPFrame *frame, *frame2;
1542   IPSocket *socket, *socket2;
1543   unsigned long ticks;
1544   static unsigned long ticksPrev=0, ticksPrev2=0;
1545
1546   ticks = OS_ThreadTime();
1547#ifdef WIN32
1548   ticks = ticksPrev + 100;
1549#endif
1550   if(ticks - ticksPrev >= 95)
1551   {
1552      if(IPVerbose && (Seconds % 60) == 0)
1553      {
1554         if(FrameFreeCount >= FRAME_COUNT-1)
1555            printf("T");
1556         else
1557            printf("T(%d)", FrameFreeCount);
1558      }
1559      ++Seconds;
1560      if(--DhcpRetrySeconds <= 0)
1561         IPDhcp(NULL, 400, 1); //DHCP request
1562   }
1563
1564   OS_MutexPend(IPMutex);
1565
1566   //Retransmit timeout packets
1567   for(frame = FrameResendHead; frame; )
1568   {
1569      frame2 = frame;
1570      frame = frame->next;
1571      frame2->timeout = (short)(frame2->timeout - (ticks - ticksPrev2));
1572      if(--frame2->timeout <= 0)
1573      {
1574         if(IPVerbose)
1575            printf("r");
1576         FrameRemove(&FrameResendHead, &FrameResendTail, frame2);
1577         IPSendFrame(frame2);
1578      }
1579   }
1580
1581   if(ticks - ticksPrev >= 95)
1582   {
1583      //Close timed out sockets
1584      for(socket = SocketHead; socket; )
1585      {
1586         socket2 = socket;
1587         socket = socket->next;
1588         if(socket2->timeout && --socket2->timeout == 0)
1589         {
1590            socket2->timeout = 10;
1591            if(IPVerbose && socket2->state != IP_CLOSED &&
1592                            socket2->state != IP_FIN_SERVER)
1593               printf("t(%d,%d)", socket2->state, FrameFreeCount);
1594            if(socket2->state == IP_TCP)
1595               IPClose(socket2);
1596            else if(socket2->state == IP_FIN_CLIENT)
1597               IPClose(socket2);
1598            else
1599               IPClose2(socket2);
1600         }
1601      }
1602      ticksPrev = ticks;
1603   }
1604   OS_MutexPost(IPMutex);
1605   ticksPrev2 = ticks;
1606}
1607
1608
1609static void DnsCallback(IPSocket *socket)
1610{
1611   uint8 buf[200], *ptr;
1612   uint32 ipAddress;
1613   int bytes;
1614
1615   memset(buf, 0, sizeof(buf));
1616   bytes = IPRead(socket, buf, sizeof(buf));
1617   if(buf[DNS_NUM_ANSWERS_RR+1])
1618   {
1619      for(ptr = buf + DNS_QUESTIONS; ptr + 14 <= buf + bytes; ++ptr)
1620      {
1621         if(ptr[0] == 0 && ptr[1] == 1 && ptr[2] == 0 && ptr[3] == 1 &&
1622            ptr[8] == 0 && ptr[9] == 4)
1623         {
1624            ipAddress = (ptr[10] << 24) | (ptr[11] << 16) | (ptr[12] << 8) | ptr[13];
1625            printf("ipAddress = %d.%d.%d.%d\n", ptr[10], ptr[11], ptr[12], ptr[13]);
1626            socket->userData = ipAddress;
1627            if(socket->userFunc)
1628            {
1629               socket->userFunc(socket, ipAddress, socket->userPtr);
1630            }
1631            break;
1632         }
1633      }
1634   }
1635   IPClose(socket);
1636}
1637
1638
1639void IPResolve(char *name, IPFuncPtr resolvedFunc, void *arg)
1640{
1641   uint8 buf[200], *ptr;
1642   int length, i;
1643   IPSocket *socket;
1644
1645   socket = IPOpen(IP_MODE_UDP, ipAddressDns, DNS_PORT, DnsCallback);
1646   memset(buf, 0, sizeof(buf));
1647   buf[DNS_ID+1] = 1;
1648   buf[DNS_FLAGS] = 1;
1649   buf[DNS_NUM_QUESTIONS+1] = 1;
1650
1651   //Setup name
1652   ptr = buf + DNS_QUESTIONS;
1653   strncpy((char*)ptr+1, name, 100);
1654   ptr[0] = 1;
1655   while(ptr[0])
1656   {
1657      for(i = 0; i < 100; ++i)
1658      {
1659         if(ptr[i+1] == '.' || ptr[i+1] == 0)
1660         {
1661            ptr[0] = (uint8)i;
1662            ptr += i+1;
1663            break;
1664         }
1665      }
1666   }
1667   ++ptr;
1668   ptr[1] = DNS_QUERY_TYPE_IP;
1669   ptr[3] = DNS_QUERY_CLASS;
1670   length = (int)(ptr - buf) + 4;
1671   if(length < 60)
1672      length = 60;
1673
1674   socket->userFunc = (IPFuncPtr)resolvedFunc;
1675   socket->userPtr = arg;
1676   socket->userData = 0;
1677   IPWrite(socket, buf, length);
1678}
1679
plasma/kernel/tcpip.h
1/*--------------------------------------------------------------------
2 * TITLE: Plasma TCP/IP Protocol Stack
3 * AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4 * DATE CREATED: 4/22/06
5 * FILENAME: tcpip.h
6 * PROJECT: Plasma CPU core
7 * COPYRIGHT: Software placed into the public domain by the author.
8 * Software 'as is' without warranty. Author liable for nothing.
9 * DESCRIPTION:
10 * Plasma TCP/IP Protocol Stack
11 *--------------------------------------------------------------------*/
12#ifndef __TCPIP_H__
13#define __TCPIP_H__
14#define PACKET_SIZE 600
15#define FRAME_COUNT 100
16#define FRAME_COUNT_SYNC 50
17#define FRAME_COUNT_SEND 10
18#define FRAME_COUNT_RCV 5
19#define RETRANSMIT_TIME 110
20#define SOCKET_TIMEOUT 12
21#define SEND_WINDOW 7000
22#define RECEIVE_WINDOW 5120
23
24typedef enum IPMode_e {
25   IP_MODE_UDP,
26   IP_MODE_TCP,
27   IP_MODE_PING
28} IPMode_e;
29
30typedef enum IPState_e {
31   IP_LISTEN,
32   IP_PING,
33   IP_UDP,
34   IP_SYN,
35   IP_TCP,
36   IP_FIN_CLIENT,
37   IP_FIN_SERVER,
38   IP_CLOSED
39} IPState_e;
40
41typedef void (*IPFuncPtr)();
42
43typedef struct IPFrame {
44   uint8 packet[PACKET_SIZE];
45   struct IPFrame *next, *prev;
46   struct IPSocket *socket;
47   uint32 seqEnd;
48   uint16 length;
49   short timeout;
50   uint8 state, retryCnt;
51} IPFrame;
52
53typedef struct IPSocket {
54   struct IPSocket *next, *prev;
55   IPState_e state;
56   uint32 seq;
57   uint32 seqReceived;
58   uint32 seqWindow;
59   uint32 ack;
60   uint32 ackProcessed;
61   uint32 timeout;
62   uint32 timeoutReset;
63   int resentDone;
64   int dontFlush;
65   uint8 headerSend[38];
66   uint8 headerRcv[38];
67   struct IPFrame *frameReadHead;
68   struct IPFrame *frameReadTail;
69   int readOffset;
70   struct IPFrame *frameSend;
71   int sendOffset;
72   void *fileOut;
73   void *fileIn;
74   IPFuncPtr funcPtr;
75   IPFuncPtr userFunc;
76   void *userPtr;
77   void *userPtr2;
78   uint32 userData;
79   uint32 userData2;
80} IPSocket;
81
82//ethernet.c
83void EthernetSendPacket(const unsigned char *packet, int length); //Windows
84void EthernetInit(unsigned char MacAddress[6]);
85int EthernetReceive(unsigned char *buffer, int length);
86void EthernetTransmit(unsigned char *buffer, int length);
87
88//tcpip.c
89void IPInit(IPFuncPtr frameSendFunction, uint8 macAddress[6], char name[6]);
90IPFrame *IPFrameGet(int freeCount);
91int IPProcessEthernetPacket(IPFrame *frameIn, int length);
92void IPTick(void);
93
94IPSocket *IPOpen(IPMode_e mode, uint32 ipAddress, uint32 port, IPFuncPtr funcPtr);
95void IPWriteFlush(IPSocket *socket);
96uint32 IPWrite(IPSocket *socket, const uint8 *buf, uint32 length);
97uint32 IPRead(IPSocket *socket, uint8 *buf, uint32 length);
98void IPClose(IPSocket *socket);
99#ifdef IPPRINTF
100void IPPrintf(IPSocket *socket, char *message, int arg0, int arg1, int arg2, int arg3);
101#else
102void IPPrintf(IPSocket *socket, char *message, ...);
103#endif
104void IPResolve(char *name, IPFuncPtr resolvedFunc, void *arg);
105uint32 IPAddressSelf(void);
106
107//http.c
108#define HTML_LENGTH_CALLBACK -2
109#define HTML_LENGTH_LIST_END -1
110typedef struct PageEntry_s {
111   const char *name;
112   int length;
113   const char *page;
114} PageEntry_t;
115void HttpInit(const PageEntry_t *Pages, int UseFiles);
116
117//html.c
118void HtmlInit(int UseFiles);
119
120//netutil.c
121void FtpdInit(int UseFiles);
122IPSocket *FtpTransfer(uint32 ip, char *user, char *passwd,
123                      char *filename, uint8 *buf, int size,
124                      int send, void (*callback)(uint8 *data, int size));
125void TftpdInit(void);
126IPSocket *TftpTransfer(uint32 ip, char *filename, uint8 *buffer, int size,
127                       void (*callback)(uint8 *data, int bytes));
128void ConsoleInit(void);
129void *IPNameValue(const char *name, void *value);
130
131#endif //__TCPIP_H__
plasma/kernel/uart.c
1/*--------------------------------------------------------------------
2 * TITLE: Plasma Uart Driver
3 * AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4 * DATE CREATED: 12/31/05
5 * FILENAME: uart.c
6 * PROJECT: Plasma CPU core
7 * COPYRIGHT: Software placed into the public domain by the author.
8 * Software 'as is' without warranty. Author liable for nothing.
9 * DESCRIPTION:
10 * Plasma Uart Driver
11 *--------------------------------------------------------------------*/
12#define NO_ELLIPSIS2
13#include "plasma.h"
14#include "rtos.h"
15
16#ifndef NO_PACKETS
17#define SUPPORT_DATA_PACKETS
18#endif
19
20#define BUFFER_WRITE_SIZE 128
21#define BUFFER_READ_SIZE 128
22#define BUFFER_PRINTF_SIZE 1024
23#undef UartPrintf
24
25void UartPrintfCritical(const char *format,
26                        int arg0, int arg1, int arg2, int arg3,
27                        int arg4, int arg5, int arg6, int arg7);
28
29typedef struct Buffer_s {
30   uint8 *data;
31   int size;
32   volatile int read, write;
33   volatile int pendingRead, pendingWrite;
34   OS_Semaphore_t *semaphoreRead, *semaphoreWrite;
35} Buffer_t;
36
37static Buffer_t *WriteBuffer, *ReadBuffer;
38static OS_Semaphore_t *SemaphoreUart;
39static char PrintfString[BUFFER_PRINTF_SIZE]; //Used in UartPrintf
40
41#ifdef SUPPORT_DATA_PACKETS
42//For packet processing [0xff lengthMSB lengthLSB checksum data]
43static PacketGetFunc_t UartPacketGet;
44static uint8 *PacketCurrent;
45static uint32 UartPacketSize;
46static uint32 UartPacketChecksum, Checksum;
47static OS_MQueue_t *UartPacketMQueue;
48static uint32 PacketBytes, PacketLength;
49static uint32 UartPacketOutLength, UartPacketOutByte;
50int CountOk, CountError;
51#endif
52static uint8 *UartPacketOut;
53
54
55/******************************************/
56Buffer_t *BufferCreate(int size)
57{
58   Buffer_t *buffer;
59   buffer = (Buffer_t*)OS_HeapMalloc(NULL, sizeof(Buffer_t) + size);
60   if(buffer == NULL)
61      return NULL;
62   buffer->data = (uint8*)(buffer + 1);
63   buffer->read = 0;
64   buffer->write = 0;
65   buffer->size = size;
66   buffer->pendingRead = 0;
67   buffer->pendingWrite = 0;
68   buffer->semaphoreRead = OS_SemaphoreCreate("BufferRead", 0);
69   buffer->semaphoreWrite = OS_SemaphoreCreate("BufferWrite", 0);
70   return buffer;
71}
72
73
74void BufferWrite(Buffer_t *buffer, int value, int pend)
75{
76   int writeNext;
77
78   writeNext = buffer->write + 1;
79   if(writeNext >= buffer->size)
80      writeNext = 0;
81
82   //Check if room for value
83   if(writeNext == buffer->read)
84   {
85      if(pend == 0)
86         return;
87      ++buffer->pendingWrite;
88      OS_SemaphorePend(buffer->semaphoreWrite, OS_WAIT_FOREVER);
89   }
90
91   buffer->data[buffer->write] = (uint8)value;
92   buffer->write = writeNext;
93   if(buffer->pendingRead)
94   {
95      --buffer->pendingRead;
96      OS_SemaphorePost(buffer->semaphoreRead);
97   }
98}
99
100
101int BufferRead(Buffer_t *buffer, int pend)
102{
103   int value;
104
105   //Check if empty buffer
106   if(buffer->read == buffer->write)
107   {
108      if(pend == 0)
109         return 0;
110      ++buffer->pendingRead;
111      OS_SemaphorePend(buffer->semaphoreRead, OS_WAIT_FOREVER);
112   }
113
114   value = buffer->data[buffer->read];
115   if(++buffer->read >= buffer->size)
116      buffer->read = 0;
117   if(buffer->pendingWrite)
118   {
119      --buffer->pendingWrite;
120      OS_SemaphorePost(buffer->semaphoreWrite);
121   }
122   return value;
123}
124
125
126/******************************************/
127#ifdef SUPPORT_DATA_PACKETS
128static void UartPacketRead(uint32 value)
129{
130   uint32 message[4];
131   if(PacketBytes == 0 && value == 0xff)
132   {
133      ++PacketBytes;
134   }
135   else if(PacketBytes == 1)
136   {
137      ++PacketBytes;
138      PacketLength = value << 8;
139   }
140   else if(PacketBytes == 2)
141   {
142      ++PacketBytes;
143      PacketLength |= value;
144      if(PacketLength <= UartPacketSize)
145      {
146         if(PacketCurrent == NULL)
147            PacketCurrent = UartPacketGet();
148      }
149      else
150      {
151         PacketBytes = 0;
152      }
153   }
154   else if(PacketBytes == 3)
155   {
156      ++PacketBytes;
157      UartPacketChecksum = value;
158      Checksum = 0;
159   }
160   else if(PacketBytes >= 4)
161   {
162      if(PacketCurrent)
163         PacketCurrent[PacketBytes - 4] = (uint8)value;
164      Checksum += value;
165      ++PacketBytes;
166      if(PacketBytes - 4 >= PacketLength)
167      {
168         if((uint8)Checksum == UartPacketChecksum)
169         {
170            //Notify thread that a packet has been received
171            ++CountOk;
172            message[0] = 0;
173            message[1] = (uint32)PacketCurrent;
174            message[2] = PacketLength;
175            if(PacketCurrent)
176               OS_MQueueSend(UartPacketMQueue, message);
177            PacketCurrent = NULL;
178         }
179         else
180         {
181            ++CountError;
182            //printf("E");
183         }
184         PacketBytes = 0;
185      }
186   }
187}
188
189
190static int UartPacketWrite(void)
191{
192   int value=0, i;
193   uint32 message[4];
194   if(UartPacketOut)
195   {
196      if(UartPacketOutByte == 0)
197      {
198         value = 0xff;
199         ++UartPacketOutByte;
200      }
201      else if(UartPacketOutByte == 1)
202      {
203         value = UartPacketOutLength >> 8;
204         ++UartPacketOutByte;
205      }
206      else if(UartPacketOutByte == 2)
207      {
208         value = (uint8)UartPacketOutLength;
209         ++UartPacketOutByte;
210      }
211      else if(UartPacketOutByte == 3)
212      {
213         value = 0;
214         for(i = 0; i < (int)UartPacketOutLength; ++i)
215            value += UartPacketOut[i];
216         value = (uint8)value;
217         ++UartPacketOutByte;
218      }
219      else
220      {
221         value = UartPacketOut[UartPacketOutByte - 4];
222         ++UartPacketOutByte;
223         if(UartPacketOutByte - 4 >= UartPacketOutLength)
224         {
225            //Notify thread that a packet has been sent
226            message[0] = 1;
227            message[1] = (uint32)UartPacketOut;
228            UartPacketOut = 0;
229            OS_MQueueSend(UartPacketMQueue, message);
230         }
231      }
232   }
233   return value;
234}
235#endif
236
237
238static void UartInterrupt(void *arg)
239{
240   uint32 status, value, count=0;
241   (void)arg;
242
243   status = OS_InterruptStatus();
244   while(status & IRQ_UART_READ_AVAILABLE)
245   {
246      value = MemoryRead(UART_READ);
247#ifdef SUPPORT_DATA_PACKETS
248      if(UartPacketGet && (value == 0xff || PacketBytes))
249         UartPacketRead(value);
250      else
251#endif
252      BufferWrite(ReadBuffer, value, 0);
253      status = OS_InterruptStatus();
254      if(++count >= 16)
255         break;
256   }
257   while(status & IRQ_UART_WRITE_AVAILABLE)
258   {
259#ifdef SUPPORT_DATA_PACKETS
260      if(UartPacketOut)
261      {
262         value = UartPacketWrite();
263         MemoryWrite(UART_WRITE, value);
264      } else
265#endif
266      if(WriteBuffer->read != WriteBuffer->write)
267      {
268         value = BufferRead(WriteBuffer, 0);
269         MemoryWrite(UART_WRITE, value);
270      }
271      else
272      {
273         OS_InterruptMaskClear(IRQ_UART_WRITE_AVAILABLE);
274         break;
275      }
276      status = OS_InterruptStatus();
277   }
278}
279
280
281void UartInit(void)
282{
283   uint32 mask;
284
285   SemaphoreUart = OS_SemaphoreCreate("Uart", 1);
286   WriteBuffer = BufferCreate(BUFFER_WRITE_SIZE);
287   ReadBuffer = BufferCreate(BUFFER_READ_SIZE);
288
289   mask = IRQ_UART_READ_AVAILABLE | IRQ_UART_WRITE_AVAILABLE;
290   OS_InterruptRegister(mask, UartInterrupt);
291   OS_InterruptMaskSet(IRQ_UART_READ_AVAILABLE);
292}
293
294
295void UartWrite(int ch)
296{
297   BufferWrite(WriteBuffer, ch, 1);
298   OS_InterruptMaskSet(IRQ_UART_WRITE_AVAILABLE);
299}
300
301
302uint8 UartRead(void)
303{
304   return (uint8)BufferRead(ReadBuffer, 1);
305}
306
307
308void UartWriteData(uint8 *data, int length)
309{
310   OS_SemaphorePend(SemaphoreUart, OS_WAIT_FOREVER);
311   while(length--)
312      UartWrite(*data++);
313   OS_SemaphorePost(SemaphoreUart);
314}
315
316
317void UartReadData(uint8 *data, int length)
318{
319   OS_SemaphorePend(SemaphoreUart, OS_WAIT_FOREVER);
320   while(length--)
321      *data++ = UartRead();
322   OS_SemaphorePost(SemaphoreUart);
323}
324
325
326void UartPrintf(const char *format,
327                int arg0, int arg1, int arg2, int arg3,
328                int arg4, int arg5, int arg6, int arg7)
329{
330   uint8 *ptr;
331#if 0
332   //Check for string "!m#~" to mask print statement
333   static char moduleLevel[26];
334   if(format[0] == '!' && format[3] == '~')
335   {
336      int level = format[2] - '5';
337      if('a' <= format[1] && format[1] <= 'z')
338      {
339         if(level < moduleLevel[format[1] - 'a'])
340            return;
341      }
342      else if('A' <= format[1] && format[1] <= 'Z')
343         moduleLevel[format[1] - 'A'] = (char)level;
344      format += 4;
345   }
346#endif
347   OS_SemaphorePend(SemaphoreUart, OS_WAIT_FOREVER);
348   sprintf(PrintfString, format, arg0, arg1, arg2, arg3,
349           arg4, arg5, arg6, arg7);
350   ptr = (uint8*)PrintfString;
351   while(*ptr)
352   {
353      if(*ptr == '\n')
354         UartWrite('\r');
355#ifdef SUPPORT_DATA_PACKETS
356      if(*ptr == 0xff)
357         *ptr = '@';
358#endif
359      UartWrite(*ptr++);
360   }
361   OS_SemaphorePost(SemaphoreUart);
362}
363
364
365void UartPrintfPoll(const char *format,
366                    int arg0, int arg1, int arg2, int arg3,
367                    int arg4, int arg5, int arg6, int arg7)
368{
369   uint8 *ptr;
370   uint32 state;
371
372   if(SemaphoreUart)
373      OS_SemaphorePend(SemaphoreUart, OS_WAIT_FOREVER);
374   sprintf(PrintfString, format, arg0, arg1, arg2, arg3,
375           arg4, arg5, arg6, arg7);
376   ptr = (uint8*)PrintfString;
377   while(*ptr)
378   {
379      while((MemoryRead(IRQ_STATUS) & IRQ_UART_WRITE_AVAILABLE) == 0)
380         ;
381      state = OS_CriticalBegin();
382      if((MemoryRead(IRQ_STATUS) & IRQ_UART_WRITE_AVAILABLE) &&
383         UartPacketOut == NULL)
384      {
385         MemoryWrite(UART_WRITE, *ptr++);
386      }
387      OS_CriticalEnd(state);
388   }
389   if(SemaphoreUart)
390      OS_SemaphorePost(SemaphoreUart);
391}
392
393
394void UartPrintfCritical(const char *format,
395                        int arg0, int arg1, int arg2, int arg3,
396                        int arg4, int arg5, int arg6, int arg7)
397{
398   uint8 *ptr;
399   uint32 state;
400
401   state = OS_CriticalBegin();
402   sprintf(PrintfString, format, arg0, arg1, arg2, arg3,
403           arg4, arg5, arg6, arg7);
404   ptr = (uint8*)PrintfString;
405   while(*ptr)
406   {
407      while((MemoryRead(IRQ_STATUS) & IRQ_UART_WRITE_AVAILABLE) == 0)
408         ;
409      MemoryWrite(UART_WRITE, *ptr++);
410#ifdef SUPPORT_DATA_PACKETS
411      if(UartPacketOut && UartPacketOutByte - 4 < UartPacketOutLength)
412      {
413         ++UartPacketOutByte;
414         --ptr;
415      }
416#endif
417   }
418   memset(PrintfString, 0, sizeof(PrintfString));
419   OS_CriticalEnd(state);
420}
421
422
423void UartPrintfNull(void)
424{
425}
426
427
428void UartScanf(const char *format,
429               int arg0, int arg1, int arg2, int arg3,
430               int arg4, int arg5, int arg6, int arg7)
431{
432   int index = 0, ch;
433   OS_SemaphorePend(SemaphoreUart, OS_WAIT_FOREVER);
434   for(;;)
435   {
436      ch = UartRead();
437      if(ch != '\b' || index)
438         UartWrite(ch);
439      if(ch == '\n' || ch == '\r')
440         break;
441      else if(ch == '\b')
442      {
443         if(index)
444         {
445            UartWrite(' ');
446            UartWrite(ch);
447            --index;
448         }
449      }
450      else if(index < sizeof(PrintfString))
451         PrintfString[index++] = (uint8)ch;
452   }
453   UartWrite('\n');
454   PrintfString[index] = 0;
455   sscanf(PrintfString, format, arg0, arg1, arg2, arg3,
456          arg4, arg5, arg6, arg7);
457   OS_SemaphorePost(SemaphoreUart);
458}
459
460
461#ifdef SUPPORT_DATA_PACKETS
462void UartPacketConfig(PacketGetFunc_t PacketGetFunc,
463                      int PacketSize,
464                      OS_MQueue_t *mQueue)
465{
466   UartPacketGet = PacketGetFunc;
467   UartPacketSize = PacketSize;
468   UartPacketMQueue = mQueue;
469}
470
471
472void UartPacketSend(uint8 *data, int bytes)
473{
474   UartPacketOutByte = 0;
475   UartPacketOutLength = bytes;
476   UartPacketOut = data;
477   OS_InterruptMaskSet(IRQ_UART_WRITE_AVAILABLE);
478}
479#else
480void UartPacketConfig(PacketGetFunc_t PacketGetFunc,
481                      int PacketSize,
482                      OS_MQueue_t *mQueue)
483{ (void)PacketGetFunc; (void)PacketSize; (void)mQueue; }
484
485
486void UartPacketSend(uint8 *data, int bytes)
487{ (void)data; (void)bytes; }
488#endif
489
490
491void Led(int mask, int value)
492{
493   mask &= 0xff;
494   MemoryWrite(GPIO0_CLEAR, mask); //clear
495   MemoryWrite(GPIO0_OUT, value & mask); //set LEDs
496}
497
498
499/******************************************/
500int puts(const char *string)
501{
502   uint8 *ptr;
503   OS_SemaphorePend(SemaphoreUart, OS_WAIT_FOREVER);
504   ptr = (uint8*)string;
505   while(*ptr)
506   {
507      if(*ptr == '\n')
508         UartWrite('\r');
509      UartWrite(*ptr++);
510   }
511   OS_SemaphorePost(SemaphoreUart);
512   return 0;
513}
514
515
516int getch(void)
517{
518   return BufferRead(ReadBuffer, 1);
519}
520
521
522int kbhit(void)
523{
524   return ReadBuffer->read != ReadBuffer->write;
525}
526
527
528/******************************************/
529#if 0
530int LogArray[100], LogIndex;
531void LogWrite(int a)
532{
533   if(LogIndex < sizeof(LogArray)/4)
534      LogArray[LogIndex++] = a;
535}
536
537void LogDump(void)
538{
539   int i;
540   for(i = 0; i < LogIndex; ++i)
541   {
542      if(LogArray[i] > 0xfff)
543         UartPrintfCritical("\n", 0,0,0,0,0,0,0,0);
544      UartPrintfCritical("0x%x ", LogArray[i], 0,0,0,0,0,0,0);
545   }
546   LogIndex = 0;
547}
548#endif
549
plasma/lib/crt0.S
1##################################################################
2# TITLE: Boot Up Code
3# AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4# DATE CREATED: 1/12/02
5# FILENAME: boot.asm
6# PROJECT: Plasma CPU core
7# COPYRIGHT: Software placed into the public domain by the author.
8# Software 'as is' without warranty. Author liable for nothing.
9# DESCRIPTION:
10# Initializes the stack pointer and jumps to main().
11##################################################################
12   #Reserve 512 bytes for stack
13   .comm InitStack, 512
14
15   .text
16   .align 2
17   .global entry
18   .ent entry
19entry:
20   .set noreorder
21
22   #These four instructions should be the first instructions.
23   #convert.exe previously initialized $gp, .sbss_start, .bss_end, $sp
24   la $gp, _gp #initialize global pointer
25   la $5, __bss_start #$5 = .sbss_start
26   la $4, _end #$2 = .bss_end
27   la $sp, InitStack+488 #initialize stack pointer
28
29$BSS_CLEAR:
30   sw $0, 0($5)
31   slt $3, $5, $4
32   bnez $3, $BSS_CLEAR
33   addiu $5, $5, 4
34
35   jal main
36   nop
37$L1:
38   j $L1
39
40   .end entry
41
42
43###################################################
44   #address 0x3c
45   .global interrupt_service_routine
46   .ent interrupt_service_routine
47interrupt_service_routine:
48   .set noreorder
49   .set noat
50
51   #Registers $26 and $27 are reserved for the OS
52   #Save all temporary registers
53   #Slots 0($29) through 12($29) reserved for saving a0-a3
54   addi $29, $29, -104 #adjust sp
55   sw $1, 16($29) #at
56   sw $2, 20($29) #v0
57   sw $3, 24($29) #v1
58   sw $4, 28($29) #a0
59   sw $5, 32($29) #a1
60   sw $6, 36($29) #a2
61   sw $7, 40($29) #a3
62   sw $8, 44($29) #t0
63   sw $9, 48($29) #t1
64   sw $10, 52($29) #t2
65   sw $11, 56($29) #t3
66   sw $12, 60($29) #t4
67   sw $13, 64($29) #t5
68   sw $14, 68($29) #t6
69   sw $15, 72($29) #t7
70   sw $24, 76($29) #t8
71   sw $25, 80($29) #t9
72   sw $31, 84($29) #lr
73   mfc0 $26, $14 #C0_EPC=14 (Exception PC)
74   addi $26, $26, -4 #Backup one opcode
75   sw $26, 88($29) #pc
76   mfhi $27
77   sw $27, 92($29) #hi
78   mflo $27
79   sw $27, 96($29) #lo
80
81   lui $6, 0x2000
82   lw $4, 0x20($6) #IRQ_STATUS
83   lw $6, 0x10($6) #IRQ_MASK
84   and $4, $4, $6
85   jal OS_InterruptServiceRoutine
86   addi $5, $29, 0
87
88   #Restore all temporary registers
89   lw $1, 16($29) #at
90   lw $2, 20($29) #v0
91   lw $3, 24($29) #v1
92   lw $4, 28($29) #a0
93   lw $5, 32($29) #a1
94   lw $6, 36($29) #a2
95   lw $7, 40($29) #a3
96   lw $8, 44($29) #t0
97   lw $9, 48($29) #t1
98   lw $10, 52($29) #t2
99   lw $11, 56($29) #t3
100   lw $12, 60($29) #t4
101   lw $13, 64($29) #t5
102   lw $14, 68($29) #t6
103   lw $15, 72($29) #t7
104   lw $24, 76($29) #t8
105   lw $25, 80($29) #t9
106   lw $31, 84($29) #lr
107   lw $26, 88($29) #pc
108   lw $27, 92($29) #hi
109   mthi $27
110   lw $27, 96($29) #lo
111   mtlo $27
112   addi $29, $29, 104 #adjust sp
113
114isr_return:
115   ori $27, $0, 0x1 #re-enable interrupts
116   jr $26
117   mtc0 $27, $12 #STATUS=1; enable interrupts
118
119   .end interrupt_service_routine
120   .set at
121
122
123###################################################
124   .global OS_AsmInterruptEnable
125   .ent OS_AsmInterruptEnable
126OS_AsmInterruptEnable:
127   .set noreorder
128   mfc0 $2, $12
129   jr $31
130   mtc0 $4, $12 #STATUS=1; enable interrupts
131   #nop
132   .set reorder
133   .end OS_AsmInterruptEnable
134
135
136###################################################
137   .global OS_AsmInterruptInit
138   .ent OS_AsmInterruptInit
139OS_AsmInterruptInit:
140   .set noreorder
141   #Patch interrupt vector to 0x1000003c
142   la $5, OS_AsmPatchValue
143   lw $6, 0($5)
144   sw $6, 0x3c($0)
145   lw $6, 4($5)
146   sw $6, 0x40($0)
147   lw $6, 8($5)
148   sw $6, 0x44($0)
149   lw $6, 12($5)
150   jr $31
151   sw $6, 0x48($0)
152
153OS_AsmPatchValue:
154   #Registers $26 and $27 are reserved for the OS
155   #Code to place at address 0x3c
156   lui $26, 0x1000
157   ori $26, $26, 0x3c
158   jr $26
159   nop
160
161   .set reorder
162   .end OS_AsmInterruptInit
163
164
165###################################################
166   .global setjmp
167   .ent setjmp
168setjmp:
169   .set noreorder
170   sw $16, 0($4) #s0
171   sw $17, 4($4) #s1
172   sw $18, 8($4) #s2
173   sw $19, 12($4) #s3
174   sw $20, 16($4) #s4
175   sw $21, 20($4) #s5
176   sw $22, 24($4) #s6
177   sw $23, 28($4) #s7
178   sw $30, 32($4) #s8
179   sw $28, 36($4) #gp
180   sw $29, 40($4) #sp
181   sw $31, 44($4) #lr
182   jr $31
183   ori $2, $0, 0
184
185   .set reorder
186   .end setjmp
187
188
189###################################################
190   .global longjmp
191   .ent longjmp
192longjmp:
193   .set noreorder
194   lw $16, 0($4) #s0
195   lw $17, 4($4) #s1
196   lw $18, 8($4) #s2
197   lw $19, 12($4) #s3
198   lw $20, 16($4) #s4
199   lw $21, 20($4) #s5
200   lw $22, 24($4) #s6
201   lw $23, 28($4) #s7
202   lw $30, 32($4) #s8
203   lw $28, 36($4) #gp
204   lw $29, 40($4) #sp
205   lw $31, 44($4) #lr
206   jr $31
207   ori $2, $5, 0
208
209   .set reorder
210   .end longjmp
211
212
213###################################################
214   .global OS_AsmMult
215   .ent OS_AsmMult
216OS_AsmMult:
217   .set noreorder
218   multu $4, $5
219   mflo $2
220   mfhi $4
221   jr $31
222   sw $4, 0($6)
223
224   .set reorder
225   .end OS_AsmMult
226
227
228###################################################
229   .global OS_Syscall
230   .ent OS_Syscall
231OS_Syscall:
232   .set noreorder
233   syscall 0
234   jr $31
235   nop
236   .set reorder
237   .end OS_Syscall
238
239
plasma/lib/ddr_init.c
1/*--------------------------------------------------------------------
2 * TITLE: Plasma DDR Initialization
3 * AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4 * DATE CREATED: 12/17/05
5 * FILENAME: ddr_init.c
6 * PROJECT: Plasma CPU core
7 * COPYRIGHT: Software placed into the public domain by the author.
8 * Software 'as is' without warranty. Author liable for nothing.
9 * DESCRIPTION:
10 * Plasma DDR Initialization
11 * Supports 64MB (512Mb) MT46V32M16 by default.
12 * For 32 MB and 128 MB DDR parts change AddressLines and Bank shift:
13 * For 32 MB change 13->12 and 11->10. MT46V16M16
14 * For 128 MB change 13->14 and 11->12. MT46V64M16
15 *--------------------------------------------------------------------*/
16#define DDR_BASE 0x10000000
17#define MemoryRead(A) (*(volatile int*)(A))
18#define MemoryWrite(A,V) *(volatile int*)(A)=(V)
19extern int putchar(int value);
20extern int puts(const char *string);
21extern void print_hex(unsigned long num);
22
23//SD_A <= address_reg(25 downto 13); --address row
24//SD_BA <= address_reg(12 downto 11); --bank_address
25//cmd := address_reg(6 downto 4); --bits RAS & CAS & WE
26int DdrInitData[] = {
27// AddressLines Bank Command
28   (0x000 << 13) | (0 << 11) | (7 << 4), //CKE=1; NOP="111"
29   (0x400 << 13) | (0 << 11) | (2 << 4), //A10=1; PRECHARGE ALL="010"
30//#ifndef DLL_DISABLE
31// (0x000 << 13) | (1 << 11) | (0 << 4), //enable DLL; BA="01"; LMR="000"
32//#else
33   (0x001 << 13) | (1 << 11) | (0 << 4), //disable DLL; BA="01"; LMR="000"
34//#endif
35   (0x121 << 13) | (0 << 11) | (0 << 4), //reset DLL, CL=2, BL=2; LMR="000"
36   (0x400 << 13) | (0 << 11) | (2 << 4), //A10=1; PRECHARGE ALL="010"
37   (0x000 << 13) | (0 << 11) | (1 << 4), //AUTO REFRESH="001"
38   (0x000 << 13) | (0 << 11) | (1 << 4), //AUTO REFRESH="001
39   (0x021 << 13) | (0 << 11) | (0 << 4) //clear DLL, CL=2, BL=2; LMR="000"
40};
41
42int DdrInit(void)
43{
44   int i, j, k=0;
45   for(i = 0; i < sizeof(DdrInitData)/sizeof(int); ++i)
46   {
47      MemoryWrite(DDR_BASE + DdrInitData[i], 0);
48      for(j = 0; j < 4; ++j)
49         ++k;
50   }
51   for(j = 0; j < 100; ++j)
52      ++k;
53   k += MemoryRead(DDR_BASE); //Enable DDR
54   return k;
55}
56
57#ifdef DDR_TEST_MAIN
58int main()
59{
60   volatile int *ptr = (int*)DDR_BASE;
61   int i;
62
63   DdrInit();
64
65   ptr[0] = 0x12345678;
66   if(ptr[0] != 0x12345678)
67      putchar('X');
68   for(i = 0; i < 10; ++i)
69   {
70      ptr[i] = i;
71   }
72
73   for(i = 0; i < 10; ++i)
74   {
75      if(ptr[i] != i)
76         putchar('A' + i);
77   }
78   *(unsigned char*)DDR_BASE = 0x23;
79   *(unsigned char*)(DDR_BASE+1) = 0x45;
80   *(unsigned char*)(DDR_BASE+2) = 0x67;
81   *(unsigned char*)(DDR_BASE+3) = 0x89;
82   if(ptr[0] != 0x23456789)
83      putchar('Y');
84   puts("\r\ndone\r\n");
85   return 0;
86}
87#endif
plasma/lib/no_os.c
1#include "plasma.h"
2
3#define MemoryRead(A) (*(volatile unsigned int*)(A))
4#define MemoryWrite(A,V) *(volatile unsigned int*)(A)=(V)
5
6int putchar(int value)
7{
8   while((MemoryRead(IRQ_STATUS) & IRQ_UART_WRITE_AVAILABLE) == 0)
9      ;
10   MemoryWrite(UART_WRITE, value);
11   return 0;
12}
13
14int puts(const char *string)
15{
16   while(*string)
17   {
18      if(*string == '\n')
19         putchar('\r');
20      putchar(*string++);
21   }
22   return 0;
23}
24
25void print_hex(unsigned long num)
26{
27   long i;
28   unsigned long j;
29   for(i = 28; i >= 0; i -= 4)
30   {
31      j = (num >> i) & 0xf;
32      if(j < 10)
33         putchar('0' + j);
34      else
35         putchar('a' - 10 + j);
36   }
37}
38
39void OS_InterruptServiceRoutine(unsigned int status)
40{
41   (void)status;
42   putchar('I');
43}
44
45int kbhit(void)
46{
47   return MemoryRead(IRQ_STATUS) & IRQ_UART_READ_AVAILABLE;
48}
49
50int getch(void)
51{
52   while(!kbhit()) ;
53   return MemoryRead(UART_READ);
54}
plasma/logic/Makefile
1DESIGN = plasma_3e
2PINS = $(DESIGN).ucf
3DEVICE = xc3s500e-fg320-4
4BGFLAGS = -g TdoPin:PULLNONE -g DonePin:PULLUP \
5                  -g CRC:enable -g StartUpClk:CCLK
6
7
8SIM_CMD = /opt/cad/modeltech/bin/vsim
9SIM_COMP_SCRIPT = simulation/$(DESIGN)_TB.do
10#SIM_INIT_SCRIPT = simulation/$(DESIGN)_init.do
11SIMGEN_OPTIONS = -p $(FPGA_ARCH) -lang $(LANGUAGE)
12
13SRC_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
14
15
16
17
18all: bits
19
20remake: clean-build all
21
22clean:
23    rm -rf *~ */*~ a.out *.log *.key *.edf *.ps trace.dat
24    rm -rf *.bit rm -rf simulation/work simulation/*wlf
25
26clean-build:
27    rm -rf build
28
29cleanall: clean
30    rm -rf build work $(DESIGN).bit
31
32bits: $(DESIGN).bit
33
34#
35# Synthesis
36#
37build/project.src:
38    @[ -d build ] || mkdir build
39    @rm -f $@
40    for i in $(SRC); do echo verilog work ../$$i >> $@; done
41    for i in $(SRC_HDL); do echo VHDL work ../$$i >> $@; done
42
43build/project.xst: build/project.src
44    echo "run" > $@
45    echo "-top $(DESIGN) " >> $@
46    echo "-p $(DEVICE)" >> $@
47    echo "-opt_mode Area" >> $@
48    echo "-opt_level 1" >> $@
49    echo "-ifn project.src" >> $@
50    echo "-ifmt mixed" >> $@
51    echo "-ofn project.ngc" >> $@
52    echo "-ofmt NGC" >> $@
53    echo "-rtlview yes" >> $@
54
55build/project.ngc: build/project.xst $(SRC)
56    cd build && xst -ifn project.xst -ofn project.log
57
58build/project.ngd: build/project.ngc $(PINS)
59    cd build && ngdbuild -p $(DEVICE) project.ngc -uc ../$(PINS)
60
61build/project.ncd: build/project.ngd
62    cd build && map -pr b -p $(DEVICE) project
63
64build/project_r.ncd: build/project.ncd
65    cd build && par -w project project_r.ncd
66
67build/project_r.twr: build/project_r.ncd
68    cd build && trce -v 25 project_r.ncd project.pcf
69
70$(DESIGN).bit: build/project_r.ncd build/project_r.twr
71    cd build && bitgen project_r.ncd -l -w $(BGFLAGS)
72    @mv -f build/project_r.bit $@
73upload: $(DESIGN).bit
74    LD_PRELOAD=/usr/lib/libusb-driver.so impact -batch prog.cmd
75
76sim:
77    cd simulation; $(SIM_CMD) -do $(DESIGN)_TB.do
78
plasma/logic/_impact.cmd
1setMode -bs
2setMode -bs
3setCable -port auto
4Identify
5identifyMPM
6assignFile -p 1 -file "/home/cain/Embedded/plasma/work/Example/logic/plasma_3e.bit"
7Program -p 1 -defaultVersion 0
8Program -p 1 -defaultVersion 0
9Program -p 1 -defaultVersion 0
10Program -p 1 -defaultVersion 0
11assignFile -p 1 -file "/home/cain/Embedded/plasma/work/Example/logic/plasma_3e.bit"
12Program -p 1 -defaultVersion 0
13Program -p 1 -defaultVersion 0
14Program -p 1 -defaultVersion 0
15saveProjectFile -file "/home/cain/Embedded/plasma/work/Example/logic/default.ipf"
plasma/logic/alu.vhd
1---------------------------------------------------------------------
2-- TITLE: Arithmetic Logic Unit
3-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4-- DATE CREATED: 2/8/01
5-- FILENAME: alu.vhd
6-- PROJECT: Plasma CPU core
7-- COPYRIGHT: Software placed into the public domain by the author.
8-- Software 'as is' without warranty. Author liable for nothing.
9-- DESCRIPTION:
10-- Implements the ALU.
11---------------------------------------------------------------------
12library ieee;
13use ieee.std_logic_1164.all;
14use work.mlite_pack.all;
15
16entity alu is
17   generic(alu_type : string := "DEFAULT");
18   port(a_in : in std_logic_vector(31 downto 0);
19        b_in : in std_logic_vector(31 downto 0);
20        alu_function : in alu_function_type;
21        c_alu : out std_logic_vector(31 downto 0));
22end; --alu
23
24architecture logic of alu is
25   signal do_add : std_logic;
26   signal sum : std_logic_vector(32 downto 0);
27   signal less_than : std_logic;
28begin
29
30   do_add <= '1' when alu_function = ALU_ADD else '0';
31   sum <= bv_adder(a_in, b_in, do_add);
32   less_than <= sum(32) when a_in(31) = b_in(31) or alu_function = ALU_LESS_THAN
33                else a_in(31);
34
35   GENERIC_ALU: if alu_type = "DEFAULT" generate
36      c_alu <= sum(31 downto 0) when alu_function=ALU_ADD or
37                                       alu_function=ALU_SUBTRACT else
38               ZERO(31 downto 1) & less_than when alu_function=ALU_LESS_THAN or
39                                alu_function=ALU_LESS_THAN_SIGNED else
40               a_in or b_in when alu_function=ALU_OR else
41               a_in and b_in when alu_function=ALU_AND else
42               a_in xor b_in when alu_function=ALU_XOR else
43               a_in nor b_in when alu_function=ALU_NOR else
44               ZERO;
45   end generate;
46
47   AREA_OPTIMIZED_ALU: if alu_type/="DEFAULT" generate
48      c_alu <= sum(31 downto 0) when alu_function=ALU_ADD or
49                                  alu_function=ALU_SUBTRACT else (others => 'Z');
50      c_alu <= ZERO(31 downto 1) & less_than when alu_function=ALU_LESS_THAN or
51                                  alu_function=ALU_LESS_THAN_SIGNED else
52                                          (others => 'Z');
53      c_alu <= a_in or b_in when alu_function=ALU_OR else (others => 'Z');
54      c_alu <= a_in and b_in when alu_function=ALU_AND else (others => 'Z');
55      c_alu <= a_in xor b_in when alu_function=ALU_XOR else (others => 'Z');
56      c_alu <= a_in nor b_in when alu_function=ALU_NOR else (others => 'Z');
57      c_alu <= ZERO when alu_function=ALU_NOTHING else (others => 'Z');
58   end generate;
59
60end; --architecture logic
61
plasma/logic/bus_mux.vhd
1---------------------------------------------------------------------
2-- TITLE: Bus Multiplexer / Signal Router
3-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4-- DATE CREATED: 2/8/01
5-- FILENAME: bus_mux.vhd
6-- PROJECT: Plasma CPU core
7-- COPYRIGHT: Software placed into the public domain by the author.
8-- Software 'as is' without warranty. Author liable for nothing.
9-- DESCRIPTION:
10-- This entity is the main signal router.
11-- It multiplexes signals from multiple sources to the correct location.
12-- The outputs are as follows:
13-- a_bus : goes to the ALU
14-- b_bus : goes to the ALU
15-- reg_dest_out : goes to the register bank
16-- take_branch : goes to pc_next
17---------------------------------------------------------------------
18library ieee;
19use ieee.std_logic_1164.all;
20use work.mlite_pack.all;
21
22entity bus_mux is
23   port(imm_in : in std_logic_vector(15 downto 0);
24        reg_source : in std_logic_vector(31 downto 0);
25        a_mux : in a_source_type;
26        a_out : out std_logic_vector(31 downto 0);
27
28        reg_target : in std_logic_vector(31 downto 0);
29        b_mux : in b_source_type;
30        b_out : out std_logic_vector(31 downto 0);
31
32        c_bus : in std_logic_vector(31 downto 0);
33        c_memory : in std_logic_vector(31 downto 0);
34        c_pc : in std_logic_vector(31 downto 2);
35        c_pc_plus4 : in std_logic_vector(31 downto 2);
36        c_mux : in c_source_type;
37        reg_dest_out : out std_logic_vector(31 downto 0);
38
39        branch_func : in branch_function_type;
40        take_branch : out std_logic);
41end; --entity bus_mux
42
43architecture logic of bus_mux is
44begin
45
46--Determine value of a_bus
47amux: process(reg_source, imm_in, a_mux, c_pc)
48begin
49   case a_mux is
50   when A_FROM_REG_SOURCE =>
51      a_out <= reg_source;
52   when A_FROM_IMM10_6 =>
53      a_out <= ZERO(31 downto 5) & imm_in(10 downto 6);
54   when A_FROM_PC =>
55      a_out <= c_pc & "00";
56   when others =>
57      a_out <= c_pc & "00";
58   end case;
59end process;
60
61--Determine value of b_bus
62bmux: process(reg_target, imm_in, b_mux)
63begin
64   case b_mux is
65   when B_FROM_REG_TARGET =>
66      b_out <= reg_target;
67   when B_FROM_IMM =>
68      b_out <= ZERO(31 downto 16) & imm_in;
69   when B_FROM_SIGNED_IMM =>
70      if imm_in(15) = '0' then
71         b_out(31 downto 16) <= ZERO(31 downto 16);
72      else
73         b_out(31 downto 16) <= "1111111111111111";
74      end if;
75      b_out(15 downto 0) <= imm_in;
76   when B_FROM_IMMX4 =>
77      if imm_in(15) = '0' then
78         b_out(31 downto 18) <= "00000000000000";
79      else
80         b_out(31 downto 18) <= "11111111111111";
81      end if;
82      b_out(17 downto 0) <= imm_in & "00";
83   when others =>
84      b_out <= reg_target;
85   end case;
86end process;
87
88--Determine value of c_bus
89cmux: process(c_bus, c_memory, c_pc, c_pc_plus4, imm_in, c_mux)
90begin
91   case c_mux is
92   when C_FROM_ALU => -- | C_FROM_SHIFT | C_FROM_MULT =>
93      reg_dest_out <= c_bus;
94   when C_FROM_MEMORY =>
95      reg_dest_out <= c_memory;
96   when C_FROM_PC =>
97      reg_dest_out <= c_pc(31 downto 2) & "00";
98   when C_FROM_PC_PLUS4 =>
99      reg_dest_out <= c_pc_plus4 & "00";
100   when C_FROM_IMM_SHIFT16 =>
101      reg_dest_out <= imm_in & ZERO(15 downto 0);
102   when others =>
103      reg_dest_out <= c_bus;
104   end case;
105end process;
106
107--Determine value of take_branch
108pc_mux: process(branch_func, reg_source, reg_target)
109   variable is_equal : std_logic;
110begin
111   if reg_source = reg_target then
112      is_equal := '1';
113   else
114      is_equal := '0';
115   end if;
116   case branch_func is
117   when BRANCH_LTZ =>
118      take_branch <= reg_source(31);
119   when BRANCH_LEZ =>
120      take_branch <= reg_source(31) or is_equal;
121   when BRANCH_EQ =>
122      take_branch <= is_equal;
123   when BRANCH_NE =>
124      take_branch <= not is_equal;
125   when BRANCH_GEZ =>
126      take_branch <= not reg_source(31);
127   when BRANCH_GTZ =>
128      take_branch <= not reg_source(31) and not is_equal;
129   when BRANCH_YES =>
130      take_branch <= '1';
131   when others =>
132      take_branch <= '0';
133   end case;
134end process;
135
136end; --architecture logic
plasma/logic/cache.vhd
1---------------------------------------------------------------------
2-- TITLE: Cache Controller
3-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4-- DATE CREATED: 12/22/08
5-- FILENAME: cache.vhd
6-- PROJECT: Plasma CPU core
7-- COPYRIGHT: Software placed into the public domain by the author.
8-- Software 'as is' without warranty. Author liable for nothing.
9-- DESCRIPTION:
10-- Control 4KB unified cache that uses the upper 4KB of the 8KB
11-- internal RAM. Only lowest 2MB of DDR is cached.
12---------------------------------------------------------------------
13library ieee;
14use ieee.std_logic_1164.all;
15use ieee.std_logic_unsigned.all;
16library UNISIM;
17use UNISIM.vcomponents.all;
18use work.mlite_pack.all;
19
20entity cache is
21   generic(memory_type : string := "DEFAULT");
22   port(clk : in std_logic;
23        reset : in std_logic;
24        address_next : in std_logic_vector(31 downto 2);
25        byte_we_next : in std_logic_vector(3 downto 0);
26        cpu_address : in std_logic_vector(31 downto 2);
27        mem_busy : in std_logic;
28
29        cache_check : out std_logic; --Stage1: address_next in first 2MB DDR
30        cache_checking : out std_logic; --Stage2: cache checking
31        cache_miss : out std_logic); --Stage2-3: cache miss
32end; --cache
33
34architecture logic of cache is
35   subtype state_type is std_logic_vector(1 downto 0);
36   constant STATE_CHECK : state_type := "00";
37   constant STATE_CHECKING : state_type := "01";
38   constant STATE_MISSED : state_type := "10";
39   constant STATE_WRITING : state_type := "11";
40
41   signal state_reg : state_type;
42   signal state : state_type;
43   signal state_next : state_type;
44
45   signal cache_address : std_logic_vector(10 downto 0);
46   signal cache_tag_in : std_logic_vector(8 downto 0);
47   signal cache_tag_reg : std_logic_vector(8 downto 0);
48   signal cache_tag_out : std_logic_vector(8 downto 0);
49   signal cache_we : std_logic;
50begin
51
52   cache_proc: process(clk, reset, mem_busy, cache_address, cache_we,
53      state_reg, state, state_next,
54      address_next, byte_we_next, cache_tag_in, --Stage1
55      cache_tag_reg, cache_tag_out, --Stage2
56      cpu_address) --Stage3
57   begin
58
59      case state_reg is
60      when STATE_CHECK =>
61         cache_checking <= '0';
62         cache_miss <= '0';
63         state <= STATE_CHECK;
64      when STATE_CHECKING =>
65         cache_checking <= '1';
66         if cache_tag_out /= cache_tag_reg or cache_tag_out = ONES(8 downto 0) then
67            cache_miss <= '1';
68            state <= STATE_MISSED;
69         else
70            cache_miss <= '0';
71            state <= STATE_CHECK;
72         end if;
73         cache_we <= '0';
74      when STATE_MISSED =>
75         cache_checking <= '0';
76         cache_miss <= '1';
77         cache_we <= '1';
78         if mem_busy = '1' then
79            state <= STATE_MISSED;
80         else
81            state <= STATE_CHECK;
82         end if;
83      when STATE_WRITING =>
84         cache_checking <= '0';
85         cache_miss <= '0';
86         cache_we <= '0';
87         if mem_busy = '1' then
88            state <= STATE_WRITING;
89         else
90            state <= STATE_CHECK;
91         end if;
92      when others =>
93         cache_checking <= '0';
94         cache_miss <= '0';
95         cache_we <= '0';
96         state <= STATE_CHECK;
97      end case; --state
98
99      if state = STATE_CHECK and state_reg /= STATE_MISSED then
100         cache_address <= '0' & address_next(11 downto 2);
101         if address_next(30 downto 21) = "0010000000" then --first 2MB of DDR
102            cache_check <= '1';
103            if byte_we_next = "0000" then
104               cache_we <= '0';
105               state_next <= STATE_CHECKING;
106            else
107               cache_we <= '1';
108               state_next <= STATE_WRITING;
109            end if;
110         else
111            cache_check <= '0';
112            cache_we <= '0';
113            state_next <= STATE_CHECK;
114         end if;
115      else
116         cache_address <= '0' & cpu_address(11 downto 2);
117         cache_check <= '0';
118         state_next <= state;
119      end if;
120
121      if byte_we_next = "0000" or byte_we_next = "1111" then
122         cache_tag_in <= address_next(20 downto 12);
123      else
124         cache_tag_in <= ONES(8 downto 0); --invalid tag
125      end if;
126
127      if reset = '1' then
128         state_reg <= STATE_CHECK;
129         cache_tag_reg <= ZERO(8 downto 0);
130      elsif rising_edge(clk) then
131         state_reg <= state_next;
132         if state = STATE_CHECK and state_reg /= STATE_MISSED then
133            cache_tag_reg <= cache_tag_in;
134         end if;
135      end if;
136
137   end process;
138
139   cache_xilinx: if memory_type = "XILINX_16X" generate
140   begin
141      cache_tag: RAMB16_S9 --Xilinx specific
142      port map (
143         DO => cache_tag_out(7 downto 0),
144         DOP => cache_tag_out(8 downto 8),
145         ADDR => cache_address, --registered
146         CLK => clk,
147         DI => cache_tag_in(7 downto 0), --registered
148         DIP => cache_tag_in(8 downto 8),
149         EN => '1',
150         SSR => ZERO(0),
151         WE => cache_we);
152   end generate; --cache_xilinx
153
154   cache_generic: if memory_type /= "XILINX_16X" generate
155   begin
156      cache_tag: process(clk, cache_address, cache_tag_in, cache_we)
157         constant ADDRESS_WIDTH : natural := 10;
158         type storage_array is
159            array(natural range 0 to 2 ** ADDRESS_WIDTH - 1) of
160            std_logic_vector(8 downto 0);
161         variable storage : storage_array;
162         variable index : natural := 0;
163      begin
164         if rising_edge(clk) then
165            index := conv_integer(cache_address(ADDRESS_WIDTH-1 downto 0));
166            if cache_we = '1' then
167               storage(index) := cache_tag_in;
168            end if;
169            cache_tag_out <= storage(index);
170         end if;
171      end process; --cache_tag
172   end generate; --cache_generic
173
174end; --logic
175
plasma/logic/code.txt
13c1c0000
2379c8a34
33c040000
434840a48
53c050000
634a50a64
73c1d0000
837bd0c60
9ac800000
100085182a
111460fffd
1224840004
130c0001d5
1400000000
150800000e
1623bdff98
17afa10010
18afa20014
19afa30018
20afa4001c
21afa50020
22afa60024
23afa70028
24afa8002c
25afa90030
26afaa0034
27afab0038
28afac003c
29afad0040
30afae0044
31afaf0048
32afb8004c
33afb90050
34afbf0054
35401a7000
36235afffc
37afba0058
380000d810
39afbb005c
400000d812
41afbb0060
4223a50000
433c062000
448cc40020
458cc60010
460c00020a
4700862024
488fa10010
498fa20014
508fa30018
518fa4001c
528fa50020
538fa60024
548fa70028
558fa8002c
568fa90030
578faa0034
588fab0038
598fac003c
608fad0040
618fae0044
628faf0048
638fb8004c
648fb90050
658fbf0054
668fba0058
678fbb005c
6803600011
698fbb0060
7003600013
7123bd0068
72341b0001
7303400008
74409b6000
7540026000
7603e00008
7740846000
783c050000
7924a50160
808ca60000
81ac06003c
828ca60004
83ac060040
848ca60008
85ac060044
868ca6000c
8703e00008
88ac060048
893c1a1000
90375a003c
9103400008
9200000000
93ac900000
94ac910004
95ac920008
96ac93000c
97ac940010
98ac950014
99ac960018
100ac97001c
101ac9e0020
102ac9c0024
103ac9d0028
104ac9f002c
10503e00008
10634020000
1078c900000
1088c910004
1098c920008
1108c93000c
1118c940010
1128c950014
1138c960018
1148c97001c
1158c9e0020
1168c9c0024
1178c9d0028
1188c9f002c
11903e00008
12034a20000
12100850019
12200001012
12300002010
12403e00008
125acc40000
1263c020000
12724420a48
128a0400008
12924050007
13000403825
1313083000f
1322862000a
13310400003
13400a73021
13510000002
13624620030
13724620037
138a0c20000
13924a5ffff
14004a1fff6
14100042102
1423c020000
14303e00008
14424420a48
1453c020000
14624420a58
147a040000a
14800803025
14924050009
15000404025
1513c07cccc
15234e7cccd
15300c70019
15400a82021
15524a5ffff
15600004810
157000918c2
15800031080
15900431021
16000021040
16100c21023
16224420030
163a0820000
16404a1fff4
16500603025
1663c020000
16703e00008
16824420a58
16927bdffe0
170afbf0018
171afb10014
172afb00010
1730c000090
17400808825
1750c0001ef
17600402025
1773c040000
1780c0001ef
17924840980
1803c023b9a
1813442c9ff
1820051102b
1831040001e
1843c030004
18534634b83
18600111242
18700430019
1883c030000
189246309cc
19000002810
191000581c2
19200101080
19300431021
1948c440000
1950c0001ef
19600000000
1973c040000
1980c0001ef
19924840984
20000101140
20100501023
20200021080
20300501023
20400021100
20500501021
206000210c0
20700501023
20800021940
20900621823
21000031880
21100701821
21200031a40
21302238823
2143c0205f5
2153442e0ff
2160051102b
21710400023
2183c0255e6
21934423b89
22002220019
2213c030000
222246309cc
22300002810
22400058642
22500101080
22600431021
2278c440000
2280c0001ef
22900000000
2303c040000
2310c0001ef
23224840990
23300101040
23400501021
23500021180
23600501023
23700021080
23800501023
23900021100
24000501023
24100021140
24200501021
24300021200
24402228823
2453c02000f
2463442423f
2470051102b
24814400005
2493c020131
2503c040000
2510c0001ef
2522484099c
2533c020131
25434422cff
2550051102b
25610400021
2573c026b5f
2583442ca6b
25902220019
2603c030000
261246309cc
26200002810
26300058582
26426020014
26500021080
26600431021
2678c440000
2680c0001ef
26900000000
2700c0001de
27124040020
27200101940
27300701823
27400031180
27500431023
276000210c0
27700501021
27800021880
27900431021
280000211c0
28102228823
2823c02000f
2833442423f
2840051102b
28514400009
2863c02431b
2873c040000
2880c0001ef
2892484099c
2903c02000f
2913442423f
2920051102b
29310400017
2943c02431b
2953442de83
29602220019
2973c030000
298246309cc
29900002810
30000058482
30100101080
30200431021
3038c440000
3040c0001ef
30500000000
3063c040000
3070c0001ef
308248409a8
30900101940
31000701823
31100031180
31200431023
313000210c0
31400501021
31500021180
31602228823
3173c020001
3183442869f
3190051102b
32010400020
3213c030a7c
32234635ac5
32300111142
32400430019
3253c030000
326246309cc
32700002810
328000581c2
32900101080
33000431021
3318c440000
3320c0001ef
33300000000
3343c040000
3350c0001ef
33624840990
33700101040
33800501021
33900021980
34000431021
34100021080
34200501021
34300021080
34400501021
34500021140
34602228823
3472e2203e8
34810400005
3492e224e20
3503c040000
3510c0001ef
352248409b4
3532e224e20
3541440001f
3552e2203e8
3563c02d1b7
35734421759
35802220019
3593c030000
360246309cc
36100002810
36200058342
36326020014
36400021080
36500431021
3668c440000
3670c0001ef
36800000000
3690c0001de
37024040020
37100101080
37200501021
373000210c0
37400501023
37500021100
37600501021
37700021100
37802228823
3792e2203e8
38010400008
3813c021062
3823c040000
3830c0001ef
384248409b4
3852e2203e8
38614400017
3872e220064
3883c021062
38934424dd3
39002220019
3913c030000
392246309cc
39300002810
39400058182
39500101080
39600431021
3978c440000
3980c0001ef
39900000000
4003c040000
4010c0001ef
402248409c0
40300101140
40400501023
40500021080
40600501021
407000210c0
40802228823
4092e220064
41014400017
4112e220014
4123c0251eb
4133442851f
41402220019
4153c030000
416246309cc
41700002810
41800058142
41900101080
42000431021
4218c440000
4220c0001ef
42300000000
4243c040000
4250c0001ef
42624840990
42700101040
42800501021
429000210c0
43000501021
43100021080
43202228823
4332e220014
43414400014
4353c030000
4363c02cccc
4373442cccd
43802220019
439246309cc
44000002810
441000580c2
44226020014
44300021080
44400431021
4458c440000
4460c0001ef
44700000000
4480c0001de
44924040020
45000101080
45100501021
45200021040
45302228823
4543c030000
455246309cc
45600111080
45700431021
4588c440000
4590c0001ef
46000000000
4610c0001de
4622404000d
4630c0001de
4642404000a
4658fbf0018
4668fb10014
4678fb00010
46803e00008
46927bd0020
47027bdffe8
471afbf0014
472afb00010
47324100003
4740c0000a8
47502002025
47600101040
4771000fffc
47802028021
4793c022000
48034420020
4818c420000
48200000000
48330420002
48414400008
4853c022000
4863c032000
48734630020
4888c620000
48900000000
49030420002
4911040fffc
4923c022000
493ac440000
49403e00008
49500000000
49627bdffe0
497afb00010
49800808025
499afbf0018
500afb10014
50192020000
50200000000
5031040000d
5042411000a
50500000000
50614510003
50700000000
5080c0001de
5092404000d
51092040000
5110c0001de
51226100001
51392020000
51400000000
5151440fff5
51600000000
5178fbf0018
5188fb10014
5198fb00010
52000001025
52103e00008
52227bd0020
52327bdffe8
524afbf0010
5250c0001de
52624040049
5278fbf0010
52800000000
52903e00008
53027bd0018
5313c022000
53234420020
5338c420000
53403e00008
53530420001
53627bdffe8
537afbf0010
5380c000212
53900000000
5401040fffd
5413c022000
5428c420000
5438fbf0010
54400000000
54503e00008
54627bd0018
54700000000
54800000000
54900000000
55000000000
55100000000
55200000000
5536e696e65
55474790000
55565696768
55674790000
55773657665
5586e747900
55973697874
56079000000
56166696674
56279000000
563666f7274
56479000000
56574686972
56674790000
5677477656e
56874790000
5696e696e65
5707465656e
57100000000
57265696768
5737465656e
57400000000
57573657665
5766e746565
5776e000000
57873697874
57965656e00
58066696674
58165656e00
582666f7572
5837465656e
58400000000
58574686972
5867465656e
58700000000
5887477656c
58976650000
590656c6576
591656e0000
59274656e00
5936e696e65
59400000000
59565696768
59674000000
59773657665
5986e000000
59973697800
60066697665
60100000000
602666f7572
60300000000
60474687265
60565000000
60674776f00
6076f6e6500
60800000000
6093a200000
6102062696c
6116c696f6e
61220000000
6132068756e
61464726564
61520000000
6166d696c6c
617696f6e20
61800000000
619206d696c
6206c696f6e
62120000000
62274686f75
62373616e64
62420000000
6252074686f
6267573616e
62764200000
6280000097c
62900000978
63000000974
6310000096c
63200000964
6330000095c
63400000958
63500000950
63600000948
63700000940
6380000093c
63900000934
6400000092c
64100000920
64200000914
6430000090c
64400000904
645000008f8
646000008ec
647000008e0
6480000097c
6490000093c
650000008d8
651000008d0
652000008c8
653000008c0
654000008b8
655000008b0
656000008a8
657000008a0
65800000000
plasma/logic/control.vhd
1---------------------------------------------------------------------
2-- TITLE: Controller / Opcode Decoder
3-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4-- DATE CREATED: 2/8/01
5-- FILENAME: control.vhd
6-- PROJECT: Plasma CPU core
7-- COPYRIGHT: Software placed into the public domain by the author.
8-- Software 'as is' without warranty. Author liable for nothing.
9-- NOTE: MIPS(tm) is a registered trademark of MIPS Technologies.
10-- MIPS Technologies does not endorse and is not associated with
11-- this project.
12-- DESCRIPTION:
13-- Controls the CPU by decoding the opcode and generating control
14-- signals to the rest of the CPU.
15-- This entity decodes the MIPS(tm) opcode into a
16-- Very-Long-Word-Instruction.
17-- The 32-bit opcode is converted to a
18-- 6+6+6+16+4+2+4+3+2+2+3+2+4 = 60 bit VLWI opcode.
19-- Based on information found in:
20-- "MIPS RISC Architecture" by Gerry Kane and Joe Heinrich
21-- and "The Designer's Guide to VHDL" by Peter J. Ashenden
22---------------------------------------------------------------------
23library ieee;
24use ieee.std_logic_1164.all;
25use work.mlite_pack.all;
26
27entity control is
28   port(opcode : in std_logic_vector(31 downto 0);
29        intr_signal : in std_logic;
30        rs_index : out std_logic_vector(5 downto 0);
31        rt_index : out std_logic_vector(5 downto 0);
32        rd_index : out std_logic_vector(5 downto 0);
33        imm_out : out std_logic_vector(15 downto 0);
34        alu_func : out alu_function_type;
35        shift_func : out shift_function_type;
36        mult_func : out mult_function_type;
37        branch_func : out branch_function_type;
38        a_source_out : out a_source_type;
39        b_source_out : out b_source_type;
40        c_source_out : out c_source_type;
41        pc_source_out: out pc_source_type;
42        mem_source_out:out mem_source_type;
43        exception_out: out std_logic);
44end; --entity control
45
46architecture logic of control is
47begin
48
49control_proc: process(opcode, intr_signal)
50   variable op, func : std_logic_vector(5 downto 0);
51   variable rs, rt, rd : std_logic_vector(5 downto 0);
52   variable rtx : std_logic_vector(4 downto 0);
53   variable imm : std_logic_vector(15 downto 0);
54   variable alu_function : alu_function_type;
55   variable shift_function : shift_function_type;
56   variable mult_function : mult_function_type;
57   variable a_source : a_source_type;
58   variable b_source : b_source_type;
59   variable c_source : c_source_type;
60   variable pc_source : pc_source_type;
61   variable branch_function: branch_function_type;
62   variable mem_source : mem_source_type;
63   variable is_syscall : std_logic;
64begin
65   alu_function := ALU_NOTHING;
66   shift_function := SHIFT_NOTHING;
67   mult_function := MULT_NOTHING;
68   a_source := A_FROM_REG_SOURCE;
69   b_source := B_FROM_REG_TARGET;
70   c_source := C_FROM_NULL;
71   pc_source := FROM_INC4;
72   branch_function := BRANCH_EQ;
73   mem_source := MEM_FETCH;
74   op := opcode(31 downto 26);
75   rs := '0' & opcode(25 downto 21);
76   rt := '0' & opcode(20 downto 16);
77   rtx := opcode(20 downto 16);
78   rd := '0' & opcode(15 downto 11);
79   func := opcode(5 downto 0);
80   imm := opcode(15 downto 0);
81   is_syscall := '0';
82
83   case op is
84   when "000000" => --SPECIAL
85      case func is
86      when "000000" => --SLL r[rd]=r[rt]<<re;
87         a_source := A_FROM_IMM10_6;
88         c_source := C_FROM_SHIFT;
89         shift_function := SHIFT_LEFT_UNSIGNED;
90
91      when "000010" => --SRL r[rd]=u[rt]>>re;
92         a_source := A_FROM_IMM10_6;
93         c_source := C_FROM_shift;
94         shift_function := SHIFT_RIGHT_UNSIGNED;
95
96      when "000011" => --SRA r[rd]=r[rt]>>re;
97         a_source := A_FROM_IMM10_6;
98         c_source := C_FROM_SHIFT;
99         shift_function := SHIFT_RIGHT_SIGNED;
100
101      when "000100" => --SLLV r[rd]=r[rt]<<r[rs];
102         c_source := C_FROM_SHIFT;
103         shift_function := SHIFT_LEFT_UNSIGNED;
104
105      when "000110" => --SRLV r[rd]=u[rt]>>r[rs];
106         c_source := C_FROM_SHIFT;
107         shift_function := SHIFT_RIGHT_UNSIGNED;
108
109      when "000111" => --SRAV r[rd]=r[rt]>>r[rs];
110         c_source := C_FROM_SHIFT;
111         shift_function := SHIFT_RIGHT_SIGNED;
112
113      when "001000" => --JR s->pc_next=r[rs];
114         pc_source := FROM_BRANCH;
115         alu_function := ALU_ADD;
116         branch_function := BRANCH_YES;
117
118      when "001001" => --JALR r[rd]=s->pc_next; s->pc_next=r[rs];
119         c_source := C_FROM_PC_PLUS4;
120         pc_source := FROM_BRANCH;
121         alu_function := ALU_ADD;
122         branch_function := BRANCH_YES;
123
124      --when "001010" => --MOVZ if(!r[rt]) r[rd]=r[rs]; /*IV*/
125      --when "001011" => --MOVN if(r[rt]) r[rd]=r[rs]; /*IV*/
126
127      when "001100" => --SYSCALL
128         is_syscall := '1';
129
130      when "001101" => --BREAK s->wakeup=1;
131         is_syscall := '1';
132
133      --when "001111" => --SYNC s->wakeup=1;
134
135      when "010000" => --MFHI r[rd]=s->hi;
136         c_source := C_FROM_MULT;
137         mult_function := MULT_READ_HI;
138
139      when "010001" => --FTHI s->hi=r[rs];
140         mult_function := MULT_WRITE_HI;
141
142      when "010010" => --MFLO r[rd]=s->lo;
143         c_source := C_FROM_MULT;
144         mult_function := MULT_READ_LO;
145
146      when "010011" => --MTLO s->lo=r[rs];
147         mult_function := MULT_WRITE_LO;
148
149      when "011000" => --MULT s->lo=r[rs]*r[rt]; s->hi=0;
150         mult_function := MULT_SIGNED_MULT;
151
152      when "011001" => --MULTU s->lo=r[rs]*r[rt]; s->hi=0;
153         mult_function := MULT_MULT;
154
155      when "011010" => --DIV s->lo=r[rs]/r[rt]; s->hi=r[rs]%r[rt];
156         mult_function := MULT_SIGNED_DIVIDE;
157
158      when "011011" => --DIVU s->lo=r[rs]/r[rt]; s->hi=r[rs]%r[rt];
159         mult_function := MULT_DIVIDE;
160
161      when "100000" => --ADD r[rd]=r[rs]+r[rt];
162         c_source := C_FROM_ALU;
163         alu_function := ALU_ADD;
164
165      when "100001" => --ADDU r[rd]=r[rs]+r[rt];
166         c_source := C_FROM_ALU;
167         alu_function := ALU_ADD;
168
169      when "100010" => --SUB r[rd]=r[rs]-r[rt];
170         c_source := C_FROM_ALU;
171         alu_function := ALU_SUBTRACT;
172
173      when "100011" => --SUBU r[rd]=r[rs]-r[rt];
174         c_source := C_FROM_ALU;
175         alu_function := ALU_SUBTRACT;
176
177      when "100100" => --AND r[rd]=r[rs]&r[rt];
178         c_source := C_FROM_ALU;
179         alu_function := ALU_AND;
180
181      when "100101" => --OR r[rd]=r[rs]|r[rt];
182         c_source := C_FROM_ALU;
183         alu_function := ALU_OR;
184
185      when "100110" => --XOR r[rd]=r[rs]^r[rt];
186         c_source := C_FROM_ALU;
187         alu_function := ALU_XOR;
188
189      when "100111" => --NOR r[rd]=~(r[rs]|r[rt]);
190         c_source := C_FROM_ALU;
191         alu_function := ALU_NOR;
192
193      when "101010" => --SLT r[rd]=r[rs]<r[rt];
194         c_source := C_FROM_ALU;
195         alu_function := ALU_LESS_THAN_SIGNED;
196
197      when "101011" => --SLTU r[rd]=u[rs]<u[rt];
198         c_source := C_FROM_ALU;
199         alu_function := ALU_LESS_THAN;
200
201      when "101101" => --DADDU r[rd]=r[rs]+u[rt];
202         c_source := C_FROM_ALU;
203         alu_function := ALU_ADD;
204
205      --when "110001" => --TGEU
206      --when "110010" => --TLT
207      --when "110011" => --TLTU
208      --when "110100" => --TEQ
209      --when "110110" => --TNE
210      when others =>
211      end case;
212
213   when "000001" => --REGIMM
214      rt := "000000";
215      rd := "011111";
216      a_source := A_FROM_PC;
217      b_source := B_FROM_IMMX4;
218      alu_function := ALU_ADD;
219      pc_source := FROM_BRANCH;
220      branch_function := BRANCH_GTZ;
221      --if(test) pc=pc+imm*4
222
223      case rtx is
224      when "10000" => --BLTZAL r[31]=s->pc_next; branch=r[rs]<0;
225         c_source := C_FROM_PC_PLUS4;
226         branch_function := BRANCH_LTZ;
227
228      when "00000" => --BLTZ branch=r[rs]<0;
229         branch_function := BRANCH_LTZ;
230
231      when "10001" => --BGEZAL r[31]=s->pc_next; branch=r[rs]>=0;
232         c_source := C_FROM_PC_PLUS4;
233         branch_function := BRANCH_GEZ;
234
235      when "00001" => --BGEZ branch=r[rs]>=0;
236         branch_function := BRANCH_GEZ;
237
238      --when "10010" => --BLTZALL r[31]=s->pc_next; lbranch=r[rs]<0;
239      --when "00010" => --BLTZL lbranch=r[rs]<0;
240      --when "10011" => --BGEZALL r[31]=s->pc_next; lbranch=r[rs]>=0;
241      --when "00011" => --BGEZL lbranch=r[rs]>=0;
242
243      when others =>
244      end case;
245
246   when "000011" => --JAL r[31]=s->pc_next; s->pc_next=(s->pc&0xf0000000)|target;
247      c_source := C_FROM_PC_PLUS4;
248      rd := "011111";
249      pc_source := FROM_OPCODE25_0;
250
251   when "000010" => --J s->pc_next=(s->pc&0xf0000000)|target;
252      pc_source := FROM_OPCODE25_0;
253
254   when "000100" => --BEQ branch=r[rs]==r[rt];
255      a_source := A_FROM_PC;
256      b_source := B_FROM_IMMX4;
257      alu_function := ALU_ADD;
258      pc_source := FROM_BRANCH;
259      branch_function := BRANCH_EQ;
260
261   when "000101" => --BNE branch=r[rs]!=r[rt];
262      a_source := A_FROM_PC;
263      b_source := B_FROM_IMMX4;
264      alu_function := ALU_ADD;
265      pc_source := FROM_BRANCH;
266      branch_function := BRANCH_NE;
267
268   when "000110" => --BLEZ branch=r[rs]<=0;
269      a_source := A_FROM_PC;
270      b_source := b_FROM_IMMX4;
271      alu_function := ALU_ADD;
272      pc_source := FROM_BRANCH;
273      branch_function := BRANCH_LEZ;
274
275   when "000111" => --BGTZ branch=r[rs]>0;
276      a_source := A_FROM_PC;
277      b_source := B_FROM_IMMX4;
278      alu_function := ALU_ADD;
279      pc_source := FROM_BRANCH;
280      branch_function := BRANCH_GTZ;
281
282   when "001000" => --ADDI r[rt]=r[rs]+(short)imm;
283      b_source := B_FROM_SIGNED_IMM;
284      c_source := C_FROM_ALU;
285      rd := rt;
286      alu_function := ALU_ADD;
287
288   when "001001" => --ADDIU u[rt]=u[rs]+(short)imm;
289      b_source := B_FROM_SIGNED_IMM;
290      c_source := C_FROM_ALU;
291      rd := rt;
292      alu_function := ALU_ADD;
293
294   when "001010" => --SLTI r[rt]=r[rs]<(short)imm;
295      b_source := B_FROM_SIGNED_IMM;
296      c_source := C_FROM_ALU;
297      rd := rt;
298      alu_function := ALU_LESS_THAN_SIGNED;
299
300   when "001011" => --SLTIU u[rt]=u[rs]<(unsigned long)(short)imm;
301      b_source := B_FROM_SIGNED_IMM;
302      c_source := C_FROM_ALU;
303      rd := rt;
304      alu_function := ALU_LESS_THAN;
305
306   when "001100" => --ANDI r[rt]=r[rs]&imm;
307      b_source := B_FROM_IMM;
308      c_source := C_FROM_ALU;
309      rd := rt;
310      alu_function := ALU_AND;
311
312   when "001101" => --ORI r[rt]=r[rs]|imm;
313      b_source := B_FROM_IMM;
314      c_source := C_FROM_ALU;
315      rd := rt;
316      alu_function := ALU_OR;
317
318   when "001110" => --XORI r[rt]=r[rs]^imm;
319      b_source := B_FROM_IMM;
320      c_source := C_FROM_ALU;
321      rd := rt;
322      alu_function := ALU_XOR;
323
324   when "001111" => --LUI r[rt]=(imm<<16);
325      c_source := C_FROM_IMM_SHIFT16;
326      rd := rt;
327
328   when "010000" => --COP0
329      alu_function := ALU_OR;
330      c_source := C_FROM_ALU;
331      if opcode(23) = '0' then --move from CP0
332         rs := '1' & opcode(15 downto 11);
333         rt := "000000";
334         rd := '0' & opcode(20 downto 16);
335      else --move to CP0
336         rs := "000000";
337         rd(5) := '1';
338         pc_source := FROM_BRANCH; --delay possible interrupt
339         branch_function := BRANCH_NO;
340      end if;
341
342   --when "010001" => --COP1
343   --when "010010" => --COP2
344   --when "010011" => --COP3
345   --when "010100" => --BEQL lbranch=r[rs]==r[rt];
346   --when "010101" => --BNEL lbranch=r[rs]!=r[rt];
347   --when "010110" => --BLEZL lbranch=r[rs]<=0;
348   --when "010111" => --BGTZL lbranch=r[rs]>0;
349
350   when "100000" => --LB r[rt]=*(signed char*)ptr;
351      a_source := A_FROM_REG_SOURCE;
352      b_source := B_FROM_SIGNED_IMM;
353      alu_function := ALU_ADD;
354      rd := rt;
355      c_source := C_FROM_MEMORY;
356      mem_source := MEM_READ8S; --address=(short)imm+r[rs];
357
358   when "100001" => --LH r[rt]=*(signed short*)ptr;
359      a_source := A_FROM_REG_SOURCE;
360      b_source := B_FROM_SIGNED_IMM;
361      alu_function := ALU_ADD;
362      rd := rt;
363      c_source := C_FROM_MEMORY;
364      mem_source := MEM_READ16S; --address=(short)imm+r[rs];
365
366   when "100010" => --LWL //Not Implemented
367      a_source := A_FROM_REG_SOURCE;
368      b_source := B_FROM_SIGNED_IMM;
369      alu_function := ALU_ADD;
370      rd := rt;
371      c_source := C_FROM_MEMORY;
372      mem_source := MEM_READ32;
373
374   when "100011" => --LW r[rt]=*(long*)ptr;
375      a_source := A_FROM_REG_SOURCE;
376      b_source := B_FROM_SIGNED_IMM;
377      alu_function := ALU_ADD;
378      rd := rt;
379      c_source := C_FROM_MEMORY;
380      mem_source := MEM_READ32;
381
382   when "100100" => --LBU r[rt]=*(unsigned char*)ptr;
383      a_source := A_FROM_REG_SOURCE;
384      b_source := B_FROM_SIGNED_IMM;
385      alu_function := ALU_ADD;
386      rd := rt;
387      c_source := C_FROM_MEMORY;
388      mem_source := MEM_READ8; --address=(short)imm+r[rs];
389
390   when "100101" => --LHU r[rt]=*(unsigned short*)ptr;
391      a_source := A_FROM_REG_SOURCE;
392      b_source := B_FROM_SIGNED_IMM;
393      alu_function := ALU_ADD;
394      rd := rt;
395      c_source := C_FROM_MEMORY;
396      mem_source := MEM_READ16; --address=(short)imm+r[rs];
397
398   --when "100110" => --LWR //Not Implemented
399
400   when "101000" => --SB *(char*)ptr=(char)r[rt];
401      a_source := A_FROM_REG_SOURCE;
402      b_source := B_FROM_SIGNED_IMM;
403      alu_function := ALU_ADD;
404      mem_source := MEM_WRITE8; --address=(short)imm+r[rs];
405
406   when "101001" => --SH *(short*)ptr=(short)r[rt];
407      a_source := A_FROM_REG_SOURCE;
408      b_source := B_FROM_SIGNED_IMM;
409      alu_function := ALU_ADD;
410      mem_source := MEM_WRITE16;
411
412   when "101010" => --SWL //Not Implemented
413      a_source := A_FROM_REG_SOURCE;
414      b_source := B_FROM_SIGNED_IMM;
415      alu_function := ALU_ADD;
416      mem_source := MEM_WRITE32; --address=(short)imm+r[rs];
417
418   when "101011" => --SW *(long*)ptr=r[rt];
419      a_source := A_FROM_REG_SOURCE;
420      b_source := B_FROM_SIGNED_IMM;
421      alu_function := ALU_ADD;
422      mem_source := MEM_WRITE32; --address=(short)imm+r[rs];
423
424   --when "101110" => --SWR //Not Implemented
425   --when "101111" => --CACHE
426   --when "110000" => --LL r[rt]=*(long*)ptr;
427   --when "110001" => --LWC1
428   --when "110010" => --LWC2
429   --when "110011" => --LWC3
430   --when "110101" => --LDC1
431   --when "110110" => --LDC2
432   --when "110111" => --LDC3
433   --when "111000" => --SC *(long*)ptr=r[rt]; r[rt]=1;
434   --when "111001" => --SWC1
435   --when "111010" => --SWC2
436   --when "111011" => --SWC3
437   --when "111101" => --SDC1
438   --when "111110" => --SDC2
439   --when "111111" => --SDC3
440   when others =>
441   end case;
442
443   if c_source = C_FROM_NULL then
444      rd := "000000";
445   end if;
446
447   if intr_signal = '1' or is_syscall = '1' then
448      rs := "111111"; --interrupt vector
449      rt := "000000";
450      rd := "101110"; --save PC in EPC
451      alu_function := ALU_OR;
452      shift_function := SHIFT_NOTHING;
453      mult_function := MULT_NOTHING;
454      branch_function := BRANCH_YES;
455      a_source := A_FROM_REG_SOURCE;
456      b_source := B_FROM_REG_TARGET;
457      c_source := C_FROM_PC;
458      pc_source := FROM_LBRANCH;
459      mem_source := MEM_FETCH;
460      exception_out <= '1';
461   else
462      exception_out <= '0';
463   end if;
464
465   rs_index <= rs;
466   rt_index <= rt;
467   rd_index <= rd;
468   imm_out <= imm;
469   alu_func <= alu_function;
470   shift_func <= shift_function;
471   mult_func <= mult_function;
472   branch_func <= branch_function;
473   a_source_out <= a_source;
474   b_source_out <= b_source;
475   c_source_out <= c_source;
476   pc_source_out <= pc_source;
477   mem_source_out <= mem_source;
478
479end process;
480
481end; --logic
plasma/logic/ddr_ctrl.vhd
1---------------------------------------------------------------------
2-- TITLE: DDR SDRAM Interface
3-- AUTHORS: Steve Rhoads (rhoadss@yahoo.com)
4-- DATE CREATED: 7/26/07
5-- FILENAME: ddr_ctrl.vhd
6-- PROJECT: Plasma CPU core
7-- COPYRIGHT: Software placed into the public domain by the author.
8-- Software 'as is' without warranty. Author liable for nothing.
9-- DESCRIPTION:
10-- Double Data Rate Sychronous Dynamic Random Access Memory Interface
11--
12-- For: 64 MB = MT46V32M16, 512Mb, 32Mb x 16 (default)
13-- ROW = address(25 downto 13)
14-- BANK = address(12 downto 11)
15-- COL = address(10 downto 2)
16--
17-- Changes are needed for 32 MB = MT46V16M16, 256Mb, 16Mb x 16
18-- ROW = address(24 downto 12) -- 25 ignored
19-- BANK = address(11 downto 10)
20-- COL = address(9 downto 2) --also change ddr_init.c
21--
22-- Changes are needed for 128 MB = MT46V64M16, 1Gb, 64Mb x 16
23-- ROW = address(26 downto 14)
24-- BANK = address(13 downto 12)
25-- COL = address(11 downto 2) --also change ddr_init.c
26--
27-- Requires CAS latency=2; burst size=2.
28-- Requires clk changes on rising_edge(clk_2x).
29-- Requires active, address, byte_we, data_w stable throughout transfer.
30-- DLL mode requires 77MHz. Non-DLL mode runs at 25 MHz.
31--
32-- cycle_cnt 777777770000111122223333444455556666777777777777
33-- clk_2x --__--__--__--__--__--__--__--__--__--__--__--__
34-- clk ____----____----____----____----____----____----
35-- SD_CLK ----____----____----____----____----____----____
36-- cmd ____write+++WRITE+++____________________________
37-- SD_DQ ~~~~~~~~~~~~~~uuuullllUUUULLLL~~~~~~~~~~~~~~~~~~
38--
39-- cycle_cnt 777777770000111122223333444455556666777777777777
40-- clk_2x --__--__--__--__--__--__--__--__--__--__--__--__
41-- clk ____----____----____----____----____----____----
42-- SD_CLK ----____----____----____----____----____----____
43-- cmd ____read++++________________________read++++____
44-- SD_DQ ~~~~~~~~~~~~~~~~~~~~~~~~uuuullll~~~~~~~~~~~~~~~~
45-- SD_DQnDLL ~~~~~~~~~~~~~~~~~~~~~~~~~~uuuullll~~~~~~~~~~~~~~
46-- pause ____------------------------________------------
47--
48-- Must run DdrInit() to initialize DDR chip.
49-- Read Micron DDR SDRAM MT46V32M16 data sheet for more details.
50---------------------------------------------------------------------
51library ieee;
52use ieee.std_logic_1164.all;
53use ieee.std_logic_unsigned.all;
54use ieee.std_logic_arith.all;
55use work.mlite_pack.all;
56
57entity ddr_ctrl is
58   port(
59      clk : in std_logic;
60      clk_2x : in std_logic;
61      reset_in : in std_logic;
62
63      address : in std_logic_vector(25 downto 2);
64      byte_we : in std_logic_vector(3 downto 0);
65      data_w : in std_logic_vector(31 downto 0);
66      data_r : out std_logic_vector(31 downto 0);
67      active : in std_logic;
68      no_start : in std_logic;
69      no_stop : in std_logic;
70      pause : out std_logic;
71
72      SD_CK_P : out std_logic; --clock_positive
73      SD_CK_N : out std_logic; --clock_negative
74      SD_CKE : out std_logic; --clock_enable
75
76      SD_BA : out std_logic_vector(1 downto 0); --bank_address
77      SD_A : out std_logic_vector(12 downto 0); --address(row or col)
78      SD_CS : out std_logic; --chip_select
79      SD_RAS : out std_logic; --row_address_strobe
80      SD_CAS : out std_logic; --column_address_strobe
81      SD_WE : out std_logic; --write_enable
82
83      SD_DQ : inout std_logic_vector(15 downto 0); --data
84      SD_UDM : out std_logic; --upper_byte_enable
85      SD_UDQS : inout std_logic; --upper_data_strobe
86      SD_LDM : out std_logic; --low_byte_enable
87      SD_LDQS : inout std_logic); --low_data_strobe
88end; --entity ddr
89
90architecture logic of ddr_ctrl is
91
92   --Commands for bits RAS & CAS & WE
93   subtype command_type is std_logic_vector(2 downto 0);
94   constant COMMAND_LMR : command_type := "000";
95   constant COMMAND_AUTO_REFRESH : command_type := "001";
96   constant COMMAND_PRECHARGE : command_type := "010";
97   constant COMMAND_ACTIVE : command_type := "011";
98   constant COMMAND_WRITE : command_type := "100";
99   constant COMMAND_READ : command_type := "101";
100   constant COMMAND_TERMINATE : command_type := "110";
101   constant COMMAND_NOP : command_type := "111";
102
103   subtype ddr_state_type is std_logic_vector(3 downto 0);
104   constant STATE_POWER_ON : ddr_state_type := "0000";
105   constant STATE_IDLE : ddr_state_type := "0001";
106   constant STATE_ROW_ACTIVATE : ddr_state_type := "0010";
107   constant STATE_ROW_ACTIVE : ddr_state_type := "0011";
108   constant STATE_READ : ddr_state_type := "0100";
109   constant STATE_READ2 : ddr_state_type := "0101";
110   constant STATE_READ3 : ddr_state_type := "0110";
111   constant STATE_PRECHARGE : ddr_state_type := "0111";
112   constant STATE_PRECHARGE2 : ddr_state_type := "1000";
113
114   signal state_prev : ddr_state_type;
115   signal refresh_cnt : std_logic_vector(7 downto 0);
116   signal data_write2 : std_logic_vector(47 downto 0); --write pipeline
117   signal byte_we_reg2 : std_logic_vector(5 downto 0); --write pipeline
118   signal write_active : std_logic;
119   signal write_prev : std_logic;
120   signal cycle_count : std_logic_vector(2 downto 0); --half clocks since op
121   signal cycle_count2 : std_logic_vector(2 downto 0); --delayed by quarter clock
122   signal cke_reg : std_logic;
123   signal clk_p : std_logic;
124   signal bank_open : std_logic_vector(3 downto 0);
125   signal data_read : std_logic_vector(31 downto 0);
126
127begin
128   ddr_proc: process(clk, clk_p, clk_2x, reset_in,
129                     address, byte_we, data_w, active, no_start, no_stop,
130                     SD_DQ, SD_UDQS, SD_LDQS,
131                     state_prev, refresh_cnt,
132                     byte_we_reg2, data_write2,
133                     cycle_count, cycle_count2, write_prev,
134                     write_active, cke_reg, bank_open,
135                     data_read)
136   type address_array_type is array(3 downto 0) of std_logic_vector(12 downto 0);
137   variable address_row : address_array_type;
138   variable command : std_logic_vector(2 downto 0); --RAS & CAS & WE
139   variable bank_index : integer;
140   variable state_current : ddr_state_type;
141
142   begin
143
144      command := COMMAND_NOP;
145      bank_index := conv_integer(address(12 downto 11));
146      state_current := state_prev;
147
148      --DDR state machine to determine state_current and command
149      case state_prev is
150         when STATE_POWER_ON =>
151            if active = '1' then
152               if byte_we /= "0000" then
153                  command := address(6 downto 4); --LMR="000"
154               else
155                  state_current := STATE_IDLE; --read transistions to STATE_IDLE
156               end if;
157            end if;
158
159         when STATE_IDLE =>
160            if refresh_cnt(7) = '1' then
161               state_current := STATE_PRECHARGE;
162               command := COMMAND_AUTO_REFRESH;
163            elsif active = '1' and no_start = '0' then
164               state_current := STATE_ROW_ACTIVATE;
165               command := COMMAND_ACTIVE;
166            end if;
167
168         when STATE_ROW_ACTIVATE =>
169            state_current := STATE_ROW_ACTIVE;
170
171         when STATE_ROW_ACTIVE =>
172            if refresh_cnt(7) = '1' then
173               if write_prev = '0' then
174                  state_current := STATE_PRECHARGE;
175                  command := COMMAND_PRECHARGE;
176               end if;
177            elsif active = '1' and no_start = '0' then
178               if bank_open(bank_index) = '0' then
179                  state_current := STATE_ROW_ACTIVATE;
180                  command := COMMAND_ACTIVE;
181               elsif address(25 downto 13) /= address_row(bank_index) then
182                  if write_prev = '0' then
183                     state_current := STATE_PRECHARGE;
184                     command := COMMAND_PRECHARGE;
185                  end if;
186               else
187                  if byte_we /= "0000" then
188                     command := COMMAND_WRITE;
189                  elsif write_prev = '0' then
190                     state_current := STATE_READ;
191                     command := COMMAND_READ;
192                  end if;
193               end if;
194            end if;
195
196         when STATE_READ =>
197            state_current := STATE_READ2;
198
199         when STATE_READ2 =>
200            state_current := STATE_READ3;
201
202         when STATE_READ3 =>
203            if no_stop = '0' then
204               state_current := STATE_ROW_ACTIVE;
205            end if;
206
207         when STATE_PRECHARGE =>
208            state_current := STATE_PRECHARGE2;
209
210         when STATE_PRECHARGE2 =>
211            state_current := STATE_IDLE;
212
213         when others =>
214            state_current := STATE_IDLE;
215      end case; --state_prev
216
217      --rising_edge(clk) domain registers
218      if reset_in = '1' then
219         state_prev <= STATE_POWER_ON;
220         cke_reg <= '0';
221         refresh_cnt <= ZERO(7 downto 0);
222         write_prev <= '0';
223         write_active <= '0';
224         bank_open <= "0000";
225      elsif rising_edge(clk) then
226
227         if active = '1' then
228            cke_reg <= '1';
229         end if;
230
231         if command = COMMAND_WRITE then
232            write_prev <= '1';
233         elsif cycle_count2(2 downto 1) = "11" then
234            write_prev <= '0';
235         end if;
236
237         if command = COMMAND_WRITE then
238            write_active <= '1';
239         elsif cycle_count2 = "100" then
240            write_active <= '0';
241         end if;
242
243         if command = COMMAND_ACTIVE then
244            bank_open(bank_index) <= '1';
245            address_row(bank_index) := address(25 downto 13);
246         end if;
247
248         if command = COMMAND_PRECHARGE then
249            bank_open <= "0000";
250         end if;
251
252         if command = COMMAND_AUTO_REFRESH then
253            refresh_cnt <= ZERO(7 downto 0);
254         else
255            refresh_cnt <= refresh_cnt + 1;
256         end if;
257
258         state_prev <= state_current;
259
260      end if; --rising_edge(clk)
261
262      --rising_edge(clk_2x) domain registers
263      if reset_in = '1' then
264         cycle_count <= "000";
265      elsif rising_edge(clk_2x) then
266         --Cycle_count
267         if (command = COMMAND_READ or command = COMMAND_WRITE) and clk = '1' then
268            cycle_count <= "000";
269         elsif cycle_count /= "111" then
270            cycle_count <= cycle_count + 1;
271         end if;
272
273         clk_p <= clk; --earlier version of not clk
274
275         --Read data (DLL disabled)
276         if cycle_count = "100" then
277            data_read(31 downto 16) <= SD_DQ; --data
278         elsif cycle_count = "101" then
279            data_read(15 downto 0) <= SD_DQ;
280         end if;
281      end if;
282
283      --falling_edge(clk_2x) domain registers
284      if reset_in = '1' then
285         cycle_count2 <= "000";
286         data_write2 <= ZERO(15 downto 0) & ZERO;
287         byte_we_reg2 <= "000000";
288      elsif falling_edge(clk_2x) then
289         cycle_count2 <= cycle_count;
290
291         --Write pipeline
292         if clk = '0' then
293            data_write2 <= data_write2(31 downto 16) & data_w;
294            byte_we_reg2 <= byte_we_reg2(3 downto 2) & byte_we;
295         else
296            data_write2(47 downto 16) <= data_write2(31 downto 0);
297            byte_we_reg2(5 downto 2) <= byte_we_reg2(3 downto 0);
298         end if;
299
300         --Read data (DLL enabled)
301         --if cycle_count = "100" then
302         -- data_read(31 downto 16) <= SD_DQ; --data
303         --elsif cycle_count = "101" then
304         -- data_read(15 downto 0) <= SD_DQ;
305         --end if;
306      end if;
307
308      data_r <= data_read;
309
310      --Write data
311      if write_active = '1' then
312         SD_UDQS <= clk_p; --upper_data_strobe
313         SD_LDQS <= clk_p; --low_data_strobe
314         SD_DQ <= data_write2(47 downto 32); --data
315         SD_UDM <= not byte_we_reg2(5); --upper_byte_enable
316         SD_LDM <= not byte_we_reg2(4); --low_byte_enable
317      else
318         SD_UDQS <= 'Z'; --upper_data_strobe
319         SD_LDQS <= 'Z'; --low_data_strobe
320         SD_DQ <= "ZZZZZZZZZZZZZZZZ"; --data
321         SD_UDM <= 'Z';
322         SD_LDM <= 'Z';
323      end if;
324
325      --DDR control signals
326      SD_CK_P <= clk_p; --clock_positive
327      SD_CK_N <= not clk_p; --clock_negative
328      SD_CKE <= cke_reg; --clock_enable
329
330      SD_BA <= address(12 downto 11); --bank_address
331      if command = COMMAND_ACTIVE or state_current = STATE_POWER_ON then
332         SD_A <= address(25 downto 13); --address row
333      elsif command = COMMAND_READ or command = COMMAND_WRITE then
334         SD_A <= "000" & address(10 downto 2) & "0"; --address col
335      else
336         SD_A <= "0010000000000"; --PERCHARGE all banks
337      end if;
338
339      SD_CS <= not cke_reg; --chip_select
340      SD_RAS <= command(2); --row_address_strobe
341      SD_CAS <= command(1); --column_address_strobe
342      SD_WE <= command(0); --write_enable
343
344      if active = '1' and state_current /= STATE_POWER_ON and
345         command /= COMMAND_WRITE and state_prev /= STATE_READ3 then
346         pause <= '1';
347      else
348         pause <= '0';
349      end if;
350
351   end process; --ddr_proc
352
353end; --architecture logic
354
plasma/logic/default.ipf
plasma/logic/default.ipf_ISE_Backup
plasma/logic/eth_dma.vhd
1---------------------------------------------------------------------
2-- TITLE: Ethernet DMA
3-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4-- DATE CREATED: 12/27/07
5-- FILENAME: eth_dma.vhd
6-- PROJECT: Plasma CPU core
7-- COPYRIGHT: Software placed into the public domain by the author.
8-- Software 'as is' without warranty. Author liable for nothing.
9-- DESCRIPTION:
10-- Ethernet DMA (Direct Memory Access) controller.
11-- Reads four bits and writes four bits from/to the Ethernet PHY each
12-- 2.5 MHz clock cycle. Received data is DMAed starting at 0x13ff0000
13-- transmit data is read from 0x13fd0000.
14-- To send a packet write bytes/4 to Ethernet send register.
15---------------------------------------------------------------------
16library ieee;
17use ieee.std_logic_1164.all;
18use ieee.std_logic_unsigned.all;
19use ieee.std_logic_arith.all;
20use work.mlite_pack.all;
21
22entity eth_dma is port(
23   clk : in std_logic; --25 MHz
24   reset : in std_logic;
25   enable_eth : in std_logic; --enable receive DMA
26   select_eth : in std_logic;
27   rec_isr : out std_logic; --data received
28   send_isr : out std_logic; --transmit done
29
30   address : out std_logic_vector(31 downto 2); --to DDR
31   byte_we : out std_logic_vector(3 downto 0);
32   data_write : out std_logic_vector(31 downto 0);
33   data_read : in std_logic_vector(31 downto 0);
34   pause_in : in std_logic;
35
36   mem_address : in std_logic_vector(31 downto 2); --from CPU
37   mem_byte_we : in std_logic_vector(3 downto 0);
38   data_w : in std_logic_vector(31 downto 0);
39   pause_out : out std_logic;
40
41   E_RX_CLK : in std_logic; --2.5 MHz receive
42   E_RX_DV : in std_logic; --data valid
43   E_RXD : in std_logic_vector(3 downto 0); --receive nibble
44   E_TX_CLK : in std_logic; --2.5 MHz transmit
45   E_TX_EN : out std_logic; --transmit enable
46   E_TXD : out std_logic_vector(3 downto 0)); --transmit nibble
47end; --entity eth_dma
48
49architecture logic of eth_dma is
50   signal rec_clk : std_logic_vector(1 downto 0); --receive
51   signal rec_store : std_logic_vector(31 downto 0); --to DDR
52   signal rec_data : std_logic_vector(27 downto 0);
53   signal rec_cnt : std_logic_vector(2 downto 0); --nibbles
54   signal rec_words : std_logic_vector(13 downto 0);
55   signal rec_dma : std_logic_vector(1 downto 0); --active & request
56   signal rec_done : std_logic;
57
58   signal send_clk : std_logic_vector(1 downto 0); --transmit
59   signal send_read : std_logic_vector(31 downto 0); --from DDR
60   signal send_data : std_logic_vector(31 downto 0);
61   signal send_cnt : std_logic_vector(2 downto 0); --nibbles
62   signal send_words : std_logic_vector(8 downto 0);
63   signal send_level : std_logic_vector(8 downto 0);
64   signal send_dma : std_logic_vector(1 downto 0); --active & request
65   signal send_enable: std_logic;
66
67begin --architecture
68
69   dma_proc: process(clk, reset, enable_eth, select_eth,
70         data_read, pause_in, mem_address, mem_byte_we, data_w,
71         E_RX_CLK, E_RX_DV, E_RXD, E_TX_CLK,
72         rec_clk, rec_store, rec_data,
73         rec_cnt, rec_words, rec_dma, rec_done,
74         send_clk, send_read, send_data, send_cnt, send_words,
75         send_level, send_dma, send_enable)
76   begin
77
78      if reset = '1' then
79         rec_clk <= "00";
80         rec_cnt <= "000";
81         rec_words <= ZERO(13 downto 0);
82         rec_dma <= "00";
83         rec_done <= '0';
84         send_clk <= "00";
85         send_cnt <= "000";
86         send_words <= ZERO(8 downto 0);
87         send_level <= ZERO(8 downto 0);
88         send_dma <= "00";
89         send_enable <= '0';
90      elsif rising_edge(clk) then
91
92         --Receive nibble on low->high E_RX_CLK. Send to DDR every 32 bits.
93         rec_clk <= rec_clk(0) & E_RX_CLK;
94         if rec_clk = "01" and enable_eth = '1' then
95            if E_RX_DV = '1' or rec_cnt /= "000" then
96               if rec_cnt = "111" then
97                  rec_store <= rec_data & E_RXD;
98                  rec_dma(0) <= '1'; --request DMA
99               end if;
100               rec_data <= rec_data(23 downto 0) & E_RXD;
101               rec_cnt <= rec_cnt + 1;
102            end if;
103         end if;
104
105         --Set transmit count or clear receive interrupt
106         if select_eth = '1' then
107            if mem_byte_we /= "0000" then
108               send_cnt <= "000";
109               send_words <= ZERO(8 downto 0);
110               send_level <= data_w(8 downto 0);
111               send_dma(0) <= '1';
112            else
113               rec_done <= '0';
114            end if;
115         end if;
116
117         --Transmit nibble on low->high E_TX_CLK. Get 32 bits from DDR.
118         send_clk <= send_clk(0) & E_TX_CLK;
119         if send_clk = "01" then
120            if send_cnt = "111" then
121               if send_words /= send_level then
122                  send_data <= send_read;
123                  send_dma(0) <= '1';
124                  send_enable <= '1';
125               else
126                  send_enable <= '0';
127               end if;
128            else
129               send_data(31 downto 4) <= send_data(27 downto 0);
130            end if;
131            send_cnt <= send_cnt + 1;
132         end if;
133
134         --Pick which type of DMA operation: bit0 = request; bit1 = active
135         if pause_in = '0' then
136            if rec_dma(1) = '1' then
137               rec_dma <= "00"; --DMA done
138               rec_words <= rec_words + 1;
139               if E_RX_DV = '0' then
140                  rec_done <= '1';
141               end if;
142            elsif send_dma(1) = '1' then
143               send_dma <= "00";
144               send_words <= send_words + 1;
145               send_read <= data_read;
146            elsif rec_dma(0) = '1' then
147               rec_dma(1) <= '1'; --start DMA
148            elsif send_dma(0) = '1' then
149               send_dma(1) <= '1'; --start DMA
150            end if;
151         end if;
152
153      end if; --rising_edge(clk)
154
155      E_TXD <= send_data(31 downto 28);
156      E_TX_EN <= send_enable;
157      rec_isr <= rec_done;
158      if send_words = send_level then
159         send_isr <= '1';
160      else
161         send_isr <= '0';
162      end if;
163
164      if rec_dma(1) = '1' then
165         address <= "0001001111111111" & rec_words; --0x13ff0000
166         byte_we <= "1111";
167         data_write <= rec_store;
168         pause_out <= '1'; --to CPU
169      elsif send_dma(1) = '1' then
170         address <= "000100111111111000000" & send_words; --0x13fe0000
171         byte_we <= "0000";
172         data_write <= data_w;
173         pause_out <= '1';
174      else
175         address <= mem_address; --Send request from CPU to DDR
176         byte_we <= mem_byte_we;
177         data_write <= data_w;
178         pause_out <= '0';
179      end if;
180
181   end process;
182
183end; --architecture logic
plasma/logic/mem_ctrl.vhd
1---------------------------------------------------------------------
2-- TITLE: Memory Controller
3-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4-- DATE CREATED: 1/31/01
5-- FILENAME: mem_ctrl.vhd
6-- PROJECT: Plasma CPU core
7-- COPYRIGHT: Software placed into the public domain by the author.
8-- Software 'as is' without warranty. Author liable for nothing.
9-- DESCRIPTION:
10-- Memory controller for the Plasma CPU.
11-- Supports Big or Little Endian mode.
12---------------------------------------------------------------------
13library ieee;
14use ieee.std_logic_1164.all;
15use work.mlite_pack.all;
16
17entity mem_ctrl is
18   port(clk : in std_logic;
19        reset_in : in std_logic;
20        pause_in : in std_logic;
21        nullify_op : in std_logic;
22        address_pc : in std_logic_vector(31 downto 2);
23        opcode_out : out std_logic_vector(31 downto 0);
24
25        address_in : in std_logic_vector(31 downto 0);
26        mem_source : in mem_source_type;
27        data_write : in std_logic_vector(31 downto 0);
28        data_read : out std_logic_vector(31 downto 0);
29        pause_out : out std_logic;
30
31        address_next : out std_logic_vector(31 downto 2);
32        byte_we_next : out std_logic_vector(3 downto 0);
33
34        address : out std_logic_vector(31 downto 2);
35        byte_we : out std_logic_vector(3 downto 0);
36        data_w : out std_logic_vector(31 downto 0);
37        data_r : in std_logic_vector(31 downto 0));
38end; --entity mem_ctrl
39
40architecture logic of mem_ctrl is
41   --"00" = big_endian; "11" = little_endian
42   constant ENDIAN_MODE : std_logic_vector(1 downto 0) := "00";
43   signal opcode_reg : std_logic_vector(31 downto 0);
44   signal next_opcode_reg : std_logic_vector(31 downto 0);
45   signal address_reg : std_logic_vector(31 downto 2);
46   signal byte_we_reg : std_logic_vector(3 downto 0);
47
48   signal mem_state_reg : std_logic;
49   constant STATE_ADDR : std_logic := '0';
50   constant STATE_ACCESS : std_logic := '1';
51
52begin
53
54mem_proc: process(clk, reset_in, pause_in, nullify_op,
55                  address_pc, address_in, mem_source, data_write,
56                  data_r, opcode_reg, next_opcode_reg, mem_state_reg,
57                  address_reg, byte_we_reg)
58   variable address_var : std_logic_vector(31 downto 2);
59   variable data_read_var : std_logic_vector(31 downto 0);
60   variable data_write_var : std_logic_vector(31 downto 0);
61   variable opcode_next : std_logic_vector(31 downto 0);
62   variable byte_we_var : std_logic_vector(3 downto 0);
63   variable mem_state_next : std_logic;
64   variable pause_var : std_logic;
65   variable bits : std_logic_vector(1 downto 0);
66begin
67   byte_we_var := "0000";
68   pause_var := '0';
69   data_read_var := ZERO;
70   data_write_var := ZERO;
71   mem_state_next := mem_state_reg;
72   opcode_next := opcode_reg;
73
74   case mem_source is
75   when MEM_READ32 =>
76      data_read_var := data_r;
77
78   when MEM_READ16 | MEM_READ16S =>
79      if address_in(1) = ENDIAN_MODE(1) then
80         data_read_var(15 downto 0) := data_r(31 downto 16);
81      else
82         data_read_var(15 downto 0) := data_r(15 downto 0);
83      end if;
84      if mem_source = MEM_READ16 or data_read_var(15) = '0' then
85         data_read_var(31 downto 16) := ZERO(31 downto 16);
86      else
87         data_read_var(31 downto 16) := ONES(31 downto 16);
88      end if;
89
90   when MEM_READ8 | MEM_READ8S =>
91      bits := address_in(1 downto 0) xor ENDIAN_MODE;
92      case bits is
93      when "00" => data_read_var(7 downto 0) := data_r(31 downto 24);
94      when "01" => data_read_var(7 downto 0) := data_r(23 downto 16);
95      when "10" => data_read_var(7 downto 0) := data_r(15 downto 8);
96      when others => data_read_var(7 downto 0) := data_r(7 downto 0);
97      end case;
98      if mem_source = MEM_READ8 or data_read_var(7) = '0' then
99         data_read_var(31 downto 8) := ZERO(31 downto 8);
100      else
101         data_read_var(31 downto 8) := ONES(31 downto 8);
102      end if;
103
104   when MEM_WRITE32 =>
105      data_write_var := data_write;
106      byte_we_var := "1111";
107
108   when MEM_WRITE16 =>
109      data_write_var := data_write(15 downto 0) & data_write(15 downto 0);
110      if address_in(1) = ENDIAN_MODE(1) then
111         byte_we_var := "1100";
112      else
113         byte_we_var := "0011";
114      end if;
115
116   when MEM_WRITE8 =>
117      data_write_var := data_write(7 downto 0) & data_write(7 downto 0) &
118                  data_write(7 downto 0) & data_write(7 downto 0);
119      bits := address_in(1 downto 0) xor ENDIAN_MODE;
120      case bits is
121      when "00" =>
122         byte_we_var := "1000";
123      when "01" =>
124         byte_we_var := "0100";
125      when "10" =>
126         byte_we_var := "0010";
127      when others =>
128         byte_we_var := "0001";
129      end case;
130
131   when others =>
132   end case;
133
134   if mem_source = MEM_FETCH then --opcode fetch
135      address_var := address_pc;
136      opcode_next := data_r;
137      mem_state_next := STATE_ADDR;
138   else
139      if mem_state_reg = STATE_ADDR then
140         if pause_in = '0' then
141            address_var := address_in(31 downto 2);
142            mem_state_next := STATE_ACCESS;
143            pause_var := '1';
144         else
145            address_var := address_pc;
146            byte_we_var := "0000";
147         end if;
148      else --STATE_ACCESS
149         if pause_in = '0' then
150            address_var := address_pc;
151            opcode_next := next_opcode_reg;
152            mem_state_next := STATE_ADDR;
153            byte_we_var := "0000";
154         else
155            address_var := address_in(31 downto 2);
156            byte_we_var := "0000";
157         end if;
158      end if;
159   end if;
160
161   if nullify_op = '1' and pause_in = '0' then
162      opcode_next := ZERO; --NOP after beql
163   end if;
164
165   if reset_in = '1' then
166      mem_state_reg <= STATE_ADDR;
167      opcode_reg <= ZERO;
168      next_opcode_reg <= ZERO;
169      address_reg <= ZERO(31 downto 2);
170      byte_we_reg <= "0000";
171   elsif rising_edge(clk) then
172      if pause_in = '0' then
173         address_reg <= address_var;
174         byte_we_reg <= byte_we_var;
175         mem_state_reg <= mem_state_next;
176         opcode_reg <= opcode_next;
177         if mem_state_reg = STATE_ADDR then
178            next_opcode_reg <= data_r;
179         end if;
180      end if;
181   end if;
182
183   opcode_out <= opcode_reg;
184   data_read <= data_read_var;
185   pause_out <= pause_var;
186
187   address_next <= address_var;
188   byte_we_next <= byte_we_var;
189
190   address <= address_reg;
191   byte_we <= byte_we_reg;
192   data_w <= data_write_var;
193
194end process; --data_proc
195
196end; --architecture logic
plasma/logic/mlite_cpu.vhd
1---------------------------------------------------------------------
2-- TITLE: Plasma CPU core
3-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4-- DATE CREATED: 2/15/01
5-- FILENAME: mlite_cpu.vhd
6-- PROJECT: Plasma CPU core
7-- COPYRIGHT: Software placed into the public domain by the author.
8-- Software 'as is' without warranty. Author liable for nothing.
9-- NOTE: MIPS(tm) and MIPS I(tm) are registered trademarks of MIPS
10-- Technologies. MIPS Technologies does not endorse and is not
11-- associated with this project.
12-- DESCRIPTION:
13-- Top level VHDL document that ties the nine other entities together.
14--
15-- Executes all MIPS I(tm) opcodes but exceptions and non-aligned
16-- memory accesses. Based on information found in:
17-- "MIPS RISC Architecture" by Gerry Kane and Joe Heinrich
18-- and "The Designer's Guide to VHDL" by Peter J. Ashenden
19--
20-- The CPU is implemented as a two or three stage pipeline.
21-- An add instruction would take the following steps (see cpu.gif):
22-- Stage #0:
23-- 1. The "pc_next" entity passes the program counter (PC) to the
24-- "mem_ctrl" entity which fetches the opcode from memory.
25-- Stage #1:
26-- 2. The memory returns the opcode.
27-- Stage #2:
28-- 3. "Mem_ctrl" passes the opcode to the "control" entity.
29-- 4. "Control" converts the 32-bit opcode to a 60-bit VLWI opcode
30-- and sends control signals to the other entities.
31-- 5. Based on the rs_index and rt_index control signals, "reg_bank"
32-- sends the 32-bit reg_source and reg_target to "bus_mux".
33-- 6. Based on the a_source and b_source control signals, "bus_mux"
34-- multiplexes reg_source onto a_bus and reg_target onto b_bus.
35-- Stage #3 (part of stage #2 if using two stage pipeline):
36-- 7. Based on the alu_func control signals, "alu" adds the values
37-- from a_bus and b_bus and places the result on c_bus.
38-- 8. Based on the c_source control signals, "bus_bux" multiplexes
39-- c_bus onto reg_dest.
40-- 9. Based on the rd_index control signal, "reg_bank" saves
41-- reg_dest into the correct register.
42-- Stage #3b:
43-- 10. Read or write memory if needed.
44--
45-- All signals are active high.
46-- Here are the signals for writing a character to address 0xffff
47-- when using a two stage pipeline:
48--
49-- Program:
50-- addr value opcode
51-- =============================
52-- 3c: 00000000 nop
53-- 40: 34040041 li $a0,0x41
54-- 44: 3405ffff li $a1,0xffff
55-- 48: a0a40000 sb $a0,0($a1)
56-- 4c: 00000000 nop
57-- 50: 00000000 nop
58--
59-- intr_in mem_pause
60-- reset_in byte_we Stages
61-- ns address data_w data_r 40 44 48 4c 50
62-- 3600 0 0 00000040 00000000 34040041 0 0 1
63-- 3700 0 0 00000044 00000000 3405FFFF 0 0 2 1
64-- 3800 0 0 00000048 00000000 A0A40000 0 0 2 1
65-- 3900 0 0 0000004C 41414141 00000000 0 0 2 1
66-- 4000 0 0 0000FFFC 41414141 XXXXXX41 1 0 3 2
67-- 4100 0 0 00000050 00000000 00000000 0 0 1
68---------------------------------------------------------------------
69library ieee;
70use work.mlite_pack.all;
71use ieee.std_logic_1164.all;
72use ieee.std_logic_unsigned.all;
73
74entity mlite_cpu is
75   generic(memory_type : string := "XILINX_16X"; --ALTERA_LPM, or DUAL_PORT_
76           mult_type : string := "DEFAULT"; --AREA_OPTIMIZED
77           shifter_type : string := "DEFAULT"; --AREA_OPTIMIZED
78           alu_type : string := "DEFAULT"; --AREA_OPTIMIZED
79           pipeline_stages : natural := 2); --2 or 3
80   port(clk : in std_logic;
81        reset_in : in std_logic;
82        intr_in : in std_logic;
83
84        address_next : out std_logic_vector(31 downto 2); --for synch ram
85        byte_we_next : out std_logic_vector(3 downto 0);
86
87        address : out std_logic_vector(31 downto 2);
88        byte_we : out std_logic_vector(3 downto 0);
89        data_w : out std_logic_vector(31 downto 0);
90        data_r : in std_logic_vector(31 downto 0);
91        mem_pause : in std_logic);
92end; --entity mlite_cpu
93
94architecture logic of mlite_cpu is
95   --When using a two stage pipeline "sigD <= sig".
96   --When using a three stage pipeline "sigD <= sig when rising_edge(clk)",
97   -- so sigD is delayed by one clock cycle.
98   signal opcode : std_logic_vector(31 downto 0);
99   signal rs_index : std_logic_vector(5 downto 0);
100   signal rt_index : std_logic_vector(5 downto 0);
101   signal rd_index : std_logic_vector(5 downto 0);
102   signal rd_indexD : std_logic_vector(5 downto 0);
103   signal reg_source : std_logic_vector(31 downto 0);
104   signal reg_target : std_logic_vector(31 downto 0);
105   signal reg_dest : std_logic_vector(31 downto 0);
106   signal reg_destD : std_logic_vector(31 downto 0);
107   signal a_bus : std_logic_vector(31 downto 0);
108   signal a_busD : std_logic_vector(31 downto 0);
109   signal b_bus : std_logic_vector(31 downto 0);
110   signal b_busD : std_logic_vector(31 downto 0);
111   signal c_bus : std_logic_vector(31 downto 0);
112   signal c_alu : std_logic_vector(31 downto 0);
113   signal c_shift : std_logic_vector(31 downto 0);
114   signal c_mult : std_logic_vector(31 downto 0);
115   signal c_memory : std_logic_vector(31 downto 0);
116   signal imm : std_logic_vector(15 downto 0);
117   signal pc_future : std_logic_vector(31 downto 2);
118   signal pc_current : std_logic_vector(31 downto 2);
119   signal pc_plus4 : std_logic_vector(31 downto 2);
120   signal alu_func : alu_function_type;
121   signal alu_funcD : alu_function_type;
122   signal shift_func : shift_function_type;
123   signal shift_funcD : shift_function_type;
124   signal mult_func : mult_function_type;
125   signal mult_funcD : mult_function_type;
126   signal branch_func : branch_function_type;
127   signal take_branch : std_logic;
128   signal a_source : a_source_type;
129   signal b_source : b_source_type;
130   signal c_source : c_source_type;
131   signal pc_source : pc_source_type;
132   signal mem_source : mem_source_type;
133   signal pause_mult : std_logic;
134   signal pause_ctrl : std_logic;
135   signal pause_pipeline : std_logic;
136   signal pause_any : std_logic;
137   signal pause_non_ctrl : std_logic;
138   signal pause_bank : std_logic;
139   signal nullify_op : std_logic;
140   signal intr_enable : std_logic;
141   signal intr_signal : std_logic;
142   signal exception_sig : std_logic;
143   signal reset_reg : std_logic_vector(3 downto 0);
144   signal reset : std_logic;
145begin --architecture
146
147   pause_any <= (mem_pause or pause_ctrl) or (pause_mult or pause_pipeline);
148   pause_non_ctrl <= (mem_pause or pause_mult) or pause_pipeline;
149   pause_bank <= (mem_pause or pause_ctrl or pause_mult) and not pause_pipeline;
150   nullify_op <= '1' when (pc_source = FROM_LBRANCH and take_branch = '0')
151                          or intr_signal = '1' or exception_sig = '1'
152                          else '0';
153   c_bus <= c_alu or c_shift or c_mult;
154   reset <= '1' when reset_in = '1' or reset_reg /= "1111" else '0';
155
156   --synchronize reset and interrupt pins
157   intr_proc: process(clk, reset_in, reset_reg, intr_in, intr_enable,
158      pc_source, pc_current, pause_any)
159   begin
160      if reset_in = '1' then
161         reset_reg <= "0000";
162         intr_signal <= '0';
163      elsif rising_edge(clk) then
164         if reset_reg /= "1111" then
165            reset_reg <= reset_reg + 1;
166         end if;
167
168         --don't try to interrupt a multi-cycle instruction
169         if pause_any = '0' then
170            if intr_in = '1' and intr_enable = '1' and
171                  pc_source = FROM_INC4 then
172               --the epc will contain pc+4
173               intr_signal <= '1';
174            else
175               intr_signal <= '0';
176            end if;
177         end if;
178
179      end if;
180   end process;
181
182   u1_pc_next: pc_next PORT MAP (
183        clk => clk,
184        reset_in => reset,
185        take_branch => take_branch,
186        pause_in => pause_any,
187        pc_new => c_bus(31 downto 2),
188        opcode25_0 => opcode(25 downto 0),
189        pc_source => pc_source,
190        pc_future => pc_future,
191        pc_current => pc_current,
192        pc_plus4 => pc_plus4);
193
194   u2_mem_ctrl: mem_ctrl
195      PORT MAP (
196        clk => clk,
197        reset_in => reset,
198        pause_in => pause_non_ctrl,
199        nullify_op => nullify_op,
200        address_pc => pc_future,
201        opcode_out => opcode,
202
203        address_in => c_bus,
204        mem_source => mem_source,
205        data_write => reg_target,
206        data_read => c_memory,
207        pause_out => pause_ctrl,
208
209        address_next => address_next,
210        byte_we_next => byte_we_next,
211
212        address => address,
213        byte_we => byte_we,
214        data_w => data_w,
215        data_r => data_r);
216
217   u3_control: control PORT MAP (
218        opcode => opcode,
219        intr_signal => intr_signal,
220        rs_index => rs_index,
221        rt_index => rt_index,
222        rd_index => rd_index,
223        imm_out => imm,
224        alu_func => alu_func,
225        shift_func => shift_func,
226        mult_func => mult_func,
227        branch_func => branch_func,
228        a_source_out => a_source,
229        b_source_out => b_source,
230        c_source_out => c_source,
231        pc_source_out=> pc_source,
232        mem_source_out=> mem_source,
233        exception_out=> exception_sig);
234
235   u4_reg_bank: reg_bank
236      generic map(memory_type => memory_type)
237      port map (
238        clk => clk,
239        reset_in => reset,
240        pause => pause_bank,
241        rs_index => rs_index,
242        rt_index => rt_index,
243        rd_index => rd_indexD,
244        reg_source_out => reg_source,
245        reg_target_out => reg_target,
246        reg_dest_new => reg_destD,
247        intr_enable => intr_enable);
248
249   u5_bus_mux: bus_mux port map (
250        imm_in => imm,
251        reg_source => reg_source,
252        a_mux => a_source,
253        a_out => a_bus,
254
255        reg_target => reg_target,
256        b_mux => b_source,
257        b_out => b_bus,
258
259        c_bus => c_bus,
260        c_memory => c_memory,
261        c_pc => pc_current,
262        c_pc_plus4 => pc_plus4,
263        c_mux => c_source,
264        reg_dest_out => reg_dest,
265
266        branch_func => branch_func,
267        take_branch => take_branch);
268
269   u6_alu: alu
270      generic map (alu_type => alu_type)
271      port map (
272        a_in => a_busD,
273        b_in => b_busD,
274        alu_function => alu_funcD,
275        c_alu => c_alu);
276
277   u7_shifter: shifter
278      generic map (shifter_type => shifter_type)
279      port map (
280        value => b_busD,
281        shift_amount => a_busD(4 downto 0),
282        shift_func => shift_funcD,
283        c_shift => c_shift);
284
285   u8_mult: mult
286      generic map (mult_type => mult_type)
287      port map (
288        clk => clk,
289        reset_in => reset,
290        a => a_busD,
291        b => b_busD,
292        mult_func => mult_funcD,
293        c_mult => c_mult,
294        pause_out => pause_mult);
295
296   pipeline2: if pipeline_stages <= 2 generate
297      a_busD <= a_bus;
298      b_busD <= b_bus;
299      alu_funcD <= alu_func;
300      shift_funcD <= shift_func;
301      mult_funcD <= mult_func;
302      rd_indexD <= rd_index;
303      reg_destD <= reg_dest;
304      pause_pipeline <= '0';
305   end generate; --pipeline2
306
307   pipeline3: if pipeline_stages > 2 generate
308      --When operating in three stage pipeline mode, the following signals
309      --are delayed by one clock cycle: a_bus, b_bus, alu/shift/mult_func,
310      --c_source, and rd_index.
311   u9_pipeline: pipeline port map (
312        clk => clk,
313        reset => reset,
314        a_bus => a_bus,
315        a_busD => a_busD,
316        b_bus => b_bus,
317        b_busD => b_busD,
318        alu_func => alu_func,
319        alu_funcD => alu_funcD,
320        shift_func => shift_func,
321        shift_funcD => shift_funcD,
322        mult_func => mult_func,
323        mult_funcD => mult_funcD,
324        reg_dest => reg_dest,
325        reg_destD => reg_destD,
326        rd_index => rd_index,
327        rd_indexD => rd_indexD,
328
329        rs_index => rs_index,
330        rt_index => rt_index,
331        pc_source => pc_source,
332        mem_source => mem_source,
333        a_source => a_source,
334        b_source => b_source,
335        c_source => c_source,
336        c_bus => c_bus,
337        pause_any => pause_any,
338        pause_pipeline => pause_pipeline);
339
340   end generate; --pipeline3
341
342end; --architecture logic
plasma/logic/mlite_pack.vhd
1---------------------------------------------------------------------
2-- TITLE: Plasma Misc. Package
3-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4-- DATE CREATED: 2/15/01
5-- FILENAME: mlite_pack.vhd
6-- PROJECT: Plasma CPU core
7-- COPYRIGHT: Software placed into the public domain by the author.
8-- Software 'as is' without warranty. Author liable for nothing.
9-- DESCRIPTION:
10-- Data types, constants, and add functions needed for the Plasma CPU.
11---------------------------------------------------------------------
12library ieee;
13use ieee.std_logic_1164.all;
14
15package mlite_pack is
16   constant ZERO : std_logic_vector(31 downto 0) :=
17      "00000000000000000000000000000000";
18   constant ONES : std_logic_vector(31 downto 0) :=
19      "11111111111111111111111111111111";
20   --make HIGH_Z equal to ZERO if compiler complains
21   constant HIGH_Z : std_logic_vector(31 downto 0) :=
22      "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ";
23
24   subtype alu_function_type is std_logic_vector(3 downto 0);
25   constant ALU_NOTHING : alu_function_type := "0000";
26   constant ALU_ADD : alu_function_type := "0001";
27   constant ALU_SUBTRACT : alu_function_type := "0010";
28   constant ALU_LESS_THAN : alu_function_type := "0011";
29   constant ALU_LESS_THAN_SIGNED : alu_function_type := "0100";
30   constant ALU_OR : alu_function_type := "0101";
31   constant ALU_AND : alu_function_type := "0110";
32   constant ALU_XOR : alu_function_type := "0111";
33   constant ALU_NOR : alu_function_type := "1000";
34
35   subtype shift_function_type is std_logic_vector(1 downto 0);
36   constant SHIFT_NOTHING : shift_function_type := "00";
37   constant SHIFT_LEFT_UNSIGNED : shift_function_type := "01";
38   constant SHIFT_RIGHT_SIGNED : shift_function_type := "11";
39   constant SHIFT_RIGHT_UNSIGNED : shift_function_type := "10";
40
41   subtype mult_function_type is std_logic_vector(3 downto 0);
42   constant MULT_NOTHING : mult_function_type := "0000";
43   constant MULT_READ_LO : mult_function_type := "0001";
44   constant MULT_READ_HI : mult_function_type := "0010";
45   constant MULT_WRITE_LO : mult_function_type := "0011";
46   constant MULT_WRITE_HI : mult_function_type := "0100";
47   constant MULT_MULT : mult_function_type := "0101";
48   constant MULT_SIGNED_MULT : mult_function_type := "0110";
49   constant MULT_DIVIDE : mult_function_type := "0111";
50   constant MULT_SIGNED_DIVIDE : mult_function_type := "1000";
51
52   subtype a_source_type is std_logic_vector(1 downto 0);
53   constant A_FROM_REG_SOURCE : a_source_type := "00";
54   constant A_FROM_IMM10_6 : a_source_type := "01";
55   constant A_FROM_PC : a_source_type := "10";
56
57   subtype b_source_type is std_logic_vector(1 downto 0);
58   constant B_FROM_REG_TARGET : b_source_type := "00";
59   constant B_FROM_IMM : b_source_type := "01";
60   constant B_FROM_SIGNED_IMM : b_source_type := "10";
61   constant B_FROM_IMMX4 : b_source_type := "11";
62
63   subtype c_source_type is std_logic_vector(2 downto 0);
64   constant C_FROM_NULL : c_source_type := "000";
65   constant C_FROM_ALU : c_source_type := "001";
66   constant C_FROM_SHIFT : c_source_type := "001"; --same as alu
67   constant C_FROM_MULT : c_source_type := "001"; --same as alu
68   constant C_FROM_MEMORY : c_source_type := "010";
69   constant C_FROM_PC : c_source_type := "011";
70   constant C_FROM_PC_PLUS4 : c_source_type := "100";
71   constant C_FROM_IMM_SHIFT16: c_source_type := "101";
72   constant C_FROM_REG_SOURCEN: c_source_type := "110";
73
74   subtype pc_source_type is std_logic_vector(1 downto 0);
75   constant FROM_INC4 : pc_source_type := "00";
76   constant FROM_OPCODE25_0 : pc_source_type := "01";
77   constant FROM_BRANCH : pc_source_type := "10";
78   constant FROM_LBRANCH : pc_source_type := "11";
79
80   subtype branch_function_type is std_logic_vector(2 downto 0);
81   constant BRANCH_LTZ : branch_function_type := "000";
82   constant BRANCH_LEZ : branch_function_type := "001";
83   constant BRANCH_EQ : branch_function_type := "010";
84   constant BRANCH_NE : branch_function_type := "011";
85   constant BRANCH_GEZ : branch_function_type := "100";
86   constant BRANCH_GTZ : branch_function_type := "101";
87   constant BRANCH_YES : branch_function_type := "110";
88   constant BRANCH_NO : branch_function_type := "111";
89
90   -- mode(32=1,16=2,8=3), signed, write
91   subtype mem_source_type is std_logic_vector(3 downto 0);
92   constant MEM_FETCH : mem_source_type := "0000";
93   constant MEM_READ32 : mem_source_type := "0100";
94   constant MEM_WRITE32 : mem_source_type := "0101";
95   constant MEM_READ16 : mem_source_type := "1000";
96   constant MEM_READ16S : mem_source_type := "1010";
97   constant MEM_WRITE16 : mem_source_type := "1001";
98   constant MEM_READ8 : mem_source_type := "1100";
99   constant MEM_READ8S : mem_source_type := "1110";
100   constant MEM_WRITE8 : mem_source_type := "1101";
101
102   function bv_adder(a : in std_logic_vector;
103                     b : in std_logic_vector;
104                     do_add: in std_logic) return std_logic_vector;
105   function bv_negate(a : in std_logic_vector) return std_logic_vector;
106   function bv_increment(a : in std_logic_vector(31 downto 2)
107                         ) return std_logic_vector;
108   function bv_inc(a : in std_logic_vector
109                  ) return std_logic_vector;
110
111   -- For Altera
112   COMPONENT lpm_ram_dp
113      generic (
114         LPM_WIDTH : natural; -- MUST be greater than 0
115         LPM_WIDTHAD : natural; -- MUST be greater than 0
116         LPM_NUMWORDS : natural := 0;
117         LPM_INDATA : string := "REGISTERED";
118         LPM_OUTDATA : string := "REGISTERED";
119         LPM_RDADDRESS_CONTROL : string := "REGISTERED";
120         LPM_WRADDRESS_CONTROL : string := "REGISTERED";
121         LPM_FILE : string := "UNUSED";
122         LPM_TYPE : string := "LPM_RAM_DP";
123         USE_EAB : string := "OFF";
124         INTENDED_DEVICE_FAMILY : string := "UNUSED";
125         RDEN_USED : string := "TRUE";
126         LPM_HINT : string := "UNUSED");
127      port (
128         RDCLOCK : in std_logic := '0';
129         RDCLKEN : in std_logic := '1';
130         RDADDRESS : in std_logic_vector(LPM_WIDTHAD-1 downto 0);
131         RDEN : in std_logic := '1';
132         DATA : in std_logic_vector(LPM_WIDTH-1 downto 0);
133         WRADDRESS : in std_logic_vector(LPM_WIDTHAD-1 downto 0);
134         WREN : in std_logic;
135         WRCLOCK : in std_logic := '0';
136         WRCLKEN : in std_logic := '1';
137         Q : out std_logic_vector(LPM_WIDTH-1 downto 0));
138   END COMPONENT;
139
140   -- For Altera
141   component LPM_RAM_DQ
142      generic (
143         LPM_WIDTH : natural; -- MUST be greater than 0
144         LPM_WIDTHAD : natural; -- MUST be greater than 0
145         LPM_NUMWORDS : natural := 0;
146         LPM_INDATA : string := "REGISTERED";
147         LPM_ADDRESS_CONTROL: string := "REGISTERED";
148         LPM_OUTDATA : string := "REGISTERED";
149         LPM_FILE : string := "UNUSED";
150         LPM_TYPE : string := "LPM_RAM_DQ";
151         USE_EAB : string := "OFF";
152         INTENDED_DEVICE_FAMILY : string := "UNUSED";
153         LPM_HINT : string := "UNUSED");
154        port (
155         DATA : in std_logic_vector(LPM_WIDTH-1 downto 0);
156         ADDRESS : in std_logic_vector(LPM_WIDTHAD-1 downto 0);
157         INCLOCK : in std_logic := '0';
158         OUTCLOCK : in std_logic := '0';
159         WE : in std_logic;
160         Q : out std_logic_vector(LPM_WIDTH-1 downto 0));
161   end component;
162
163   -- For Xilinx
164   component RAM16X1D
165      -- synthesis translate_off
166      generic (INIT : bit_vector := X"16");
167      -- synthesis translate_on
168      port (DPO : out STD_ULOGIC;
169            SPO : out STD_ULOGIC;
170            A0 : in STD_ULOGIC;
171            A1 : in STD_ULOGIC;
172            A2 : in STD_ULOGIC;
173            A3 : in STD_ULOGIC;
174            D : in STD_ULOGIC;
175            DPRA0 : in STD_ULOGIC;
176            DPRA1 : in STD_ULOGIC;
177            DPRA2 : in STD_ULOGIC;
178            DPRA3 : in STD_ULOGIC;
179            WCLK : in STD_ULOGIC;
180            WE : in STD_ULOGIC);
181   end component;
182
183   component pc_next
184      port(clk : in std_logic;
185           reset_in : in std_logic;
186           pc_new : in std_logic_vector(31 downto 2);
187           take_branch : in std_logic;
188           pause_in : in std_logic;
189           opcode25_0 : in std_logic_vector(25 downto 0);
190           pc_source : in pc_source_type;
191           pc_future : out std_logic_vector(31 downto 2);
192           pc_current : out std_logic_vector(31 downto 2);
193           pc_plus4 : out std_logic_vector(31 downto 2));
194   end component;
195
196   component mem_ctrl
197      port(clk : in std_logic;
198           reset_in : in std_logic;
199           pause_in : in std_logic;
200           nullify_op : in std_logic;
201           address_pc : in std_logic_vector(31 downto 2);
202           opcode_out : out std_logic_vector(31 downto 0);
203
204           address_in : in std_logic_vector(31 downto 0);
205           mem_source : in mem_source_type;
206           data_write : in std_logic_vector(31 downto 0);
207           data_read : out std_logic_vector(31 downto 0);
208           pause_out : out std_logic;
209
210           address_next : out std_logic_vector(31 downto 2);
211           byte_we_next : out std_logic_vector(3 downto 0);
212
213           address : out std_logic_vector(31 downto 2);
214           byte_we : out std_logic_vector(3 downto 0);
215           data_w : out std_logic_vector(31 downto 0);
216           data_r : in std_logic_vector(31 downto 0));
217   end component;
218
219   component control
220      port(opcode : in std_logic_vector(31 downto 0);
221           intr_signal : in std_logic;
222           rs_index : out std_logic_vector(5 downto 0);
223           rt_index : out std_logic_vector(5 downto 0);
224           rd_index : out std_logic_vector(5 downto 0);
225           imm_out : out std_logic_vector(15 downto 0);
226           alu_func : out alu_function_type;
227           shift_func : out shift_function_type;
228           mult_func : out mult_function_type;
229           branch_func : out branch_function_type;
230           a_source_out : out a_source_type;
231           b_source_out : out b_source_type;
232           c_source_out : out c_source_type;
233           pc_source_out: out pc_source_type;
234           mem_source_out:out mem_source_type;
235           exception_out: out std_logic);
236   end component;
237
238   component reg_bank
239      generic(memory_type : string := "XILINX_16X");
240      port(clk : in std_logic;
241           reset_in : in std_logic;
242           pause : in std_logic;
243           rs_index : in std_logic_vector(5 downto 0);
244           rt_index : in std_logic_vector(5 downto 0);
245           rd_index : in std_logic_vector(5 downto 0);
246           reg_source_out : out std_logic_vector(31 downto 0);
247           reg_target_out : out std_logic_vector(31 downto 0);
248           reg_dest_new : in std_logic_vector(31 downto 0);
249           intr_enable : out std_logic);
250   end component;
251
252   component bus_mux
253      port(imm_in : in std_logic_vector(15 downto 0);
254           reg_source : in std_logic_vector(31 downto 0);
255           a_mux : in a_source_type;
256           a_out : out std_logic_vector(31 downto 0);
257
258           reg_target : in std_logic_vector(31 downto 0);
259           b_mux : in b_source_type;
260           b_out : out std_logic_vector(31 downto 0);
261
262           c_bus : in std_logic_vector(31 downto 0);
263           c_memory : in std_logic_vector(31 downto 0);
264           c_pc : in std_logic_vector(31 downto 2);
265           c_pc_plus4 : in std_logic_vector(31 downto 2);
266           c_mux : in c_source_type;
267           reg_dest_out : out std_logic_vector(31 downto 0);
268
269           branch_func : in branch_function_type;
270           take_branch : out std_logic);
271   end component;
272
273   component alu
274      generic(alu_type : string := "DEFAULT");
275      port(a_in : in std_logic_vector(31 downto 0);
276           b_in : in std_logic_vector(31 downto 0);
277           alu_function : in alu_function_type;
278           c_alu : out std_logic_vector(31 downto 0));
279   end component;
280
281   component shifter
282      generic(shifter_type : string := "DEFAULT" );
283      port(value : in std_logic_vector(31 downto 0);
284           shift_amount : in std_logic_vector(4 downto 0);
285           shift_func : in shift_function_type;
286           c_shift : out std_logic_vector(31 downto 0));
287   end component;
288
289   component mult
290      generic(mult_type : string := "DEFAULT");
291      port(clk : in std_logic;
292           reset_in : in std_logic;
293           a, b : in std_logic_vector(31 downto 0);
294           mult_func : in mult_function_type;
295           c_mult : out std_logic_vector(31 downto 0);
296           pause_out : out std_logic);
297   end component;
298
299   component pipeline
300      port(clk : in std_logic;
301           reset : in std_logic;
302           a_bus : in std_logic_vector(31 downto 0);
303           a_busD : out std_logic_vector(31 downto 0);
304           b_bus : in std_logic_vector(31 downto 0);
305           b_busD : out std_logic_vector(31 downto 0);
306           alu_func : in alu_function_type;
307           alu_funcD : out alu_function_type;
308           shift_func : in shift_function_type;
309           shift_funcD : out shift_function_type;
310           mult_func : in mult_function_type;
311           mult_funcD : out mult_function_type;
312           reg_dest : in std_logic_vector(31 downto 0);
313           reg_destD : out std_logic_vector(31 downto 0);
314           rd_index : in std_logic_vector(5 downto 0);
315           rd_indexD : out std_logic_vector(5 downto 0);
316
317           rs_index : in std_logic_vector(5 downto 0);
318           rt_index : in std_logic_vector(5 downto 0);
319           pc_source : in pc_source_type;
320           mem_source : in mem_source_type;
321           a_source : in a_source_type;
322           b_source : in b_source_type;
323           c_source : in c_source_type;
324           c_bus : in std_logic_vector(31 downto 0);
325           pause_any : in std_logic;
326           pause_pipeline : out std_logic);
327   end component;
328
329   component mlite_cpu
330      generic(memory_type : string := "XILINX_16X"; --ALTERA_LPM, or DUAL_PORT_
331              mult_type : string := "DEFAULT";
332              shifter_type : string := "DEFAULT";
333              alu_type : string := "DEFAULT";
334              pipeline_stages : natural := 2); --2 or 3
335      port(clk : in std_logic;
336           reset_in : in std_logic;
337           intr_in : in std_logic;
338
339           address_next : out std_logic_vector(31 downto 2); --for synch ram
340           byte_we_next : out std_logic_vector(3 downto 0);
341
342           address : out std_logic_vector(31 downto 2);
343           byte_we : out std_logic_vector(3 downto 0);
344           data_w : out std_logic_vector(31 downto 0);
345           data_r : in std_logic_vector(31 downto 0);
346           mem_pause : in std_logic);
347   end component;
348
349   component cache
350      generic(memory_type : string := "DEFAULT");
351
352      port(clk : in std_logic;
353           reset : in std_logic;
354           address_next : in std_logic_vector(31 downto 2);
355           byte_we_next : in std_logic_vector(3 downto 0);
356           cpu_address : in std_logic_vector(31 downto 2);
357           mem_busy : in std_logic;
358
359           cache_check : out std_logic; --Stage1: address_next in first 2MB DDR
360           cache_checking : out std_logic; --Stage2: cache checking
361           cache_miss : out std_logic); --Stage2-3: cache miss
362   end component; --cache
363
364   component ram
365      generic(memory_type : string := "DEFAULT");
366      port(clk : in std_logic;
367           enable : in std_logic;
368           write_byte_enable : in std_logic_vector(3 downto 0);
369           address : in std_logic_vector(31 downto 2);
370           data_write : in std_logic_vector(31 downto 0);
371           data_read : out std_logic_vector(31 downto 0));
372   end component; --ram
373
374   component uart
375      generic(log_file : string := "UNUSED");
376      port(clk : in std_logic;
377           reset : in std_logic;
378           enable_read : in std_logic;
379           enable_write : in std_logic;
380           data_in : in std_logic_vector(7 downto 0);
381           data_out : out std_logic_vector(7 downto 0);
382           uart_read : in std_logic;
383           uart_write : out std_logic;
384           busy_write : out std_logic;
385           data_avail : out std_logic);
386   end component; --uart
387
388   component eth_dma
389      port(clk : in std_logic; --25 MHz
390           reset : in std_logic;
391           enable_eth : in std_logic;
392           select_eth : in std_logic;
393           rec_isr : out std_logic;
394           send_isr : out std_logic;
395
396           address : out std_logic_vector(31 downto 2); --to DDR
397           byte_we : out std_logic_vector(3 downto 0);
398           data_write : out std_logic_vector(31 downto 0);
399           data_read : in std_logic_vector(31 downto 0);
400           pause_in : in std_logic;
401
402           mem_address : in std_logic_vector(31 downto 2); --from CPU
403           mem_byte_we : in std_logic_vector(3 downto 0);
404           data_w : in std_logic_vector(31 downto 0);
405           pause_out : out std_logic;
406
407           E_RX_CLK : in std_logic; --2.5 MHz receive
408           E_RX_DV : in std_logic; --data valid
409           E_RXD : in std_logic_vector(3 downto 0); --receive nibble
410           E_TX_CLK : in std_logic; --2.5 MHz transmit
411           E_TX_EN : out std_logic; --transmit enable
412           E_TXD : out std_logic_vector(3 downto 0)); --transmit nibble
413   end component; --eth_dma
414
415   component plasma
416      generic(memory_type : string := "XILINX_X16"; --"DUAL_PORT_" "ALTERA_LPM";
417              log_file : string := "UNUSED";
418              ethernet : std_logic := '0';
419              use_cache : std_logic := '0');
420      port(clk : in std_logic;
421           reset : in std_logic;
422           uart_write : out std_logic;
423           uart_read : in std_logic;
424
425           address : out std_logic_vector(31 downto 2);
426           byte_we : out std_logic_vector(3 downto 0);
427           data_write : out std_logic_vector(31 downto 0);
428           data_read : in std_logic_vector(31 downto 0);
429           mem_pause_in : in std_logic;
430           no_ddr_start : out std_logic;
431           no_ddr_stop : out std_logic;
432
433           gpio0_out : out std_logic_vector(31 downto 0);
434           gpioA_in : in std_logic_vector(31 downto 0));
435   end component; --plasma
436
437   component ddr_ctrl
438      port(clk : in std_logic;
439           clk_2x : in std_logic;
440           reset_in : in std_logic;
441
442           address : in std_logic_vector(25 downto 2);
443           byte_we : in std_logic_vector(3 downto 0);
444           data_w : in std_logic_vector(31 downto 0);
445           data_r : out std_logic_vector(31 downto 0);
446           active : in std_logic;
447           no_start : in std_logic;
448           no_stop : in std_logic;
449           pause : out std_logic;
450
451           SD_CK_P : out std_logic; --clock_positive
452           SD_CK_N : out std_logic; --clock_negative
453           SD_CKE : out std_logic; --clock_enable
454
455           SD_BA : out std_logic_vector(1 downto 0); --bank_address
456           SD_A : out std_logic_vector(12 downto 0); --address(row or col)
457           SD_CS : out std_logic; --chip_select
458           SD_RAS : out std_logic; --row_address_strobe
459           SD_CAS : out std_logic; --column_address_strobe
460           SD_WE : out std_logic; --write_enable
461
462           SD_DQ : inout std_logic_vector(15 downto 0); --data
463           SD_UDM : out std_logic; --upper_byte_enable
464           SD_UDQS : inout std_logic; --upper_data_strobe
465           SD_LDM : out std_logic; --low_byte_enable
466           SD_LDQS : inout std_logic); --low_data_strobe
467   end component; --ddr
468
469end; --package mlite_pack
470
471
472package body mlite_pack is
473
474function bv_adder(a : in std_logic_vector;
475                  b : in std_logic_vector;
476                  do_add: in std_logic) return std_logic_vector is
477   variable carry_in : std_logic;
478   variable bb : std_logic_vector(a'length-1 downto 0);
479   variable result : std_logic_vector(a'length downto 0);
480begin
481   if do_add = '1' then
482      bb := b;
483      carry_in := '0';
484   else
485      bb := not b;
486      carry_in := '1';
487   end if;
488   for index in 0 to a'length-1 loop
489      result(index) := a(index) xor bb(index) xor carry_in;
490      carry_in := (carry_in and (a(index) or bb(index))) or
491                  (a(index) and bb(index));
492   end loop;
493   result(a'length) := carry_in xnor do_add;
494   return result;
495end; --function
496
497
498function bv_negate(a : in std_logic_vector) return std_logic_vector is
499   variable carry_in : std_logic;
500   variable not_a : std_logic_vector(a'length-1 downto 0);
501   variable result : std_logic_vector(a'length-1 downto 0);
502begin
503   not_a := not a;
504   carry_in := '1';
505   for index in a'reverse_range loop
506      result(index) := not_a(index) xor carry_in;
507      carry_in := carry_in and not_a(index);
508   end loop;
509   return result;
510end; --function
511
512
513function bv_increment(a : in std_logic_vector(31 downto 2)
514                     ) return std_logic_vector is
515   variable carry_in : std_logic;
516   variable result : std_logic_vector(31 downto 2);
517begin
518   carry_in := '1';
519   for index in 2 to 31 loop
520      result(index) := a(index) xor carry_in;
521      carry_in := a(index) and carry_in;
522   end loop;
523   return result;
524end; --function
525
526
527function bv_inc(a : in std_logic_vector
528                ) return std_logic_vector is
529   variable carry_in : std_logic;
530   variable result : std_logic_vector(a'length-1 downto 0);
531begin
532   carry_in := '1';
533   for index in 0 to a'length-1 loop
534      result(index) := a(index) xor carry_in;
535      carry_in := a(index) and carry_in;
536   end loop;
537   return result;
538end; --function
539
540end; --package body
541
542
plasma/logic/mult.vhd
1---------------------------------------------------------------------
2-- TITLE: Multiplication and Division Unit
3-- AUTHORS: Steve Rhoads (rhoadss@yahoo.com)
4-- DATE CREATED: 1/31/01
5-- FILENAME: mult.vhd
6-- PROJECT: Plasma CPU core
7-- COPYRIGHT: Software placed into the public domain by the author.
8-- Software 'as is' without warranty. Author liable for nothing.
9-- DESCRIPTION:
10-- Implements the multiplication and division unit in 32 clocks.
11--
12-- To reduce space, compile your code using the flag "-mno-mul" which
13-- will use software base routines in math.c if USE_SW_MULT is defined.
14-- Then remove references to the entity mult in mlite_cpu.vhd.
15--
16-- MULTIPLICATION
17-- long64 answer = 0
18-- for(i = 0; i < 32; ++i)
19-- {
20-- answer = (answer >> 1) + (((b&1)?a:0) << 31);
21-- b = b >> 1;
22-- }
23--
24-- DIVISION
25-- long upper=a, lower=0;
26-- a = b << 31;
27-- for(i = 0; i < 32; ++i)
28-- {
29-- lower = lower << 1;
30-- if(upper >= a && a && b < 2)
31-- {
32-- upper = upper - a;
33-- lower |= 1;
34-- }
35-- a = ((b&2) << 30) | (a >> 1);
36-- b = b >> 1;
37-- }
38---------------------------------------------------------------------
39library ieee;
40use ieee.std_logic_1164.all;
41use ieee.std_logic_unsigned.all;
42use IEEE.std_logic_arith.all;
43use work.mlite_pack.all;
44
45entity mult is
46   generic(mult_type : string := "DEFAULT");
47   port(clk : in std_logic;
48        reset_in : in std_logic;
49        a, b : in std_logic_vector(31 downto 0);
50        mult_func : in mult_function_type;
51        c_mult : out std_logic_vector(31 downto 0);
52        pause_out : out std_logic);
53end; --entity mult
54
55architecture logic of mult is
56
57   constant MODE_MULT : std_logic := '1';
58   constant MODE_DIV : std_logic := '0';
59
60   signal mode_reg : std_logic;
61   signal negate_reg : std_logic;
62   signal sign_reg : std_logic;
63   signal sign2_reg : std_logic;
64   signal count_reg : std_logic_vector(5 downto 0);
65   signal aa_reg : std_logic_vector(31 downto 0);
66   signal bb_reg : std_logic_vector(31 downto 0);
67   signal upper_reg : std_logic_vector(31 downto 0);
68   signal lower_reg : std_logic_vector(31 downto 0);
69
70   signal a_neg : std_logic_vector(31 downto 0);
71   signal b_neg : std_logic_vector(31 downto 0);
72   signal sum : std_logic_vector(32 downto 0);
73
74begin
75
76   -- Result
77   c_mult <= lower_reg when mult_func = MULT_READ_LO and negate_reg = '0' else
78             bv_negate(lower_reg) when mult_func = MULT_READ_LO
79                and negate_reg = '1' else
80             upper_reg when mult_func = MULT_READ_HI else
81             ZERO;
82   pause_out <= '1' when (count_reg /= "000000") and
83             (mult_func = MULT_READ_LO or mult_func = MULT_READ_HI) else '0';
84
85   -- ABS and remainder signals
86   a_neg <= bv_negate(a);
87   b_neg <= bv_negate(b);
88   sum <= bv_adder(upper_reg, aa_reg, mode_reg);
89
90   --multiplication/division unit
91   mult_proc: process(clk, reset_in, a, b, mult_func,
92      a_neg, b_neg, sum, sign_reg, mode_reg, negate_reg,
93      count_reg, aa_reg, bb_reg, upper_reg, lower_reg)
94      variable count : std_logic_vector(2 downto 0);
95   begin
96      count := "001";
97      if reset_in = '1' then
98         mode_reg <= '0';
99         negate_reg <= '0';
100         sign_reg <= '0';
101         sign2_reg <= '0';
102         count_reg <= "000000";
103         aa_reg <= ZERO;
104         bb_reg <= ZERO;
105         upper_reg <= ZERO;
106         lower_reg <= ZERO;
107      elsif rising_edge(clk) then
108         case mult_func is
109            when MULT_WRITE_LO =>
110               lower_reg <= a;
111               negate_reg <= '0';
112            when MULT_WRITE_HI =>
113               upper_reg <= a;
114               negate_reg <= '0';
115            when MULT_MULT =>
116               mode_reg <= MODE_MULT;
117               aa_reg <= a;
118               bb_reg <= b;
119               upper_reg <= ZERO;
120               count_reg <= "100000";
121               negate_reg <= '0';
122               sign_reg <= '0';
123               sign2_reg <= '0';
124            when MULT_SIGNED_MULT =>
125               mode_reg <= MODE_MULT;
126               if b(31) = '0' then
127                  aa_reg <= a;
128                  bb_reg <= b;
129                  sign_reg <= a(31);
130               else
131                  aa_reg <= a_neg;
132                  bb_reg <= b_neg;
133                  sign_reg <= a_neg(31);
134               end if;
135               sign2_reg <= '0';
136               upper_reg <= ZERO;
137               count_reg <= "100000";
138               negate_reg <= '0';
139            when MULT_DIVIDE =>
140               mode_reg <= MODE_DIV;
141               aa_reg <= b(0) & ZERO(30 downto 0);
142               bb_reg <= b;
143               upper_reg <= a;
144               count_reg <= "100000";
145               negate_reg <= '0';
146            when MULT_SIGNED_DIVIDE =>
147               mode_reg <= MODE_DIV;
148               if b(31) = '0' then
149                  aa_reg(31) <= b(0);
150                  bb_reg <= b;
151               else
152                  aa_reg(31) <= b_neg(0);
153                  bb_reg <= b_neg;
154               end if;
155               if a(31) = '0' then
156                  upper_reg <= a;
157               else
158                  upper_reg <= a_neg;
159               end if;
160               aa_reg(30 downto 0) <= ZERO(30 downto 0);
161               count_reg <= "100000";
162               negate_reg <= a(31) xor b(31);
163            when others =>
164
165               if count_reg /= "000000" then
166                  if mode_reg = MODE_MULT then
167                     -- Multiplication
168                     if bb_reg(0) = '1' then
169                        upper_reg <= (sign_reg xor sum(32)) & sum(31 downto 1);
170                        lower_reg <= sum(0) & lower_reg(31 downto 1);
171                        sign2_reg <= sign2_reg or sign_reg;
172                        sign_reg <= '0';
173                        bb_reg <= '0' & bb_reg(31 downto 1);
174                     -- The following six lines are optional for speedup
175                     --elsif bb_reg(3 downto 0) = "0000" and sign2_reg = '0' and
176                     -- count_reg(5 downto 2) /= "0000" then
177                     -- upper_reg <= "0000" & upper_reg(31 downto 4);
178                     -- lower_reg <= upper_reg(3 downto 0) & lower_reg(31 downto 4);
179                     -- count := "100";
180                     -- bb_reg <= "0000" & bb_reg(31 downto 4);
181                     else
182                        upper_reg <= sign2_reg & upper_reg(31 downto 1);
183                        lower_reg <= upper_reg(0) & lower_reg(31 downto 1);
184                        bb_reg <= '0' & bb_reg(31 downto 1);
185                     end if;
186                  else
187                     -- Division
188                     if sum(32) = '0' and aa_reg /= ZERO and
189                           bb_reg(31 downto 1) = ZERO(31 downto 1) then
190                        upper_reg <= sum(31 downto 0);
191                        lower_reg(0) <= '1';
192                     else
193                        lower_reg(0) <= '0';
194                     end if;
195                     aa_reg <= bb_reg(1) & aa_reg(31 downto 1);
196                     lower_reg(31 downto 1) <= lower_reg(30 downto 0);
197                     bb_reg <= '0' & bb_reg(31 downto 1);
198                  end if;
199                  count_reg <= count_reg - count;
200               end if; --count
201
202         end case;
203
204      end if;
205
206   end process;
207
208end; --architecture logic
plasma/logic/pc_next.vhd
1---------------------------------------------------------------------
2-- TITLE: Program Counter Next
3-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4-- DATE CREATED: 2/8/01
5-- FILENAME: pc_next.vhd
6-- PROJECT: Plasma CPU core
7-- COPYRIGHT: Software placed into the public domain by the author.
8-- Software 'as is' without warranty. Author liable for nothing.
9-- DESCRIPTION:
10-- Implements the Program Counter logic.
11---------------------------------------------------------------------
12library ieee;
13use ieee.std_logic_1164.all;
14use work.mlite_pack.all;
15
16entity pc_next is
17   port(clk : in std_logic;
18        reset_in : in std_logic;
19        pc_new : in std_logic_vector(31 downto 2);
20        take_branch : in std_logic;
21        pause_in : in std_logic;
22        opcode25_0 : in std_logic_vector(25 downto 0);
23        pc_source : in pc_source_type;
24        pc_future : out std_logic_vector(31 downto 2);
25        pc_current : out std_logic_vector(31 downto 2);
26        pc_plus4 : out std_logic_vector(31 downto 2));
27end; --pc_next
28
29architecture logic of pc_next is
30   signal pc_reg : std_logic_vector(31 downto 2);
31begin
32
33pc_select: process(clk, reset_in, pc_new, take_branch, pause_in,
34                 opcode25_0, pc_source, pc_reg)
35   variable pc_inc : std_logic_vector(31 downto 2);
36   variable pc_next : std_logic_vector(31 downto 2);
37begin
38   pc_inc := bv_increment(pc_reg); --pc_reg+1
39
40   case pc_source is
41   when FROM_INC4 =>
42      pc_next := pc_inc;
43   when FROM_OPCODE25_0 =>
44      pc_next := pc_reg(31 downto 28) & opcode25_0;
45   when FROM_BRANCH | FROM_LBRANCH =>
46      if take_branch = '1' then
47         pc_next := pc_new;
48      else
49         pc_next := pc_inc;
50      end if;
51   when others =>
52      pc_next := pc_inc;
53   end case;
54
55   if pause_in = '1' then
56      pc_next := pc_reg;
57   end if;
58
59   if reset_in = '1' then
60      pc_reg <= ZERO(31 downto 2);
61      pc_next := pc_reg;
62   elsif rising_edge(clk) then
63      pc_reg <= pc_next;
64   end if;
65
66   pc_future <= pc_next;
67   pc_current <= pc_reg;
68   pc_plus4 <= pc_inc;
69end process;
70
71end; --logic
plasma/logic/pipeline.vhd
1---------------------------------------------------------------------
2-- TITLE: Pipeline
3-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4-- DATE CREATED: 6/24/02
5-- FILENAME: pipeline.vhd
6-- PROJECT: Plasma CPU core
7-- COPYRIGHT: Software placed into the public domain by the author.
8-- Software 'as is' without warranty. Author liable for nothing.
9-- DESCRIPTION:
10-- Controls the three stage pipeline by delaying the signals:
11-- a_bus, b_bus, alu/shift/mult_func, c_source, and rs_index.
12---------------------------------------------------------------------
13library ieee;
14use ieee.std_logic_1164.all;
15use work.mlite_pack.all;
16
17--Note: sigD <= sig after rising_edge(clk)
18entity pipeline is
19   port(clk : in std_logic;
20        reset : in std_logic;
21        a_bus : in std_logic_vector(31 downto 0);
22        a_busD : out std_logic_vector(31 downto 0);
23        b_bus : in std_logic_vector(31 downto 0);
24        b_busD : out std_logic_vector(31 downto 0);
25        alu_func : in alu_function_type;
26        alu_funcD : out alu_function_type;
27        shift_func : in shift_function_type;
28        shift_funcD : out shift_function_type;
29        mult_func : in mult_function_type;
30        mult_funcD : out mult_function_type;
31        reg_dest : in std_logic_vector(31 downto 0);
32        reg_destD : out std_logic_vector(31 downto 0);
33        rd_index : in std_logic_vector(5 downto 0);
34        rd_indexD : out std_logic_vector(5 downto 0);
35
36        rs_index : in std_logic_vector(5 downto 0);
37        rt_index : in std_logic_vector(5 downto 0);
38        pc_source : in pc_source_type;
39        mem_source : in mem_source_type;
40        a_source : in a_source_type;
41        b_source : in b_source_type;
42        c_source : in c_source_type;
43        c_bus : in std_logic_vector(31 downto 0);
44        pause_any : in std_logic;
45        pause_pipeline : out std_logic);
46end; --entity pipeline
47
48architecture logic of pipeline is
49   signal rd_index_reg : std_logic_vector(5 downto 0);
50   signal reg_dest_reg : std_logic_vector(31 downto 0);
51   signal reg_dest_delay : std_logic_vector(31 downto 0);
52   signal c_source_reg : c_source_type;
53   signal pause_enable_reg : std_logic;
54begin
55
56--When operating in three stage pipeline mode, the following signals
57--are delayed by one clock cycle: a_bus, b_bus, alu/shift/mult_func,
58--c_source, and rd_index.
59pipeline3: process(clk, reset, a_bus, b_bus, alu_func, shift_func, mult_func,
60      rd_index, rd_index_reg, pause_any, pause_enable_reg,
61      rs_index, rt_index,
62      pc_source, mem_source, a_source, b_source, c_source, c_source_reg,
63      reg_dest, reg_dest_reg, reg_dest_delay, c_bus)
64   variable pause_mult_clock : std_logic;
65   variable freeze_pipeline : std_logic;
66begin
67   if (pc_source /= FROM_INC4 and pc_source /= FROM_OPCODE25_0) or
68         mem_source /= MEM_FETCH or
69         (mult_func = MULT_READ_LO or mult_func = MULT_READ_HI) then
70      pause_mult_clock := '1';
71   else
72      pause_mult_clock := '0';
73   end if;
74
75   freeze_pipeline := not (pause_mult_clock and pause_enable_reg) and pause_any;
76   pause_pipeline <= pause_mult_clock and pause_enable_reg;
77   rd_indexD <= rd_index_reg;
78
79   -- The value written back into the register bank, signal reg_dest is tricky.
80   -- If reg_dest comes from the ALU via the signal c_bus, it is already delayed
81   -- into stage #3, because a_busD and b_busD are delayed. If reg_dest comes from
82   -- c_memory, pc_current, or pc_plus4 then reg_dest hasn't yet been delayed into
83   -- stage #3.
84   -- Instead of delaying c_memory, pc_current, and pc_plus4, these signals
85   -- are multiplexed into reg_dest which is then delayed. The decision to use
86   -- the already delayed c_bus or the delayed value of reg_dest (reg_dest_reg) is
87   -- based on a delayed value of c_source (c_source_reg).
88
89   if c_source_reg = C_FROM_ALU then
90      reg_dest_delay <= c_bus; --delayed by 1 clock cycle via a_busD & b_busD
91   else
92      reg_dest_delay <= reg_dest_reg; --need to delay 1 clock cycle from reg_dest
93   end if;
94   reg_destD <= reg_dest_delay;
95
96   if reset = '1' then
97      a_busD <= ZERO;
98      b_busD <= ZERO;
99      alu_funcD <= ALU_NOTHING;
100      shift_funcD <= SHIFT_NOTHING;
101      mult_funcD <= MULT_NOTHING;
102      reg_dest_reg <= ZERO;
103      c_source_reg <= "000";
104      rd_index_reg <= "000000";
105      pause_enable_reg <= '0';
106   elsif rising_edge(clk) then
107      if freeze_pipeline = '0' then
108         if (rs_index = "000000" or rs_index /= rd_index_reg) or
109            (a_source /= A_FROM_REG_SOURCE or pause_enable_reg = '0') then
110            a_busD <= a_bus;
111         else
112            a_busD <= reg_dest_delay; --rs from previous operation (bypass stage)
113         end if;
114
115         if (rt_index = "000000" or rt_index /= rd_index_reg) or
116               (b_source /= B_FROM_REG_TARGET or pause_enable_reg = '0') then
117            b_busD <= b_bus;
118         else
119            b_busD <= reg_dest_delay; --rt from previous operation
120         end if;
121
122         alu_funcD <= alu_func;
123         shift_funcD <= shift_func;
124         mult_funcD <= mult_func;
125         reg_dest_reg <= reg_dest;
126         c_source_reg <= c_source;
127         rd_index_reg <= rd_index;
128      end if;
129
130      if pause_enable_reg = '0' and pause_any = '0' then
131         pause_enable_reg <= '1'; --enable pause_pipeline
132      elsif pause_mult_clock = '1' then
133         pause_enable_reg <= '0'; --disable pause_pipeline
134      end if;
135   end if;
136
137end process; --pipeline3
138
139end; --logic
plasma/logic/plasma.vhd
1---------------------------------------------------------------------
2-- TITLE: Plasma (CPU core with memory)
3-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4-- DATE CREATED: 6/4/02
5-- FILENAME: plasma.vhd
6-- PROJECT: Plasma CPU core
7-- COPYRIGHT: Software placed into the public domain by the author.
8-- Software 'as is' without warranty. Author liable for nothing.
9-- DESCRIPTION:
10-- This entity combines the CPU core with memory and a UART.
11--
12-- Memory Map:
13-- 0x00000000 - 0x0000ffff Internal RAM (8KB)
14-- 0x10000000 - 0x100fffff External RAM (1MB)
15-- Access all Misc registers with 32-bit accesses
16-- 0x20000000 Uart Write (will pause CPU if busy)
17-- 0x20000000 Uart Read
18-- 0x20000010 IRQ Mask
19-- 0x20000020 IRQ Status
20-- 0x20000030 GPIO0 Out Set bits
21-- 0x20000040 GPIO0 Out Clear bits
22-- 0x20000050 GPIOA In
23-- 0x20000060 Counter
24-- 0x20000070 Ethernet transmit count
25-- IRQ bits:
26-- 7 GPIO31
27-- 6 ^GPIO31
28-- 5 EthernetSendDone
29-- 4 EthernetReceive
30-- 3 Counter(18)
31-- 2 ^Counter(18)
32-- 1 ^UartWriteBusy
33-- 0 UartDataAvailable
34---------------------------------------------------------------------
35library ieee;
36use ieee.std_logic_1164.all;
37use work.mlite_pack.all;
38
39entity plasma is
40   generic(memory_type : string := "XILINX_16X"; --"DUAL_PORT_" "ALTERA_LPM";
41           log_file : string := "UNUSED";
42           ethernet : std_logic := '0';
43           use_cache : std_logic := '0');
44   port(clk : in std_logic;
45        reset : in std_logic;
46
47        uart_write : out std_logic;
48        uart_read : in std_logic;
49
50        address : out std_logic_vector(31 downto 2);
51        byte_we : out std_logic_vector(3 downto 0);
52        data_write : out std_logic_vector(31 downto 0);
53        data_read : in std_logic_vector(31 downto 0);
54        mem_pause_in : in std_logic;
55        no_ddr_start : out std_logic;
56        no_ddr_stop : out std_logic;
57
58        gpio0_out : out std_logic_vector(31 downto 0);
59        gpioA_in : in std_logic_vector(31 downto 0));
60end; --entity plasma
61
62architecture logic of plasma is
63   signal address_next : std_logic_vector(31 downto 2);
64   signal byte_we_next : std_logic_vector(3 downto 0);
65   signal cpu_address : std_logic_vector(31 downto 0);
66   signal cpu_byte_we : std_logic_vector(3 downto 0);
67   signal cpu_data_w : std_logic_vector(31 downto 0);
68   signal cpu_data_r : std_logic_vector(31 downto 0);
69   signal cpu_pause : std_logic;
70
71   signal data_read_uart : std_logic_vector(7 downto 0);
72   signal write_enable : std_logic;
73   signal eth_pause_in : std_logic;
74   signal eth_pause : std_logic;
75   signal mem_busy : std_logic;
76
77   signal enable_misc : std_logic;
78   signal enable_uart : std_logic;
79   signal enable_uart_read : std_logic;
80   signal enable_uart_write : std_logic;
81   signal enable_eth : std_logic;
82
83   signal gpio0_reg : std_logic_vector(31 downto 0);
84   signal uart_write_busy : std_logic;
85   signal uart_data_avail : std_logic;
86   signal irq_mask_reg : std_logic_vector(7 downto 0);
87   signal irq_status : std_logic_vector(7 downto 0);
88   signal irq : std_logic;
89   signal irq_eth_rec : std_logic;
90   signal irq_eth_send : std_logic;
91   signal counter_reg : std_logic_vector(31 downto 0);
92
93   signal ram_enable : std_logic;
94   signal ram_byte_we : std_logic_vector(3 downto 0);
95   signal ram_address : std_logic_vector(31 downto 2);
96   signal ram_data_w : std_logic_vector(31 downto 0);
97   signal ram_data_r : std_logic_vector(31 downto 0);
98
99   signal cache_check : std_logic;
100   signal cache_checking : std_logic;
101   signal cache_miss : std_logic;
102   signal cache_hit : std_logic;
103
104begin --architecture
105   write_enable <= '1' when cpu_byte_we /= "0000" else '0';
106   mem_busy <= eth_pause or mem_pause_in;
107   cache_hit <= cache_checking and not cache_miss;
108   cpu_pause <= (uart_write_busy and enable_uart and write_enable) or --UART busy
109      cache_miss or --Cache wait
110      (cpu_address(28) and not cache_hit and mem_busy); --DDR or flash --DDR in use
111   irq_status <= gpioA_in(31) & not gpioA_in(31) &
112                 irq_eth_send & irq_eth_rec &
113                 counter_reg(18) & not counter_reg(18) &
114                 not uart_write_busy & uart_data_avail;
115   irq <= '1' when (irq_status and irq_mask_reg) /= ZERO(7 downto 0) else '0';
116   gpio0_out(31 downto 29) <= gpio0_reg(31 downto 29);
117   gpio0_out(23 downto 0) <= gpio0_reg(23 downto 0);
118
119   enable_misc <= '1' when cpu_address(30 downto 28) = "010" else '0';
120   enable_uart <= '1' when enable_misc = '1' and cpu_address(7 downto 4) = "0000" else '0';
121   enable_uart_read <= enable_uart and not write_enable;
122   enable_uart_write <= enable_uart and write_enable;
123   enable_eth <= '1' when enable_misc = '1' and cpu_address(7 downto 4) = "0111" else '0';
124   cpu_address(1 downto 0) <= "00";
125
126   u1_cpu: mlite_cpu
127      generic map (memory_type => memory_type)
128      PORT MAP (
129         clk => clk,
130         reset_in => reset,
131         intr_in => irq,
132
133         address_next => address_next, --before rising_edge(clk)
134         byte_we_next => byte_we_next,
135
136         address => cpu_address(31 downto 2), --after rising_edge(clk)
137         byte_we => cpu_byte_we,
138         data_w => cpu_data_w,
139         data_r => cpu_data_r,
140         mem_pause => cpu_pause);
141
142   opt_cache: if use_cache = '0' generate
143      cache_check <= '0';
144      cache_checking <= '0';
145      cache_miss <= '0';
146   end generate;
147
148   opt_cache2: if use_cache = '1' generate
149   --Control 4KB unified cache that uses the upper 4KB of the 8KB
150   --internal RAM. Only lowest 2MB of DDR is cached.
151   u_cache: cache
152      generic map (memory_type => memory_type)
153      PORT MAP (
154         clk => clk,
155         reset => reset,
156         address_next => address_next,
157         byte_we_next => byte_we_next,
158         cpu_address => cpu_address(31 downto 2),
159         mem_busy => mem_busy,
160
161         cache_check => cache_check, --Stage1: address_next in first 2MB DDR
162         cache_checking => cache_checking, --Stage2
163         cache_miss => cache_miss); --Stage3
164   end generate; --opt_cache2
165
166   no_ddr_start <= not eth_pause and cache_checking;
167   no_ddr_stop <= not eth_pause and cache_miss;
168   eth_pause_in <= mem_pause_in or (not eth_pause and cache_miss and not cache_checking);
169
170   misc_proc: process(clk, reset, cpu_address, enable_misc,
171      ram_data_r, data_read, data_read_uart, cpu_pause,
172      irq_mask_reg, irq_status, gpio0_reg, write_enable,
173      cache_checking,
174      gpioA_in, counter_reg, cpu_data_w)
175   begin
176      case cpu_address(30 downto 28) is
177      when "000" => --internal RAM
178         cpu_data_r <= ram_data_r;
179      when "001" => --external RAM
180         if cache_checking = '1' then
181            cpu_data_r <= ram_data_r; --cache
182         else
183            cpu_data_r <= data_read; --DDR
184         end if;
185      when "010" => --misc
186         case cpu_address(6 downto 4) is
187         when "000" => --uart
188            cpu_data_r <= ZERO(31 downto 8) & data_read_uart;
189         when "001" => --irq_mask
190            cpu_data_r <= ZERO(31 downto 8) & irq_mask_reg;
191         when "010" => --irq_status
192            cpu_data_r <= ZERO(31 downto 8) & irq_status;
193         when "011" => --gpio0
194            cpu_data_r <= gpio0_reg;
195         when "101" => --gpioA
196            cpu_data_r <= gpioA_in;
197         when "110" => --counter
198            cpu_data_r <= counter_reg;
199         when others =>
200            cpu_data_r <= gpioA_in;
201         end case;
202      when "011" => --flash
203         cpu_data_r <= data_read;
204      when others =>
205         cpu_data_r <= ZERO;
206      end case;
207
208      if reset = '1' then
209         irq_mask_reg <= ZERO(7 downto 0);
210         gpio0_reg <= ZERO;
211         counter_reg <= ZERO;
212      elsif rising_edge(clk) then
213         if cpu_pause = '0' then
214            if enable_misc = '1' and write_enable = '1' then
215               if cpu_address(6 downto 4) = "001" then
216                  irq_mask_reg <= cpu_data_w(7 downto 0);
217               elsif cpu_address(6 downto 4) = "011" then
218                  gpio0_reg <= gpio0_reg or cpu_data_w;
219               elsif cpu_address(6 downto 4) = "100" then
220                  gpio0_reg <= gpio0_reg and not cpu_data_w;
221               end if;
222            end if;
223         end if;
224         counter_reg <= bv_inc(counter_reg);
225      end if;
226   end process;
227
228   ram_enable <= '1' when address_next(30 downto 28) = "000" or
229                  cache_check = '1' or cache_miss = '1' else '0';
230   ram_byte_we <= byte_we_next when cache_miss = '0' else "1111";
231   ram_address(31 downto 13) <= ZERO(31 downto 13);
232   ram_address(12 downto 2) <= (address_next(12) or cache_check) & address_next(11 downto 2)
233            when cache_miss = '0' else
234            '1' & cpu_address(11 downto 2); --Update cache after cache miss
235   ram_data_w <= cpu_data_w when cache_miss = '0' else data_read;
236
237   u2_ram: ram
238      generic map (memory_type => memory_type)
239      port map (
240         clk => clk,
241         enable => ram_enable,
242         write_byte_enable => ram_byte_we,
243         address => ram_address,
244         data_write => ram_data_w,
245         data_read => ram_data_r);
246
247   u3_uart: uart
248      generic map (log_file => log_file)
249      port map(
250         clk => clk,
251         reset => reset,
252         enable_read => enable_uart_read,
253         enable_write => enable_uart_write,
254         data_in => cpu_data_w(7 downto 0),
255         data_out => data_read_uart,
256         uart_read => uart_read,
257         uart_write => uart_write,
258         busy_write => uart_write_busy,
259         data_avail => uart_data_avail);
260
261   dma_gen: if ethernet = '0' generate
262      address <= cpu_address(31 downto 2);
263      byte_we <= cpu_byte_we;
264      data_write <= cpu_data_w;
265      eth_pause <= '0';
266      gpio0_out(28 downto 24) <= ZERO(28 downto 24);
267      irq_eth_rec <= '0';
268      irq_eth_send <= '0';
269   end generate;
270
271   dma_gen2: if ethernet = '1' generate
272   u4_eth: eth_dma
273      port map(
274         clk => clk,
275         reset => reset,
276         enable_eth => gpio0_reg(24),
277         select_eth => enable_eth,
278         rec_isr => irq_eth_rec,
279         send_isr => irq_eth_send,
280
281         address => address, --to DDR
282         byte_we => byte_we,
283         data_write => data_write,
284         data_read => data_read,
285         pause_in => eth_pause_in,
286
287         mem_address => cpu_address(31 downto 2), --from CPU
288         mem_byte_we => cpu_byte_we,
289         data_w => cpu_data_w,
290         pause_out => eth_pause,
291
292         E_RX_CLK => gpioA_in(20),
293         E_RX_DV => gpioA_in(19),
294         E_RXD => gpioA_in(18 downto 15),
295         E_TX_CLK => gpioA_in(14),
296         E_TX_EN => gpio0_out(28),
297         E_TXD => gpio0_out(27 downto 24));
298   end generate;
299
300end; --architecture logic
301
plasma/logic/plasma_3e.ucf
1#####################################################
2### SPARTAN-3E STARTER KIT BOARD CONSTRAINTS FILE
3#####################################################
4# ==== Analog-to-Digital Converter (ADC) ====
5# some connections shared with SPI Flash, DAC, ADC, and AMP
6#NET "AD_CONV" LOC = "P11" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 6 ;
7# ==== Programmable Gain Amplifier (AMP) ====
8# some connections shared with SPI Flash, DAC, ADC, and AMP
9#NET "AMP_CS" LOC = "N7" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 6 ;
10#NET "AMP_DOUT" LOC = "E18" | IOSTANDARD = LVCMOS33 ;
11#NET "AMP_SHDN" LOC = "P7" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 6 ;
12# ==== Pushbuttons (BTN) ====
13NET "BTN_EAST" LOC = "H13" | IOSTANDARD = LVTTL | PULLDOWN ;
14NET "BTN_NORTH" LOC = "V4" | IOSTANDARD = LVTTL | PULLDOWN ;
15NET "BTN_SOUTH" LOC = "K17" | IOSTANDARD = LVTTL | PULLDOWN ;
16NET "BTN_WEST" LOC = "D18" | IOSTANDARD = LVTTL | PULLDOWN ;
17# ==== Clock inputs (CLK) ====
18NET "CLK_50MHZ" LOC = "C9" | IOSTANDARD = LVCMOS33 ;
19# Define clock period for 50 MHz oscillator (40%/60% duty-cycle)
20NET "CLK_50MHZ" PERIOD = 20 ns HIGH 40 %;
21#NET "CLK_AUX" LOC = "B8" | IOSTANDARD = LVCMOS33 ;
22#NET "CLK_SMA" LOC = "A10" | IOSTANDARD = LVCMOS33 ;
23# ==== Digital-to-Analog Converter (DAC) ====
24# some connections shared with SPI Flash, DAC, ADC, and AMP
25#NET "DAC_CLR" LOC = "P8" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ;
26#NET "DAC_CS" LOC = "N8" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ;
27# ==== 1-Wire Secure EEPROM (DS)
28#NET "DS_WIRE" LOC = "U4" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 ;
29# ==== Ethernet PHY (E) ====
30#NET "E_COL" LOC = "U6" | IOSTANDARD = LVCMOS33 ;
31#NET "E_CRS" LOC = "U13" | IOSTANDARD = LVCMOS33 ;
32NET "E_MDC" LOC = "P9" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ;
33NET "E_MDIO" LOC = "U5" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ;
34NET "E_RX_CLK" LOC = "V3" | IOSTANDARD = LVCMOS33 ;
35NET "E_RX_DV" LOC = "V2" | IOSTANDARD = LVCMOS33 ;
36NET "E_RXD<0>" LOC = "V8" | IOSTANDARD = LVCMOS33 ;
37NET "E_RXD<1>" LOC = "T11" | IOSTANDARD = LVCMOS33 ;
38NET "E_RXD<2>" LOC = "U11" | IOSTANDARD = LVCMOS33 ;
39NET "E_RXD<3>" LOC = "V14" | IOSTANDARD = LVCMOS33 ;
40#NET "E_RXD<4>" LOC = "U14" | IOSTANDARD = LVCMOS33 ;
41NET "E_TX_CLK" LOC = "T7" | IOSTANDARD = LVCMOS33 ;
42NET "E_TX_EN" LOC = "P15" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ;
43NET "E_TXD<0>" LOC = "R11" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ;
44NET "E_TXD<1>" LOC = "T15" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ;
45NET "E_TXD<2>" LOC = "R5" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ;
46NET "E_TXD<3>" LOC = "T5" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ;
47#NET "E_TXD<4>" LOC = "R6" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ;
48# ==== FPGA Configuration Mode, INIT_B Pins (FPGA) ====
49#NET "FPGA_M0" LOC = "M10" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ;
50#NET "FPGA_M1" LOC = "V11" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ;
51#NET "FPGA_M2" LOC = "T10" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ;
52#NET "FPGA_INIT_B" LOC = "T3" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 4 ;
53#NET "FPGA_RDWR_B" LOC = "U10" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 4 ;
54#NET "FPGA_HSWAP" LOC = "B3" | IOSTANDARD = LVCMOS33 ;
55# ==== FX2 Connector (FX2) ====
56#NET "FX2_CLKIN" LOC = "E10" | IOSTANDARD = LVCMOS33 ;
57#NET "FX2_CLKIO" LOC = "D9" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
58#NET "FX2_CLKOUT" LOC = "D10" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
59# These four connections are shared with the J1 6-pin accessory header
60#NET "FX2_IO<1>" LOC = "B4" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
61#NET "FX2_IO<2>" LOC = "A4" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
62#NET "FX2_IO<3>" LOC = "D5" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
63#NET "FX2_IO<4>" LOC = "C5" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
64# These four connections are shared with the J2 6-pin accessory header
65#NET "FX2_IO<5>" LOC = "A6" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
66#NET "FX2_IO<6>" LOC = "B6" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
67#NET "FX2_IO<7>" LOC = "E7" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
68#NET "FX2_IO<8>" LOC = "F7" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
69# These four connections are shared with the J4 6-pin accessory header
70#NET "FX2_IO<9>" LOC = "D7" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
71#NET "FX2_IO<10>" LOC = "C7" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
72#NET "FX2_IO<11>" LOC = "F8" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
73#NET "FX2_IO<12>" LOC = "E8" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
74# The discrete LEDs are shared with the following 8 FX2 connections
75#NET "FX2_IO<13>" LOC = "F9" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
76#NET "FX2_IO<14>" LOC = "E9" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
77#NET "FX2_IO<15>" LOC = "D11" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
78#NET "FX2_IO<16>" LOC = "C11" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
79#NET "FX2_IO<17>" LOC = "F11" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
80#NET "FX2_IO<18>" LOC = "E11" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
81#NET "FX2_IO<19>" LOC = "E12" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
82#NET "FX2_IO<20>" LOC = "F12" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
83#NET "FX2_IO<21>" LOC = "A13" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
84#NET "FX2_IO<22>" LOC = "B13" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
85#NET "FX2_IO<23>" LOC = "A14" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
86#NET "FX2_IO<24>" LOC = "B14" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
87#NET "FX2_IO<25>" LOC = "C14" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
88#NET "FX2_IO<26>" LOC = "D14" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
89#NET "FX2_IO<27>" LOC = "A16" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
90#NET "FX2_IO<28>" LOC = "B16" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
91#NET "FX2_IO<29>" LOC = "E13" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
92#NET "FX2_IO<30>" LOC = "C4" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
93#NET "FX2_IO<31>" LOC = "B11" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
94#NET "FX2_IO<32>" LOC = "A11" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
95#NET "FX2_IO<33>" LOC = "A8" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
96#NET "FX2_IO<34>" LOC = "G9" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
97#NET "FX2_IP<35>" LOC = "D12" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
98#NET "FX2_IP<36>" LOC = "C12" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
99#NET "FX2_IP<37>" LOC = "A15" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
100#NET "FX2_IP<38>" LOC = "B15" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
101#NET "FX2_IO<39>" LOC = "C3" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
102#NET "FX2_IP<40>" LOC = "C15" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
103# ==== 6-pin header J1 ====
104# These are shared connections with the FX2 connector
105#NET "J1<0>" LOC = "B4" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 6 ;
106#NET "J1<1>" LOC = "A4" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 6 ;
107#NET "J1<2>" LOC = "D5" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 6 ;
108#NET "J1<3>" LOC = "C5" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 6 ;
109# ==== 6-pin header J2 ====
110# These are shared connections with the FX2 connector
111#NET "J2<0>" LOC = "A6" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 6 ;
112#NET "J2<1>" LOC = "B6" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 6 ;
113#NET "J2<2>" LOC = "E7" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 6 ;
114#NET "J2<3>" LOC = "F7" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 6 ;
115# ==== 6-pin header J4 ====
116# These are shared connections with the FX2 connector
117#NET "J4<0>" LOC = "D7" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 6 ;
118#NET "J4<1>" LOC = "C7" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 6 ;
119#NET "J4<2>" LOC = "F8" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 6 ;
120#NET "J4<3>" LOC = "E8" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 6 ;
121# ==== Character LCD (LCD) ====
122#NET "LCD_E" LOC = "M18" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
123#NET "LCD_RS" LOC = "L18" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
124#NET "LCD_RW" LOC = "L17" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
125# LCD data connections are shared with StrataFlash connections SF_D<11:8>
126#NET "SF_D<8>" LOC = "R15" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
127#NET "SF_D<9>" LOC = "R16" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
128#NET "SF_D<10>" LOC = "P17" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
129#NET "SF_D<11>" LOC = "M15" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
130# ==== Discrete LEDs (LED) ====
131# These are shared connections with the FX2 connector
132NET "LED<0>" LOC = "F12" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 ;
133NET "LED<1>" LOC = "E12" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 ;
134NET "LED<2>" LOC = "E11" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 ;
135NET "LED<3>" LOC = "F11" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 ;
136NET "LED<4>" LOC = "C11" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 ;
137NET "LED<5>" LOC = "D11" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 ;
138NET "LED<6>" LOC = "E9" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 ;
139NET "LED<7>" LOC = "F9" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 ;
140# ==== PS/2 Mouse/Keyboard Port (PS2) ====
141NET "PS2_CLK" LOC = "G14" | IOSTANDARD = LVCMOS33 ;
142NET "PS2_DATA" LOC = "G13" | IOSTANDARD = LVCMOS33 ;
143# ==== Rotary Pushbutton Switch (ROT) ====
144NET "ROT_A" LOC = "K18" | IOSTANDARD = LVTTL | PULLUP ;
145NET "ROT_B" LOC = "G18" | IOSTANDARD = LVTTL | PULLUP ;
146NET "ROT_CENTER" LOC = "V16" | IOSTANDARD = LVTTL | PULLDOWN ;
147# ==== RS-232 Serial Ports (RS232) ====
148NET "RS232_DCE_RXD" LOC = "R7" | IOSTANDARD = LVTTL ;
149NET "RS232_DCE_TXD" LOC = "M14" | IOSTANDARD = LVTTL | DRIVE = 8 | SLEW = SLOW ;
150#NET "RS232_DTE_RXD" LOC = "U8" | IOSTANDARD = LVTTL ;
151#NET "RS232_DTE_TXD" LOC = "M13" | IOSTANDARD = LVTTL | DRIVE = 8 | SLEW = SLOW ;
152# ==== DDR SDRAM (SD) ==== (I/O Bank 3, VCCO=2.5V)
153NET "SD_A<0>" LOC = "T1" | IOSTANDARD = SSTL2_I ;
154NET "SD_A<1>" LOC = "R3" | IOSTANDARD = SSTL2_I ;
155NET "SD_A<2>" LOC = "R2" | IOSTANDARD = SSTL2_I ;
156NET "SD_A<3>" LOC = "P1" | IOSTANDARD = SSTL2_I ;
157NET "SD_A<4>" LOC = "F4" | IOSTANDARD = SSTL2_I ;
158NET "SD_A<5>" LOC = "H4" | IOSTANDARD = SSTL2_I ;
159NET "SD_A<6>" LOC = "H3" | IOSTANDARD = SSTL2_I ;
160NET "SD_A<7>" LOC = "H1" | IOSTANDARD = SSTL2_I ;
161NET "SD_A<8>" LOC = "H2" | IOSTANDARD = SSTL2_I ;
162NET "SD_A<9>" LOC = "N4" | IOSTANDARD = SSTL2_I ;
163NET "SD_A<10>" LOC = "T2" | IOSTANDARD = SSTL2_I ;
164NET "SD_A<11>" LOC = "N5" | IOSTANDARD = SSTL2_I ;
165NET "SD_A<12>" LOC = "P2" | IOSTANDARD = SSTL2_I ;
166NET "SD_BA<0>" LOC = "K5" | IOSTANDARD = SSTL2_I ;
167NET "SD_BA<1>" LOC = "K6" | IOSTANDARD = SSTL2_I ;
168NET "SD_CAS" LOC = "C2" | IOSTANDARD = SSTL2_I ;
169NET "SD_CK_N" LOC = "J4" | IOSTANDARD = SSTL2_I ;
170NET "SD_CK_P" LOC = "J5" | IOSTANDARD = SSTL2_I ;
171NET "SD_CKE" LOC = "K3" | IOSTANDARD = SSTL2_I ;
172NET "SD_CS" LOC = "K4" | IOSTANDARD = SSTL2_I ;
173NET "SD_DQ<0>" LOC = "L2" | IOSTANDARD = SSTL2_I ;
174NET "SD_DQ<1>" LOC = "L1" | IOSTANDARD = SSTL2_I ;
175NET "SD_DQ<2>" LOC = "L3" | IOSTANDARD = SSTL2_I ;
176NET "SD_DQ<3>" LOC = "L4" | IOSTANDARD = SSTL2_I ;
177NET "SD_DQ<4>" LOC = "M3" | IOSTANDARD = SSTL2_I ;
178NET "SD_DQ<5>" LOC = "M4" | IOSTANDARD = SSTL2_I ;
179NET "SD_DQ<6>" LOC = "M5" | IOSTANDARD = SSTL2_I ;
180NET "SD_DQ<7>" LOC = "M6" | IOSTANDARD = SSTL2_I ;
181NET "SD_DQ<8>" LOC = "E2" | IOSTANDARD = SSTL2_I ;
182NET "SD_DQ<9>" LOC = "E1" | IOSTANDARD = SSTL2_I ;
183NET "SD_DQ<10>" LOC = "F1" | IOSTANDARD = SSTL2_I ;
184NET "SD_DQ<11>" LOC = "F2" | IOSTANDARD = SSTL2_I ;
185NET "SD_DQ<12>" LOC = "G6" | IOSTANDARD = SSTL2_I ;
186NET "SD_DQ<13>" LOC = "G5" | IOSTANDARD = SSTL2_I ;
187NET "SD_DQ<14>" LOC = "H6" | IOSTANDARD = SSTL2_I ;
188NET "SD_DQ<15>" LOC = "H5" | IOSTANDARD = SSTL2_I ;
189NET "SD_LDM" LOC = "J2" | IOSTANDARD = SSTL2_I ;
190NET "SD_LDQS" LOC = "L6" | IOSTANDARD = SSTL2_I ;
191NET "SD_RAS" LOC = "C1" | IOSTANDARD = SSTL2_I ;
192NET "SD_UDM" LOC = "J1" | IOSTANDARD = SSTL2_I ;
193NET "SD_UDQS" LOC = "G3" | IOSTANDARD = SSTL2_I ;
194NET "SD_WE" LOC = "D1" | IOSTANDARD = SSTL2_I ;
195# Path to allow connection to top DCM connection
196#NET "SD_CK_FB" LOC = "B9" | IOSTANDARD = LVCMOS33 ;
197# Prohibit VREF pins
198CONFIG PROHIBIT = D2;
199CONFIG PROHIBIT = G4;
200CONFIG PROHIBIT = J6;
201CONFIG PROHIBIT = L5;
202CONFIG PROHIBIT = R4;
203# ==== Intel StrataFlash Parallel NOR Flash (SF) ====
204NET "SF_A<0>" LOC = "H17" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
205NET "SF_A<1>" LOC = "J13" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
206NET "SF_A<2>" LOC = "J12" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
207NET "SF_A<3>" LOC = "J14" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
208NET "SF_A<4>" LOC = "J15" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
209NET "SF_A<5>" LOC = "J16" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
210NET "SF_A<6>" LOC = "J17" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
211NET "SF_A<7>" LOC = "K14" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
212NET "SF_A<8>" LOC = "K15" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
213NET "SF_A<9>" LOC = "K12" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
214NET "SF_A<10>" LOC = "K13" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
215NET "SF_A<11>" LOC = "L15" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
216NET "SF_A<12>" LOC = "L16" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
217NET "SF_A<13>" LOC = "T18" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
218NET "SF_A<14>" LOC = "R18" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
219NET "SF_A<15>" LOC = "T17" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
220NET "SF_A<16>" LOC = "U18" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
221NET "SF_A<17>" LOC = "T16" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
222NET "SF_A<18>" LOC = "U15" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
223NET "SF_A<19>" LOC = "V15" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
224NET "SF_A<20>" LOC = "T12" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
225NET "SF_A<21>" LOC = "V13" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
226NET "SF_A<22>" LOC = "V12" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
227NET "SF_A<23>" LOC = "N11" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
228NET "SF_A<24>" LOC = "A11" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
229NET "SF_BYTE" LOC = "C17" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
230NET "SF_CE0" LOC = "D16" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
231NET "SF_D<1>" LOC = "P10" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
232NET "SF_D<2>" LOC = "R10" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
233NET "SF_D<3>" LOC = "V9" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
234NET "SF_D<4>" LOC = "U9" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
235NET "SF_D<5>" LOC = "R9" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
236NET "SF_D<6>" LOC = "M9" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
237NET "SF_D<7>" LOC = "N9" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
238NET "SF_D<8>" LOC = "R15" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
239NET "SF_D<9>" LOC = "R16" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
240NET "SF_D<10>" LOC = "P17" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
241NET "SF_D<11>" LOC = "M15" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
242NET "SF_D<12>" LOC = "M16" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
243NET "SF_D<13>" LOC = "P6" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
244NET "SF_D<14>" LOC = "R8" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
245NET "SF_D<15>" LOC = "T8" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
246NET "SF_OE" LOC = "C18" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
247NET "SF_STS" LOC = "B18" | IOSTANDARD = LVCMOS33 ;
248NET "SF_WE" LOC = "D17" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
249# ==== STMicro SPI serial Flash (SPI) ====
250# some connections shared with SPI Flash, DAC, ADC, and AMP
251NET "SPI_MISO" LOC = "N10" | IOSTANDARD = LVCMOS33 ;
252#NET "SPI_MOSI" LOC = "T4" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 6 ;
253#NET "SPI_SCK" LOC = "U16" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 6 ;
254#NET "SPI_SS_B" LOC = "U3" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 6 ;
255#NET "SPI_ALT_CS_JP11" LOC = "R12" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 6 ;
256# ==== Slide Switches (SW) ====
257NET "SW<0>" LOC = "L13" | IOSTANDARD = LVTTL | PULLUP ;
258NET "SW<1>" LOC = "L14" | IOSTANDARD = LVTTL | PULLUP ;
259NET "SW<2>" LOC = "H18" | IOSTANDARD = LVTTL | PULLUP ;
260NET "SW<3>" LOC = "N17" | IOSTANDARD = LVTTL | PULLUP ;
261# ==== VGA Port (VGA) ====
262NET "VGA_BLUE" LOC = "G15" | IOSTANDARD = LVTTL | DRIVE = 8 | SLEW = FAST ;
263NET "VGA_GREEN" LOC = "H15" | IOSTANDARD = LVTTL | DRIVE = 8 | SLEW = FAST ;
264NET "VGA_HSYNC" LOC = "F15" | IOSTANDARD = LVTTL | DRIVE = 8 | SLEW = FAST ;
265NET "VGA_RED" LOC = "H14" | IOSTANDARD = LVTTL | DRIVE = 8 | SLEW = FAST ;
266NET "VGA_VSYNC" LOC = "F14" | IOSTANDARD = LVTTL | DRIVE = 8 | SLEW = FAST ;
267# ==== Xilinx CPLD (XC) ====
268#NET "XC_CMD<0>" LOC = "P18" | IOSTANDARD = LVTTL | DRIVE = 4 | SLEW = SLOW ;
269#NET "XC_CMD<1>" LOC = "N18" | IOSTANDARD = LVTTL | DRIVE = 4 | SLEW = SLOW ;
270#NET "XC_CPLD_EN" LOC = "B10" | IOSTANDARD = LVTTL ;
271#NET "XC_D<0>" LOC = "G16" | IOSTANDARD = LVTTL | DRIVE = 4 | SLEW = SLOW ;
272#NET "XC_D<1>" LOC = "F18" | IOSTANDARD = LVTTL | DRIVE = 4 | SLEW = SLOW ;
273#NET "XC_D<2>" LOC = "F17" | IOSTANDARD = LVTTL | DRIVE = 4 | SLEW = SLOW ;
274#NET "XC_TRIG" LOC = "R17" | IOSTANDARD = LVCMOS33 ;
275#NET "XC_GCK0" LOC = "H16" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
276#NET "GCLK10" LOC = "C9" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
277NET "CLK_50MHZ" TNM_NET = "CLK_50MHZ";
278NET "clk_reg1" TNM_NET = "clk_reg1";
279TIMESPEC "TS_clk_reg1" = PERIOD "clk_reg1" 40 ns HIGH 50 %;
plasma/logic/plasma_3e.vhd
1library ieee;
2use ieee.std_logic_1164.all;
3use ieee.std_logic_unsigned.all;
4use ieee.std_logic_arith.all;
5--use work.mlite_pack.all;
6
7entity plasma_3e is
8   port(CLK_50MHZ : in std_logic;
9        RS232_DCE_RXD : in std_logic;
10        RS232_DCE_TXD : out std_logic;
11
12        SD_CK_P : out std_logic; --DDR SDRAM clock_positive
13        SD_CK_N : out std_logic; --clock_negative
14        SD_CKE : out std_logic; --clock_enable
15
16        SD_BA : out std_logic_vector(1 downto 0); --bank_address
17        SD_A : out std_logic_vector(12 downto 0); --address(row or col)
18        SD_CS : out std_logic; --chip_select
19        SD_RAS : out std_logic; --row_address_strobe
20        SD_CAS : out std_logic; --column_address_strobe
21        SD_WE : out std_logic; --write_enable
22
23        SD_DQ : inout std_logic_vector(15 downto 0); --data
24        SD_UDM : out std_logic; --upper_byte_enable
25        SD_UDQS : inout std_logic; --upper_data_strobe
26        SD_LDM : out std_logic; --low_byte_enable
27        SD_LDQS : inout std_logic; --low_data_strobe
28
29        E_MDC : out std_logic; --Ethernet PHY
30        E_MDIO : inout std_logic; --management data in/out
31        E_RX_CLK : in std_logic; --receive clock
32        E_RX_DV : in std_logic; --data valid
33        E_RXD : in std_logic_vector(3 downto 0);
34        E_TX_CLK : in std_logic; --transmit clock
35        E_TX_EN : out std_logic; --data valid
36        E_TXD : out std_logic_vector(3 downto 0);
37
38        SF_CE0 : out std_logic; --NOR flash
39        SF_OE : out std_logic;
40        SF_WE : out std_logic;
41        SF_BYTE : out std_logic;
42        SF_STS : in std_logic; --status
43        SF_A : out std_logic_vector(24 downto 0);
44        SF_D : inout std_logic_vector(15 downto 1);
45        SPI_MISO : inout std_logic;
46
47        VGA_VSYNC : out std_logic; --VGA port
48        VGA_HSYNC : out std_logic;
49        VGA_RED : out std_logic;
50        VGA_GREEN : out std_logic;
51        VGA_BLUE : out std_logic;
52
53        PS2_CLK : in std_logic; --Keyboard
54        PS2_DATA : in std_logic;
55
56        LED : out std_logic_vector(7 downto 0);
57        ROT_CENTER : in std_logic;
58        ROT_A : in std_logic;
59        ROT_B : in std_logic;
60        BTN_EAST : in std_logic;
61        BTN_NORTH : in std_logic;
62        BTN_SOUTH : in std_logic;
63        BTN_WEST : in std_logic;
64        SW : in std_logic_vector(3 downto 0));
65end; --entity plasma_if
66
67
68architecture logic of plasma_3e is
69
70   component plasma
71      generic(memory_type : string := "XILINX_16X"; --"DUAL_PORT_" "ALTERA_LPM";
72              log_file : string := "UNUSED";
73              ethernet : std_logic := '0';
74              use_cache : std_logic := '0');
75      port(clk : in std_logic;
76           reset : in std_logic;
77           uart_write : out std_logic;
78           uart_read : in std_logic;
79
80           address : out std_logic_vector(31 downto 2);
81           byte_we : out std_logic_vector(3 downto 0);
82           data_write : out std_logic_vector(31 downto 0);
83           data_read : in std_logic_vector(31 downto 0);
84           mem_pause_in : in std_logic;
85           no_ddr_start : out std_logic;
86           no_ddr_stop : out std_logic;
87
88           gpio0_out : out std_logic_vector(31 downto 0);
89           gpioA_in : in std_logic_vector(31 downto 0));
90   end component; --plasma
91
92   component ddr_ctrl
93      port(clk : in std_logic;
94           clk_2x : in std_logic;
95           reset_in : in std_logic;
96
97           address : in std_logic_vector(25 downto 2);
98           byte_we : in std_logic_vector(3 downto 0);
99           data_w : in std_logic_vector(31 downto 0);
100           data_r : out std_logic_vector(31 downto 0);
101           active : in std_logic;
102           no_start : in std_logic;
103           no_stop : in std_logic;
104           pause : out std_logic;
105
106           SD_CK_P : out std_logic; --clock_positive
107           SD_CK_N : out std_logic; --clock_negative
108           SD_CKE : out std_logic; --clock_enable
109
110           SD_BA : out std_logic_vector(1 downto 0); --bank_address
111           SD_A : out std_logic_vector(12 downto 0); --address(row or col)
112           SD_CS : out std_logic; --chip_select
113           SD_RAS : out std_logic; --row_address_strobe
114           SD_CAS : out std_logic; --column_address_strobe
115           SD_WE : out std_logic; --write_enable
116
117           SD_DQ : inout std_logic_vector(15 downto 0); --data
118           SD_UDM : out std_logic; --upper_byte_enable
119           SD_UDQS : inout std_logic; --upper_data_strobe
120           SD_LDM : out std_logic; --low_byte_enable
121           SD_LDQS : inout std_logic); --low_data_strobe
122   end component; --ddr
123
124   signal clk_reg : std_logic;
125   signal address : std_logic_vector(31 downto 2);
126   signal data_write : std_logic_vector(31 downto 0);
127   signal data_read : std_logic_vector(31 downto 0);
128   signal data_r_ddr : std_logic_vector(31 downto 0);
129   signal byte_we : std_logic_vector(3 downto 0);
130   signal write_enable : std_logic;
131   signal pause_ddr : std_logic;
132   signal pause : std_logic;
133   signal no_ddr_start : std_logic;
134   signal no_ddr_stop : std_logic;
135   signal ddr_active : std_logic;
136   signal flash_active : std_logic;
137   signal flash_cnt : std_logic_vector(1 downto 0);
138   signal flash_we : std_logic;
139   signal reset : std_logic;
140   signal gpio0_out : std_logic_vector(31 downto 0);
141   signal gpio0_in : std_logic_vector(31 downto 0);
142
143begin --architecture
144   --Divide 50 MHz clock by two
145   clk_div: process(reset, CLK_50MHZ, clk_reg)
146   begin
147      if reset = '1' then
148         clk_reg <= '0';
149      elsif rising_edge(CLK_50MHZ) then
150         clk_reg <= not clk_reg;
151      end if;
152   end process; --clk_div
153
154   reset <= ROT_CENTER;
155   E_TX_EN <= gpio0_out(28); --Ethernet
156   E_TXD <= gpio0_out(27 downto 24);
157   E_MDC <= gpio0_out(23);
158   E_MDIO <= gpio0_out(21) when gpio0_out(22) = '1' else 'Z';
159   VGA_VSYNC <= gpio0_out(20);
160   VGA_HSYNC <= gpio0_out(19);
161   VGA_RED <= gpio0_out(18);
162   VGA_GREEN <= gpio0_out(17);
163   VGA_BLUE <= gpio0_out(16);
164   LED <= gpio0_out(7 downto 0);
165   gpio0_in(31 downto 21) <= (others => '0');
166   gpio0_in(20 downto 13) <= E_RX_CLK & E_RX_DV & E_RXD & E_TX_CLK & E_MDIO;
167   gpio0_in(12 downto 10) <= SF_STS & PS2_CLK & PS2_DATA;
168   gpio0_in(9 downto 0) <= ROT_A & ROT_B & BTN_EAST & BTN_NORTH &
169                           BTN_SOUTH & BTN_WEST & SW;
170   ddr_active <= '1' when address(31 downto 28) = "0001" else '0';
171   flash_active <= '1' when address(31 downto 28) = "0011" else '0';
172   write_enable <= '1' when byte_we /= "0000" else '0';
173
174   u1_plama: plasma
175      generic map (memory_type => "XILINX_16X",
176                   log_file => "UNUSED",
177                   ethernet => '1',
178                   use_cache => '1')
179      --generic map (memory_type => "DUAL_PORT_",
180      -- log_file => "output2.txt",
181      -- ethernet => '1')
182      PORT MAP (
183         clk => clk_reg,
184         reset => reset,
185         uart_write => RS232_DCE_TXD,
186         uart_read => RS232_DCE_RXD,
187
188         address => address,
189         byte_we => byte_we,
190         data_write => data_write,
191         data_read => data_read,
192         mem_pause_in => pause,
193         no_ddr_start => no_ddr_start,
194         no_ddr_stop => no_ddr_stop,
195
196         gpio0_out => gpio0_out,
197         gpioA_in => gpio0_in);
198
199   u2_ddr: ddr_ctrl
200      port map (
201         clk => clk_reg,
202         clk_2x => CLK_50MHZ,
203         reset_in => reset,
204
205         address => address(25 downto 2),
206         byte_we => byte_we,
207         data_w => data_write,
208         data_r => data_r_ddr,
209         active => ddr_active,
210         no_start => no_ddr_start,
211         no_stop => no_ddr_stop,
212         pause => pause_ddr,
213
214         SD_CK_P => SD_CK_P, --clock_positive
215         SD_CK_N => SD_CK_N, --clock_negative
216         SD_CKE => SD_CKE, --clock_enable
217
218         SD_BA => SD_BA, --bank_address
219         SD_A => SD_A, --address(row or col)
220         SD_CS => SD_CS, --chip_select
221         SD_RAS => SD_RAS, --row_address_strobe
222         SD_CAS => SD_CAS, --column_address_strobe
223         SD_WE => SD_WE, --write_enable
224
225         SD_DQ => SD_DQ, --data
226         SD_UDM => SD_UDM, --upper_byte_enable
227         SD_UDQS => SD_UDQS, --upper_data_strobe
228         SD_LDM => SD_LDM, --low_byte_enable
229         SD_LDQS => SD_LDQS); --low_data_strobe
230
231   --Flash control (only lower 16-bit data lines connected)
232   flash_ctrl: process(reset, clk_reg, flash_active, write_enable,
233                       flash_cnt, pause_ddr)
234   begin
235      if reset = '1' then
236         flash_cnt <= "00";
237         flash_we <= '1';
238      elsif rising_edge(clk_reg) then
239         if flash_active = '0' then
240            flash_cnt <= "00";
241            flash_we <= '1';
242         else
243            if write_enable = '1' and flash_cnt(1) = '0' then
244               flash_we <= '0';
245            else
246               flash_we <= '1';
247            end if;
248            if flash_cnt /= "11" then
249               flash_cnt <= flash_cnt + 1;
250            end if;
251         end if;
252      end if; --rising_edge(clk_reg)
253      if pause_ddr = '1' or (flash_active = '1' and flash_cnt /= "11") then
254         pause <= '1';
255      else
256         pause <= '0';
257      end if;
258   end process; --flash_ctrl
259
260   SF_CE0 <= not flash_active;
261   SF_OE <= write_enable or not flash_active;
262   SF_WE <= flash_we;
263   SF_BYTE <= '1'; --16-bit access
264   SF_A <= address(25 downto 2) & '0' when flash_active = '1' else
265              "0000000000000000000000000";
266   SF_D <= data_write(15 downto 1) when
267              flash_active = '1' and write_enable = '1'
268              else "ZZZZZZZZZZZZZZZ";
269   SPI_MISO <= data_write(0) when
270              flash_active = '1' and write_enable = '1'
271              else 'Z';
272   data_read(31 downto 16) <= data_r_ddr(31 downto 16);
273   data_read(15 downto 0) <= data_r_ddr(15 downto 0) when flash_active = '0'
274                             else SF_D & SPI_MISO;
275
276end; --architecture logic
277
plasma/logic/plasma_if.ucf
1NET "clk_in" TNM_NET = "clk_in";
2TIMESPEC "TS_clk_in" = PERIOD "clk_in" 20 ns HIGH 50 %;
3#NET "clk_reg1" TNM_NET = "clk_reg1";
4#TIMESPEC "TS_clk_reg1" = PERIOD "clk_reg1" 40 ns HIGH 50 %;
5NET "clk_reg1" TNM_NET = "clk_reg1";
6TIMESPEC "TS_clk_reg1" = PERIOD "clk_reg1" 39.9 ns HIGH 50 %;
7#PACE: Start of Constraints generated by PACE
8#PACE: Start of PACE I/O Pin Assignments
9NET "clk_in" LOC = "T9";
10NET "gpio0_out<0>" LOC = "K12";
11NET "gpio0_out<10>" LOC = "N15";
12NET "gpio0_out<11>" LOC = "P15";
13NET "gpio0_out<12>" LOC = "R16";
14NET "gpio0_out<13>" LOC = "F13";
15NET "gpio0_out<14>" LOC = "N16";
16NET "gpio0_out<15>" LOC = "P16";
17NET "gpio0_out<16>" LOC = "E13";
18NET "gpio0_out<17>" LOC = "F14";
19NET "gpio0_out<18>" LOC = "G14";
20NET "gpio0_out<19>" LOC = "D14";
21NET "gpio0_out<1>" LOC = "P14";
22NET "gpio0_out<24>" LOC = "R12";
23NET "gpio0_out<25>" LOC = "T12";
24NET "gpio0_out<26>" LOC = "R11";
25NET "gpio0_out<27>" LOC = "R9";
26NET "gpio0_out<28>" LOC = "T10";
27NET "gpio0_out<2>" LOC = "L12";
28NET "gpio0_out<3>" LOC = "N14";
29NET "gpio0_out<4>" LOC = "P13";
30NET "gpio0_out<5>" LOC = "N12";
31NET "gpio0_out<6>" LOC = "P12";
32NET "gpio0_out<7>" LOC = "P11";
33NET "gpio0_out<8>" LOC = "E14";
34NET "gpio0_out<9>" LOC = "G13";
35NET "gpioA_in<0>" LOC = "F12";
36NET "gpioA_in<10>" LOC = "L13";
37NET "gpioA_in<1>" LOC = "G12";
38NET "gpioA_in<2>" LOC = "H14";
39NET "gpioA_in<30>" LOC = "M15";
40NET "gpioA_in<31>" LOC = "M16";
41NET "gpioA_in<3>" LOC = "H13";
42NET "gpioA_in<4>" LOC = "J14";
43NET "gpioA_in<5>" LOC = "J13";
44NET "gpioA_in<6>" LOC = "K14";
45NET "gpioA_in<7>" LOC = "K13";
46NET "gpioA_in<8>" LOC = "M13";
47NET "gpioA_in<9>" LOC = "M14";
48NET "ram_address<10>" LOC = "E3";
49NET "ram_address<11>" LOC = "E4";
50NET "ram_address<12>" LOC = "G5";
51NET "ram_address<13>" LOC = "H3";
52NET "ram_address<14>" LOC = "H4";
53NET "ram_address<15>" LOC = "J4";
54NET "ram_address<16>" LOC = "J3";
55NET "ram_address<17>" LOC = "K3";
56NET "ram_address<18>" LOC = "K5";
57NET "ram_address<19>" LOC = "L3";
58NET "ram_address<2>" LOC = "L5";
59NET "ram_address<3>" LOC = "N3";
60NET "ram_address<4>" LOC = "M4";
61NET "ram_address<5>" LOC = "M3";
62NET "ram_address<6>" LOC = "L4";
63NET "ram_address<7>" LOC = "G4";
64NET "ram_address<8>" LOC = "F3";
65NET "ram_address<9>" LOC = "F4";
66NET "ram_ce1_n" LOC = "P7";
67NET "ram_ce2_n" LOC = "N5";
68NET "ram_data<0>" LOC = "P2";
69NET "ram_data<10>" LOC = "G1";
70NET "ram_data<11>" LOC = "F5";
71NET "ram_data<12>" LOC = "C3";
72NET "ram_data<13>" LOC = "K2";
73NET "ram_data<14>" LOC = "M1";
74NET "ram_data<15>" LOC = "N1";
75NET "ram_data<16>" LOC = "N7";
76NET "ram_data<17>" LOC = "T8";
77NET "ram_data<18>" LOC = "R6";
78NET "ram_data<19>" LOC = "T5";
79NET "ram_data<1>" LOC = "N2";
80NET "ram_data<20>" LOC = "R5";
81NET "ram_data<21>" LOC = "C2";
82NET "ram_data<22>" LOC = "C1";
83NET "ram_data<23>" LOC = "B1";
84NET "ram_data<24>" LOC = "D3";
85NET "ram_data<25>" LOC = "P8";
86NET "ram_data<26>" LOC = "F2";
87NET "ram_data<27>" LOC = "H1";
88NET "ram_data<28>" LOC = "J2";
89NET "ram_data<29>" LOC = "L2";
90NET "ram_data<2>" LOC = "M2";
91NET "ram_data<30>" LOC = "P1";
92NET "ram_data<31>" LOC = "R1";
93NET "ram_data<3>" LOC = "K1";
94NET "ram_data<4>" LOC = "J1";
95NET "ram_data<5>" LOC = "G2";
96NET "ram_data<6>" LOC = "E1";
97NET "ram_data<7>" LOC = "D1";
98NET "ram_data<8>" LOC = "D2";
99NET "ram_data<9>" LOC = "E2";
100NET "ram_lb1_n" LOC = "P6";
101NET "ram_lb2_n" LOC = "P5";
102NET "ram_oe_n" LOC = "K4";
103NET "ram_ub1_n" LOC = "T4";
104NET "ram_ub2_n" LOC = "R4";
105NET "ram_we_n" LOC = "G3";
106NET "reset" LOC = "L14";
107NET "uart_read" LOC = "T13";
108NET "uart_write" LOC = "R13";
109#PACE: Start of PACE Area Constraints
110#PACE: Start of PACE Prohibit Constraints
111#PACE: End of Constraints generated by PACE
plasma/logic/plasma_if.vhd
1---------------------------------------------------------------------
2-- TITLE: Plamsa Interface (clock divider and interface to FPGA board)
3-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4-- DATE CREATED: 6/6/02
5-- FILENAME: plasma_if.vhd
6-- PROJECT: Plasma CPU core
7-- COPYRIGHT: Software placed into the public domain by the author.
8-- Software 'as is' without warranty. Author liable for nothing.
9-- DESCRIPTION:
10-- This entity divides the clock by two and interfaces to the
11-- Altera EP20K200EFC484-2X FPGA board.
12-- Xilinx Spartan-3 XC3S200FT256-4 FPGA.
13---------------------------------------------------------------------
14library ieee;
15use ieee.std_logic_1164.all;
16--use work.mlite_pack.all;
17
18entity plasma_if is
19   port(clk_in : in std_logic;
20        reset : in std_logic;
21        uart_read : in std_logic;
22        uart_write : out std_logic;
23
24        ram_address : out std_logic_vector(31 downto 2);
25        ram_data : inout std_logic_vector(31 downto 0);
26        ram_ce1_n : out std_logic;
27        ram_ub1_n : out std_logic;
28        ram_lb1_n : out std_logic;
29        ram_ce2_n : out std_logic;
30        ram_ub2_n : out std_logic;
31        ram_lb2_n : out std_logic;
32        ram_we_n : out std_logic;
33        ram_oe_n : out std_logic;
34
35        gpio0_out : out std_logic_vector(31 downto 0);
36        gpioA_in : in std_logic_vector(31 downto 0));
37end; --entity plasma_if
38
39
40architecture logic of plasma_if is
41
42   component plasma
43      generic(memory_type : string := "XILINX_16X"; --"DUAL_PORT_" "ALTERA_LPM";
44              log_file : string := "UNUSED");
45      port(clk : in std_logic;
46           reset : in std_logic;
47           uart_write : out std_logic;
48           uart_read : in std_logic;
49
50           address : out std_logic_vector(31 downto 2);
51           byte_we : out std_logic_vector(3 downto 0);
52           data_write : out std_logic_vector(31 downto 0);
53           data_read : in std_logic_vector(31 downto 0);
54           mem_pause_in : in std_logic;
55
56           gpio0_out : out std_logic_vector(31 downto 0);
57           gpioA_in : in std_logic_vector(31 downto 0));
58   end component; --plasma
59
60   signal clk_reg : std_logic;
61   signal we_n_next : std_logic;
62   signal we_n_reg : std_logic;
63   signal mem_address : std_logic_vector(31 downto 2);
64   signal data_write : std_logic_vector(31 downto 0);
65   signal data_reg : std_logic_vector(31 downto 0);
66   signal byte_we : std_logic_vector(3 downto 0);
67   signal mem_pause_in : std_logic;
68
69begin --architecture
70   --Divide 50 MHz clock by two
71   clk_div: process(reset, clk_in, clk_reg, we_n_next)
72   begin
73      if reset = '1' then
74         clk_reg <= '0';
75      elsif rising_edge(clk_in) then
76         clk_reg <= not clk_reg;
77      end if;
78
79      if reset = '1' then
80         we_n_reg <= '1';
81         data_reg <= (others => '0');
82      elsif falling_edge(clk_in) then
83         we_n_reg <= we_n_next or not clk_reg;
84         data_reg <= ram_data;
85      end if;
86   end process; --clk_div
87
88   mem_pause_in <= '0';
89   ram_address <= mem_address(31 downto 2);
90   ram_we_n <= we_n_reg;
91
92   --For Xilinx Spartan-3 Starter Kit
93   ram_control:
94   process(clk_reg, mem_address, byte_we, data_write)
95   begin
96      if mem_address(30 downto 28) = "001" then --RAM
97         ram_ce1_n <= '0';
98         ram_ce2_n <= '0';
99         if byte_we = "0000" then --read
100            ram_data <= (others => 'Z');
101            ram_ub1_n <= '0';
102            ram_lb1_n <= '0';
103            ram_ub2_n <= '0';
104            ram_lb2_n <= '0';
105            we_n_next <= '1';
106            ram_oe_n <= '0';
107         else --write
108            if clk_reg = '1' then
109               ram_data <= (others => 'Z');
110            else
111               ram_data <= data_write;
112            end if;
113            ram_ub1_n <= not byte_we(3);
114            ram_lb1_n <= not byte_we(2);
115            ram_ub2_n <= not byte_we(1);
116            ram_lb2_n <= not byte_we(0);
117            we_n_next <= '0';
118            ram_oe_n <= '1';
119         end if;
120      else
121         ram_data <= (others => 'Z');
122         ram_ce1_n <= '1';
123         ram_ub1_n <= '1';
124         ram_lb1_n <= '1';
125         ram_ce2_n <= '1';
126         ram_ub2_n <= '1';
127         ram_lb2_n <= '1';
128         we_n_next <= '1';
129         ram_oe_n <= '1';
130      end if;
131   end process; --ram_control
132
133   u1_plama: plasma
134      generic map (memory_type => "XILINX_16X",
135                   log_file => "UNUSED")
136      PORT MAP (
137         clk => clk_reg,
138         reset => reset,
139         uart_write => uart_write,
140         uart_read => uart_read,
141
142         address => mem_address,
143         byte_we => byte_we,
144         data_write => data_write,
145         data_read => data_reg,
146         mem_pause_in => mem_pause_in,
147
148         gpio0_out => gpio0_out,
149         gpioA_in => gpioA_in);
150
151end; --architecture logic
152
plasma/logic/prog.cmd
1setmode -bscan
2setcable -p auto
3identify
4assignfile -p 1 -file plasma_3e.bit
5program -p 1
6quit
plasma/logic/ram.vhd
1---------------------------------------------------------------------
2-- TITLE: Random Access Memory
3-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4-- DATE CREATED: 4/21/01
5-- FILENAME: ram.vhd
6-- PROJECT: Plasma CPU core
7-- COPYRIGHT: Software placed into the public domain by the author.
8-- Software 'as is' without warranty. Author liable for nothing.
9-- DESCRIPTION:
10-- Implements the RAM, reads the executable from either "code.txt",
11-- or for Altera "code[0-3].hex".
12-- Modified from "The Designer's Guide to VHDL" by Peter J. Ashenden
13---------------------------------------------------------------------
14library ieee;
15use ieee.std_logic_1164.all;
16use ieee.std_logic_misc.all;
17use ieee.std_logic_arith.all;
18use ieee.std_logic_unsigned.all;
19use ieee.std_logic_textio.all;
20use std.textio.all;
21use work.mlite_pack.all;
22
23entity ram is
24   generic(memory_type : string := "DEFAULT");
25   port(clk : in std_logic;
26        enable : in std_logic;
27        write_byte_enable : in std_logic_vector(3 downto 0);
28        address : in std_logic_vector(31 downto 2);
29        data_write : in std_logic_vector(31 downto 0);
30        data_read : out std_logic_vector(31 downto 0));
31end; --entity ram
32
33architecture logic of ram is
34   constant ADDRESS_WIDTH : natural := 13;
35begin
36
37   generic_ram:
38   if memory_type /= "ALTERA_LPM" generate
39   begin
40   --Simulate a synchronous RAM
41   ram_proc: process(clk, enable, write_byte_enable,
42         address, data_write) --mem_write, mem_sel
43      variable mem_size : natural := 2 ** ADDRESS_WIDTH;
44      variable data : std_logic_vector(31 downto 0);
45      subtype word is std_logic_vector(data_write'length-1 downto 0);
46      type storage_array is
47         array(natural range 0 to mem_size/4 - 1) of word;
48      variable storage : storage_array;
49      variable index : natural := 0;
50      file load_file : text open read_mode is "code.txt";
51      variable hex_file_line : line;
52   begin
53
54      --Load in the ram executable image
55      if index = 0 then
56         while not endfile(load_file) loop
57--The following two lines had to be commented out for synthesis
58            readline(load_file, hex_file_line);
59            hread(hex_file_line, data);
60            storage(index) := data;
61            index := index + 1;
62         end loop;
63      end if;
64
65      if rising_edge(clk) then
66         index := conv_integer(address(ADDRESS_WIDTH-1 downto 2));
67         data := storage(index);
68
69         if enable = '1' then
70            if write_byte_enable(0) = '1' then
71               data(7 downto 0) := data_write(7 downto 0);
72            end if;
73            if write_byte_enable(1) = '1' then
74               data(15 downto 8) := data_write(15 downto 8);
75            end if;
76            if write_byte_enable(2) = '1' then
77               data(23 downto 16) := data_write(23 downto 16);
78            end if;
79            if write_byte_enable(3) = '1' then
80               data(31 downto 24) := data_write(31 downto 24);
81            end if;
82         end if;
83
84         if write_byte_enable /= "0000" then
85            storage(index) := data;
86         end if;
87      end if;
88
89      data_read <= data;
90   end process;
91   end generate; --generic_ram
92
93
94   altera_ram:
95   if memory_type = "ALTERA_LPM" generate
96      signal byte_we : std_logic_vector(3 downto 0);
97   begin
98      byte_we <= write_byte_enable when enable = '1' else "0000";
99      lpm_ram_io_component0 : lpm_ram_dq
100         GENERIC MAP (
101            intended_device_family => "UNUSED",
102            lpm_width => 8,
103            lpm_widthad => ADDRESS_WIDTH-2,
104            lpm_indata => "REGISTERED",
105            lpm_address_control => "REGISTERED",
106            lpm_outdata => "UNREGISTERED",
107            lpm_file => "code0.hex",
108            use_eab => "ON",
109            lpm_type => "LPM_RAM_DQ")
110         PORT MAP (
111            data => data_write(31 downto 24),
112            address => address(ADDRESS_WIDTH-1 downto 2),
113            inclock => clk,
114            we => byte_we(3),
115            q => data_read(31 downto 24));
116
117      lpm_ram_io_component1 : lpm_ram_dq
118         GENERIC MAP (
119            intended_device_family => "UNUSED",
120            lpm_width => 8,
121            lpm_widthad => ADDRESS_WIDTH-2,
122            lpm_indata => "REGISTERED",
123            lpm_address_control => "REGISTERED",
124            lpm_outdata => "UNREGISTERED",
125            lpm_file => "code1.hex",
126            use_eab => "ON",
127            lpm_type => "LPM_RAM_DQ")
128         PORT MAP (
129            data => data_write(23 downto 16),
130            address => address(ADDRESS_WIDTH-1 downto 2),
131            inclock => clk,
132            we => byte_we(2),
133            q => data_read(23 downto 16));
134
135      lpm_ram_io_component2 : lpm_ram_dq
136         GENERIC MAP (
137            intended_device_family => "UNUSED",
138            lpm_width => 8,
139            lpm_widthad => ADDRESS_WIDTH-2,
140            lpm_indata => "REGISTERED",
141            lpm_address_control => "REGISTERED",
142            lpm_outdata => "UNREGISTERED",
143            lpm_file => "code2.hex",
144            use_eab => "ON",
145            lpm_type => "LPM_RAM_DQ")
146         PORT MAP (
147            data => data_write(15 downto 8),
148            address => address(ADDRESS_WIDTH-1 downto 2),
149            inclock => clk,
150            we => byte_we(1),
151            q => data_read(15 downto 8));
152
153      lpm_ram_io_component3 : lpm_ram_dq
154         GENERIC MAP (
155            intended_device_family => "UNUSED",
156            lpm_width => 8,
157            lpm_widthad => ADDRESS_WIDTH-2,
158            lpm_indata => "REGISTERED",
159            lpm_address_control => "REGISTERED",
160            lpm_outdata => "UNREGISTERED",
161            lpm_file => "code3.hex",
162            use_eab => "ON",
163            lpm_type => "LPM_RAM_DQ")
164         PORT MAP (
165            data => data_write(7 downto 0),
166            address => address(ADDRESS_WIDTH-1 downto 2),
167            inclock => clk,
168            we => byte_we(0),
169            q => data_read(7 downto 0));
170
171   end generate; --altera_ram
172
173
174   --For XILINX see ram_xilinx.vhd
175
176end; --architecture logic
plasma/logic/ram_image.vhd
1---------------------------------------------------------------------
2-- TITLE: Random Access Memory for Xilinx
3-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4-- DATE CREATED: 11/06/05
5-- FILENAME: ram_xilinx.vhd
6-- PROJECT: Plasma CPU core
7-- COPYRIGHT: Software placed into the public domain by the author.
8-- Software 'as is' without warranty. Author liable for nothing.
9-- DESCRIPTION:
10-- Implements the RAM for Spartan 3 Xilinx FPGA
11--
12-- Compile the MIPS C and assembly code into "test.axf".
13-- Run convert.exe to change "test.axf" to "code.txt" which
14-- will contain the hex values of the opcodes.
15-- Next run "ram_image ram_xilinx.vhd code.txt ram_image.vhd",
16-- to create the "ram_image.vhd" file that will have the opcodes
17-- correctly placed inside the INIT_00 => strings.
18-- Then include ram_image.vhd in the simulation/synthesis.
19---------------------------------------------------------------------
20library ieee;
21use ieee.std_logic_1164.all;
22use ieee.std_logic_misc.all;
23use ieee.std_logic_arith.all;
24use ieee.std_logic_unsigned.all;
25use work.mlite_pack.all;
26library UNISIM;
27use UNISIM.vcomponents.all;
28
29entity ram is
30   generic(memory_type : string := "DEFAULT");
31   port(clk : in std_logic;
32        enable : in std_logic;
33        write_byte_enable : in std_logic_vector(3 downto 0);
34        address : in std_logic_vector(31 downto 2);
35        data_write : in std_logic_vector(31 downto 0);
36        data_read : out std_logic_vector(31 downto 0));
37end; --entity ram
38
39architecture logic of ram is
40begin
41
42   RAMB16_S9_inst0 : RAMB16_S9
43   generic map (
44INIT_00 => X"afafafafafafafafafafafafafafafaf2308000c241400ac273c243c243c273c",
45INIT_01 => X"8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f230c008c8c3caf00af00af2340afaf",
46INIT_02 => X"acacacac0003373cac038cac8cac8cac8c243c40034040033423038f038f8f8f",
47INIT_03 => X"000300ac0300000034038c8c8c8c8c8c8c8c8c8c8c8c3403acacacacacacacac",
48INIT_04 => X"1c24001030008c24ac24ac9424003c00180003241c24a4248c0018ac2400003c",
49INIT_05 => X"a00024241028302400a03c24243c3c0003001030008cacac242400003c000300",
50INIT_06 => X"100010000c00102a0200260c24af08af2424240000afafafafaf270103001424",
51INIT_07 => X"240c001a001427038f8f8f8f8f8f8f02240c240c000824102c24142c24142e24",
52INIT_08 => X"3c240c3c240c3c240c3c240c3caf0cafafafafafafafafaf270008260c24240c",
53INIT_09 => X"3c3c3c3c3c3c003c3c0c003c240c3c3c1430248c3c1030008c34ac3c3c24240c",
54INIT_0A => X"0c3c240c3c270c260c260c260c260c240c3c240c3c240c3c240c3c240c3c240c",
55INIT_0B => X"3c3c08240c3c000c000c8e0000008c0024003c3c102c260000142c2400000c24",
56INIT_0C => X"3c3c080002a208000c000c00000c240c3c0008923c08ae000c000c00000c240c",
57INIT_0D => X"080216a002260c00000010000c240c3c3c080216260c900200000010000c240c",
58INIT_0E => X"0010000c240c3c3c08240c000c000c0014002490020000000010000c240c3c3c",
59INIT_0F => X"240c3c021402240c000c260c8c021032021002240c000c260c8c02240c3c0000",
60INIT_10 => X"14343c000c240c3c3c0800003c0016260c262610000c3c120008a23c243c3c08",
61INIT_11 => X"0c000c2608240c3c000c020c240c3c00000c240c3c020c3c083c0c003c000c00",
62INIT_12 => X"00100082260c00240800100080afafaf270003ac001030008c343c3c08240c00",
63INIT_13 => X"2424142c3002242400afafafaf272703008f8f8f00140082000c2682000c2414",
64INIT_14 => X"24243c3c2703008f8c3c10000caf2730038c343c240827038f8f8f8f0216260c",
65INIT_15 => X"740a00616d20423a003531303241656c62747267650a24038c0014ac00248c3c",
66INIT_16 => X"617965330a7769796532006f61796531006e706e724f303030206e6569612020",
67INIT_17 => X"4600753900736838006979656137617965613673647475350a62697965340079",
68INIT_18 => X"37336820660a0d786e6e0a786e750a3d6541206820720a3e00616f446f42316f",
69INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000",
70INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",
71INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",
72INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",
73INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",
74INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",
75INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",
76INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",
77INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",
78INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",
79INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",
80INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",
81INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",
82INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",
83INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",
84INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",
85INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",
86INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",
87INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",
88INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",
89INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",
90INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",
91INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",
92INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",
93INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",
94INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",
95INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",
96INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",
97INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",
98INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",
99INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",
100INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",
101INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",
102INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",
103INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",
104INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",
105INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",
106INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",
107INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000")
108   port map (
109      DO => data_read(31 downto 24),
110      DOP => open,
111      ADDR => address(12 downto 2),
112      CLK => clk,
113      DI => data_write(31 downto 24),
114      DIP => ZERO(0 downto 0),
115      EN => enable,
116      SSR => ZERO(0),
117      WE => write_byte_enable(3));
118
119   RAMB16_S9_inst1 : RAMB16_S9
120   generic map (
121INIT_00 => X"b8afaeadacabaaa9a8a7a6a5a4a3a2a1bd000000a560a4a0bd1d8404a5059c1c",
122INIT_01 => X"b9b8afaeadacabaaa9a8a7a6a5a4a3a2a1a50086c6c406bb00bb00ba5a1abfb9",
123INIT_02 => X"9392919000405a1a06e0a606a606a606a6a50584e0029b401bbd60bb60bbbabf",
124INIT_03 => X"00e000c4e0000085a2e09f9d9c9e979695949392919002e09f9d9c9e97969594",
125INIT_04 => X"c0c60040420062636284658205620205c000e084c0a582c6a200c0a202a20502",
126INIT_05 => X"c2e5070740a285634040036642020300e000404200828283020382040200e000",
127INIT_06 => X"54405300000040220312310090b000bf1514130000b1b2b3b4b5bd00e004c3c6",
128INIT_07 => X"040000208095bde0b0b1b2b3b4b5bf4004000400000090404282404282400250",
129INIT_08 => X"04840004840004840004840004b000b1b2b3b4b5b6b7bebfbd12003100040400",
130INIT_09 => X"021e171615144002060000048400041543420382146063004342830204038400",
131INIT_0A => X"0002440002c400e400c400a40084004400024400024400024400024400024400",
132INIT_0B => X"0202004400024000000044008000444383030402406203000040424240000044",
133INIT_0C => X"0202000040500040004000400000440002000044020050400040004000004400",
134INIT_0D => X"0000136251100000004040000044000202000011100044420000404000004400",
135INIT_0E => X"404000004400020200040040000000a0a683a543420000004040000044000202",
136INIT_0F => X"4400020060130400400030004450400200601304004000300044504400020000",
137INIT_10 => X"4363030000440002020000400240535200101040000002110000501311120200",
138INIT_11 => X"0000000300440002400040004400024000004400020000020006000004000000",
139INIT_12 => X"00400002100040110080400082b1bfb0bd00e0a40040420062a3050200040040",
140INIT_13 => X"646440624312111080bfb0b1b2bdbde000b0b1bf004000024000100200000451",
141INIT_14 => X"63440302bde000bf6203400000bfbd42e06263030400bde0b0b1b2bf12111000",
142INIT_15 => X"6957007320666f0a003a39313170726f6f686f73744742e0a200834045848205",
143INIT_16 => X"64206d2e006f74206d2e007264206d2e007374752074303078616b206d726266",
144INIT_17 => X"2e006d2e0075652e0074206d772e64206d772e73646f6d2e007974206d2e0074",
145INIT_18 => X"3834207769430a3e2074433e206556207364006569654120007320526d203270",
146INIT_19 => X"0004000080240080000000000000000000000000000000000000000000000000",
147INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",
148INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",
149INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",
150INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",
151INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",
152INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",
153INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",
154INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",
155INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",
156INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",
157INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",
158INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",
159INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",
160INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",
161INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",
162INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",
163INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",
164INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",
165INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",
166INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",
167INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",
168INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",
169INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",
170INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",
171INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",
172INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",
173INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",
174INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",
175INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",
176INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",
177INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",
178INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",
179INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",
180INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",
181INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",
182INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",
183INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",
184INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000")
185   port map (
186      DO => data_read(23 downto 16),
187      DOP => open,
188      ADDR => address(12 downto 2),
189      CLK => clk,
190      DI => data_write(23 downto 16),
191      DIP => ZERO(0 downto 0),
192      EN => enable,
193      SSR => ZERO(0),
194      WE => write_byte_enable(2));
195
196   RAMB16_S9_inst2 : RAMB16_S9
197   generic map (
198INIT_00 => X"00000000000000000000000000000000ff00000100ff18000e000f000c008c00",
199INIT_01 => X"000000000000000000000000000000000000022000002000d800d800ff700000",
200INIT_02 => X"0000000000000010000000000000000000010060006060000000000000000000",
201INIT_03 => X"0000000000201000000000000000000000000000000000000000000000000000",
202INIT_04 => X"ffff00ff00000000000000000018301800000000ff0000ff0000000000282830",
203INIT_05 => X"001000000000000c4000000d0d0000000000ff00000000000000202030000000",
204INIT_06 => X"002000000200000090190002ff00000000000088900000000000ff100021ffff",
205INIT_07 => X"0002000080ff00000000000000000010000200020000ff0000ffff00ffff00ff",
206INIT_08 => X"000a02000c02000a02000a02000002000000000000000000ff9100ff02000002",
207INIT_09 => X"000000000000f810000028100a02000000ff3c00000000000000002030000a02",
208INIT_0A => X"02000b02000b020b020b020b020b020b02000b02000b02000b02000b02000a02",
209INIT_0B => X"0000010b0200200200000000000000100c100000ff00ff90000000ff8000020c",
210INIT_0C => X"00000100f80001200280002000000c0200000100000100200280002000000c02",
211INIT_0D => X"0188ff00180002888098ff00000c0200000110ff00020010108088ff00000c02",
212INIT_0E => X"980000000c0200000100022002000010ff20000010102028300000000c020000",
213INIT_0F => X"0c020088ff180002200200000010ff0088001800022002000000100c02008880",
214INIT_10 => X"ff561200000c0200000100f81080ff0002ff00ff000210008002001027100001",
215INIT_11 => X"022000ff010b0200200220000c02009000000c02002002000100002810200000",
216INIT_12 => X"00000000000220000280000000000000ff00000010ff00000000200001000220",
217INIT_13 => X"000000000010ff009000000000ff00001000000000ff000020020000000200ff",
218INIT_14 => X"0c0c0000000000000020ff000200ff0000000020000200000000000010ffff02",
219INIT_15 => X"6e61006866726f0000343a30207220616f656d20697200000000ff0010000010",
220INIT_16 => X"20726f20007265776f20006420726f20003a69204d680a303174656c6179696f",
221INIT_17 => X"20007020006d63200065776f20200a726f20200a72207020007465776f200065",
222INIT_18 => X"3e353169726f002068206f2068206100736400786e7364000068662020663879",
223INIT_19 => X"0020000000202800000804040404040404040408040407070606060606050500",
224INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",
225INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",
226INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",
227INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",
228INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",
229INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",
230INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",
231INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",
232INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",
233INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",
234INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",
235INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",
236INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",
237INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",
238INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",
239INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",
240INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",
241INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",
242INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",
243INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",
244INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",
245INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",
246INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",
247INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",
248INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",
249INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",
250INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",
251INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",
252INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",
253INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",
254INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",
255INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",
256INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",
257INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",
258INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",
259INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",
260INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",
261INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000")
262   port map (
263      DO => data_read(15 downto 8),
264      DOP => open,
265      ADDR => address(12 downto 2),
266      CLK => clk,
267      DI => data_write(15 downto 8),
268      DIP => ZERO(0 downto 0),
269      EN => enable,
270      SSR => ZERO(0),
271      WE => write_byte_enable(1));
272
273   RAMB16_S9_inst3 : RAMB16_S9
274   generic map (
275INIT_00 => X"4c4844403c3834302c2824201c181410980e000704fd2a00f8001000fc00f001",
276INIT_01 => X"504c4844403c3834302c2824201c181410008a2410200060125c1058fc005450",
277INIT_02 => X"0c08040000083c0048080c440840043c006000000800000801681360115c5854",
278INIT_03 => X"00080c000810121900082c2824201c1814100c08040000082c2824201c181410",
279INIT_04 => X"f4fe00fc80000004000200004021004011000802fb0400fe00000700ff214000",
280INIT_05 => X"00213037020a0fff21080007000000000800fc8000000000d020214000000800",
281INIT_06 => X"0c210e009100121021000145c910db28080d0a212114181c2024d0210802f7ff",
282INIT_07 => X"0845000821d930081014181c202428210a450d4500d4a9111a9fed1abff10ad0",
283INIT_08 => X"00d44f00344f00c84f00a84f00109c14181c2024282c3034c802d8ff45082045",
284INIT_09 => X"000000000000090002802100e44f00000cff1c00001001000050000000ffe04f",
285INIT_0A => X"4f00fc4f00f04fe04fc84fb44fa04f884f00704f00584f00404f00284f00f84f",
286INIT_0B => X"0000406c4f00214f00b100000800002184800000d416cf2100c20ad021009120",
287INIT_0C => X"0000400009003f214f21b12100c5444f00007600004000214f21b12100c5444f",
288INIT_0D => X"4021fb002101912121218900c5544f00004021fb014500212121219a00c5544f",
289INIT_0E => X"211e00c5544f0000400a45214f00b121fb21010021212121217600c5544f0000",
290INIT_0F => X"644f0021f42b2045214f04b10021f00f210e2b2045214f04b10021644f002121",
291INIT_10 => X"1f783400c5684f00004000090021f30191ff01fb008c000b210a001010000040",
292INIT_11 => X"4f21b1cf6a6c4f00214f21b1384f002100c5244f0021450040028f210021a300",
293INIT_12 => X"000d00000145210a6021160000141810e000080021fc020000200000400a4521",
294INIT_13 => X"5730020a0f06fc1c211c101418e020082110141800f500002145010000450df8",
295INIT_14 => X"fcdc0000180800100000fd008c10e80108002000494520081014181c06f8fc45",
296INIT_15 => X"6769000a6c6f74000038300032200064742020666e6584080000fb0021040000",
297INIT_16 => X"6265724d00642072724d000a7765724d000a6f4f656500303020646967206e72",
298INIT_17 => X"43000a44000a6b43000a72726d520065726d52006561204a00652072724d000a",
299INIT_18 => X"203632746d6e00006569750065696c002072003e20736400000a6c7444724b20",
300INIT_19 => X"00001010200000207060fcfcfcfcfcfcfcfcfc08fcfc6404c07c6c3c30fcd400",
301INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",
302INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",
303INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",
304INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",
305INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",
306INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",
307INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",
308INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",
309INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",
310INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",
311INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",
312INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",
313INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",
314INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",
315INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",
316INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",
317INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",
318INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",
319INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",
320INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",
321INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",
322INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",
323INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",
324INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",
325INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",
326INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",
327INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",
328INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",
329INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",
330INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",
331INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",
332INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",
333INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",
334INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",
335INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",
336INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",
337INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",
338INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000")
339   port map (
340      DO => data_read(7 downto 0),
341      DOP => open,
342      ADDR => address(12 downto 2),
343      CLK => clk,
344      DI => data_write(7 downto 0),
345      DIP => ZERO(0 downto 0),
346      EN => enable,
347      SSR => ZERO(0),
348      WE => write_byte_enable(0));
349
350end; --architecture logic
plasma/logic/ram_xilinx.vhd
1---------------------------------------------------------------------
2-- TITLE: Random Access Memory for Xilinx
3-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4-- DATE CREATED: 11/06/05
5-- FILENAME: ram_xilinx.vhd
6-- PROJECT: Plasma CPU core
7-- COPYRIGHT: Software placed into the public domain by the author.
8-- Software 'as is' without warranty. Author liable for nothing.
9-- DESCRIPTION:
10-- Implements the RAM for Spartan 3 Xilinx FPGA
11--
12-- Compile the MIPS C and assembly code into "test.axf".
13-- Run convert.exe to change "test.axf" to "code.txt" which
14-- will contain the hex values of the opcodes.
15-- Next run "ram_image ram_xilinx.vhd code.txt ram_image.vhd",
16-- to create the "ram_image.vhd" file that will have the opcodes
17-- correctly placed inside the INIT_00 => strings.
18-- Then include ram_image.vhd in the simulation/synthesis.
19---------------------------------------------------------------------
20library ieee;
21use ieee.std_logic_1164.all;
22use ieee.std_logic_misc.all;
23use ieee.std_logic_arith.all;
24use ieee.std_logic_unsigned.all;
25use work.mlite_pack.all;
26library UNISIM;
27use UNISIM.vcomponents.all;
28
29entity ram is
30   generic(memory_type : string := "DEFAULT");
31   port(clk : in std_logic;
32        enable : in std_logic;
33        write_byte_enable : in std_logic_vector(3 downto 0);
34        address : in std_logic_vector(31 downto 2);
35        data_write : in std_logic_vector(31 downto 0);
36        data_read : out std_logic_vector(31 downto 0));
37end; --entity ram
38
39architecture logic of ram is
40begin
41
42   RAMB16_S9_inst0 : RAMB16_S9
43   generic map (
44INIT_00 => X"000000000000000000000000000000000000000000000000000000000c080400",
45INIT_01 => X"0000000000000000000000000000000000000000000000000000000000000000",
46INIT_02 => X"0000000000000000000000000000000000000000000000000000000000000000",
47INIT_03 => X"0000000000000000000000000000000000000000000000000000000000000000",
48INIT_04 => X"0000000000000000000000000000000000000000000000000000000000000000",
49INIT_05 => X"0000000000000000000000000000000000000000000000000000000000000000",
50INIT_06 => X"0000000000000000000000000000000000000000000000000000000000000000",
51INIT_07 => X"0000000000000000000000000000000000000000000000000000000000000000",
52INIT_08 => X"0000000000000000000000000000000000000000000000000000000000000000",
53INIT_09 => X"0000000000000000000000000000000000000000000000000000000000000000",
54INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000",
55INIT_0B => X"0000000000000000000000000000000000000000000000000000000000000000",
56INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000",
57INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000",
58INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000",
59INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000",
60INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000",
61INIT_11 => X"0000000000000000000000000000000000000000000000000000000000000000",
62INIT_12 => X"0000000000000000000000000000000000000000000000000000000000000000",
63INIT_13 => X"0000000000000000000000000000000000000000000000000000000000000000",
64INIT_14 => X"0000000000000000000000000000000000000000000000000000000000000000",
65INIT_15 => X"0000000000000000000000000000000000000000000000000000000000000000",
66INIT_16 => X"0000000000000000000000000000000000000000000000000000000000000000",
67INIT_17 => X"0000000000000000000000000000000000000000000000000000000000000000",
68INIT_18 => X"0000000000000000000000000000000000000000000000000000000000000000",
69INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000",
70INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",
71INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",
72INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",
73INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",
74INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",
75INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",
76INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",
77INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",
78INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",
79INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",
80INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",
81INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",
82INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",
83INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",
84INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",
85INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",
86INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",
87INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",
88INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",
89INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",
90INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",
91INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",
92INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",
93INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",
94INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",
95INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",
96INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",
97INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",
98INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",
99INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",
100INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",
101INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",
102INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",
103INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",
104INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",
105INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",
106INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",
107INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000")
108   port map (
109      DO => data_read(31 downto 24),
110      DOP => open,
111      ADDR => address(12 downto 2),
112      CLK => clk,
113      DI => data_write(31 downto 24),
114      DIP => ZERO(0 downto 0),
115      EN => enable,
116      SSR => ZERO(0),
117      WE => write_byte_enable(3));
118
119   RAMB16_S9_inst1 : RAMB16_S9
120   generic map (
121INIT_00 => X"000000000000000000000000000000000000000000000000000000000d090501",
122INIT_01 => X"0000000000000000000000000000000000000000000000000000000000000000",
123INIT_02 => X"0000000000000000000000000000000000000000000000000000000000000000",
124INIT_03 => X"0000000000000000000000000000000000000000000000000000000000000000",
125INIT_04 => X"0000000000000000000000000000000000000000000000000000000000000000",
126INIT_05 => X"0000000000000000000000000000000000000000000000000000000000000000",
127INIT_06 => X"0000000000000000000000000000000000000000000000000000000000000000",
128INIT_07 => X"0000000000000000000000000000000000000000000000000000000000000000",
129INIT_08 => X"0000000000000000000000000000000000000000000000000000000000000000",
130INIT_09 => X"0000000000000000000000000000000000000000000000000000000000000000",
131INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000",
132INIT_0B => X"0000000000000000000000000000000000000000000000000000000000000000",
133INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000",
134INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000",
135INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000",
136INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000",
137INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000",
138INIT_11 => X"0000000000000000000000000000000000000000000000000000000000000000",
139INIT_12 => X"0000000000000000000000000000000000000000000000000000000000000000",
140INIT_13 => X"0000000000000000000000000000000000000000000000000000000000000000",
141INIT_14 => X"0000000000000000000000000000000000000000000000000000000000000000",
142INIT_15 => X"0000000000000000000000000000000000000000000000000000000000000000",
143INIT_16 => X"0000000000000000000000000000000000000000000000000000000000000000",
144INIT_17 => X"0000000000000000000000000000000000000000000000000000000000000000",
145INIT_18 => X"0000000000000000000000000000000000000000000000000000000000000000",
146INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000",
147INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",
148INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",
149INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",
150INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",
151INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",
152INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",
153INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",
154INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",
155INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",
156INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",
157INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",
158INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",
159INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",
160INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",
161INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",
162INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",
163INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",
164INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",
165INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",
166INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",
167INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",
168INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",
169INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",
170INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",
171INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",
172INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",
173INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",
174INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",
175INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",
176INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",
177INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",
178INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",
179INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",
180INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",
181INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",
182INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",
183INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",
184INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000")
185   port map (
186      DO => data_read(23 downto 16),
187      DOP => open,
188      ADDR => address(12 downto 2),
189      CLK => clk,
190      DI => data_write(23 downto 16),
191      DIP => ZERO(0 downto 0),
192      EN => enable,
193      SSR => ZERO(0),
194      WE => write_byte_enable(2));
195
196   RAMB16_S9_inst2 : RAMB16_S9
197   generic map (
198INIT_00 => X"000000000000000000000000000000000000000000000000000000000e0a0602",
199INIT_01 => X"0000000000000000000000000000000000000000000000000000000000000000",
200INIT_02 => X"0000000000000000000000000000000000000000000000000000000000000000",
201INIT_03 => X"0000000000000000000000000000000000000000000000000000000000000000",
202INIT_04 => X"0000000000000000000000000000000000000000000000000000000000000000",
203INIT_05 => X"0000000000000000000000000000000000000000000000000000000000000000",
204INIT_06 => X"0000000000000000000000000000000000000000000000000000000000000000",
205INIT_07 => X"0000000000000000000000000000000000000000000000000000000000000000",
206INIT_08 => X"0000000000000000000000000000000000000000000000000000000000000000",
207INIT_09 => X"0000000000000000000000000000000000000000000000000000000000000000",
208INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000",
209INIT_0B => X"0000000000000000000000000000000000000000000000000000000000000000",
210INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000",
211INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000",
212INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000",
213INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000",
214INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000",
215INIT_11 => X"0000000000000000000000000000000000000000000000000000000000000000",
216INIT_12 => X"0000000000000000000000000000000000000000000000000000000000000000",
217INIT_13 => X"0000000000000000000000000000000000000000000000000000000000000000",
218INIT_14 => X"0000000000000000000000000000000000000000000000000000000000000000",
219INIT_15 => X"0000000000000000000000000000000000000000000000000000000000000000",
220INIT_16 => X"0000000000000000000000000000000000000000000000000000000000000000",
221INIT_17 => X"0000000000000000000000000000000000000000000000000000000000000000",
222INIT_18 => X"0000000000000000000000000000000000000000000000000000000000000000",
223INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000",
224INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",
225INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",
226INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",
227INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",
228INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",
229INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",
230INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",
231INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",
232INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",
233INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",
234INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",
235INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",
236INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",
237INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",
238INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",
239INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",
240INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",
241INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",
242INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",
243INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",
244INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",
245INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",
246INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",
247INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",
248INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",
249INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",
250INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",
251INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",
252INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",
253INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",
254INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",
255INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",
256INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",
257INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",
258INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",
259INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",
260INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",
261INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000")
262   port map (
263      DO => data_read(15 downto 8),
264      DOP => open,
265      ADDR => address(12 downto 2),
266      CLK => clk,
267      DI => data_write(15 downto 8),
268      DIP => ZERO(0 downto 0),
269      EN => enable,
270      SSR => ZERO(0),
271      WE => write_byte_enable(1));
272
273   RAMB16_S9_inst3 : RAMB16_S9
274   generic map (
275INIT_00 => X"000000000000000000000000000000000000000000000000000000000f0b0703",
276INIT_01 => X"0000000000000000000000000000000000000000000000000000000000000000",
277INIT_02 => X"0000000000000000000000000000000000000000000000000000000000000000",
278INIT_03 => X"0000000000000000000000000000000000000000000000000000000000000000",
279INIT_04 => X"0000000000000000000000000000000000000000000000000000000000000000",
280INIT_05 => X"0000000000000000000000000000000000000000000000000000000000000000",
281INIT_06 => X"0000000000000000000000000000000000000000000000000000000000000000",
282INIT_07 => X"0000000000000000000000000000000000000000000000000000000000000000",
283INIT_08 => X"0000000000000000000000000000000000000000000000000000000000000000",
284INIT_09 => X"0000000000000000000000000000000000000000000000000000000000000000",
285INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000",
286INIT_0B => X"0000000000000000000000000000000000000000000000000000000000000000",
287INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000",
288INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000",
289INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000",
290INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000",
291INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000",
292INIT_11 => X"0000000000000000000000000000000000000000000000000000000000000000",
293INIT_12 => X"0000000000000000000000000000000000000000000000000000000000000000",
294INIT_13 => X"0000000000000000000000000000000000000000000000000000000000000000",
295INIT_14 => X"0000000000000000000000000000000000000000000000000000000000000000",
296INIT_15 => X"0000000000000000000000000000000000000000000000000000000000000000",
297INIT_16 => X"0000000000000000000000000000000000000000000000000000000000000000",
298INIT_17 => X"0000000000000000000000000000000000000000000000000000000000000000",
299INIT_18 => X"0000000000000000000000000000000000000000000000000000000000000000",
300INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000",
301INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",
302INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",
303INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",
304INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",
305INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",
306INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",
307INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",
308INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",
309INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",
310INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",
311INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",
312INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",
313INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",
314INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",
315INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",
316INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",
317INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",
318INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",
319INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",
320INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",
321INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",
322INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",
323INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",
324INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",
325INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",
326INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",
327INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",
328INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",
329INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",
330INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",
331INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",
332INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",
333INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",
334INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",
335INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",
336INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",
337INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",
338INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000")
339   port map (
340      DO => data_read(7 downto 0),
341      DOP => open,
342      ADDR => address(12 downto 2),
343      CLK => clk,
344      DI => data_write(7 downto 0),
345      DIP => ZERO(0 downto 0),
346      EN => enable,
347      SSR => ZERO(0),
348      WE => write_byte_enable(0));
349
350end; --architecture logic
plasma/logic/reg_bank.vhd
1---------------------------------------------------------------------
2-- TITLE: Register Bank
3-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4-- DATE CREATED: 2/2/01
5-- FILENAME: reg_bank.vhd
6-- PROJECT: Plasma CPU core
7-- COPYRIGHT: Software placed into the public domain by the author.
8-- Software 'as is' without warranty. Author liable for nothing.
9-- DESCRIPTION:
10-- Implements a register bank with 32 registers that are 32-bits wide.
11-- There are two read-ports and one write port.
12---------------------------------------------------------------------
13library ieee;
14use ieee.std_logic_1164.all;
15use ieee.std_logic_unsigned.all;
16use work.mlite_pack.all;
17--library UNISIM; --May need to uncomment for ModelSim
18--use UNISIM.vcomponents.all; --May need to uncomment for ModelSim
19
20entity reg_bank is
21   generic(memory_type : string := "XILINX_16X");
22   port(clk : in std_logic;
23        reset_in : in std_logic;
24        pause : in std_logic;
25        rs_index : in std_logic_vector(5 downto 0);
26        rt_index : in std_logic_vector(5 downto 0);
27        rd_index : in std_logic_vector(5 downto 0);
28        reg_source_out : out std_logic_vector(31 downto 0);
29        reg_target_out : out std_logic_vector(31 downto 0);
30        reg_dest_new : in std_logic_vector(31 downto 0);
31        intr_enable : out std_logic);
32end; --entity reg_bank
33
34
35--------------------------------------------------------------------
36-- The ram_block architecture attempts to use TWO dual-port memories.
37-- Different FPGAs and ASICs need different implementations.
38-- Choose one of the RAM implementations below.
39-- I need feedback on this section!
40--------------------------------------------------------------------
41architecture ram_block of reg_bank is
42   signal intr_enable_reg : std_logic;
43   type ram_type is array(31 downto 0) of std_logic_vector(31 downto 0);
44
45   --controls access to dual-port memories
46   signal addr_read1, addr_read2 : std_logic_vector(4 downto 0);
47   signal addr_write : std_logic_vector(4 downto 0);
48   signal data_out1, data_out2 : std_logic_vector(31 downto 0);
49   signal write_enable : std_logic;
50
51begin
52
53reg_proc: process(clk, rs_index, rt_index, rd_index, reg_dest_new,
54      intr_enable_reg, data_out1, data_out2, reset_in, pause)
55begin
56   --setup for first dual-port memory
57   if rs_index = "101110" then --reg_epc CP0 14
58      addr_read1 <= "00000";
59   else
60      addr_read1 <= rs_index(4 downto 0);
61   end if;
62   case rs_index is
63   when "000000" => reg_source_out <= ZERO;
64   when "101100" => reg_source_out <= ZERO(31 downto 1) & intr_enable_reg;
65                    --interrupt vector address = 0x3c
66   when "111111" => reg_source_out <= ZERO(31 downto 8) & "00111100";
67   when others => reg_source_out <= data_out1;
68   end case;
69
70   --setup for second dual-port memory
71   addr_read2 <= rt_index(4 downto 0);
72   case rt_index is
73   when "000000" => reg_target_out <= ZERO;
74   when others => reg_target_out <= data_out2;
75   end case;
76
77   --setup write port for both dual-port memories
78   if rd_index /= "000000" and rd_index /= "101100" and pause = '0' then
79      write_enable <= '1';
80   else
81      write_enable <= '0';
82   end if;
83   if rd_index = "101110" then --reg_epc CP0 14
84      addr_write <= "00000";
85   else
86      addr_write <= rd_index(4 downto 0);
87   end if;
88
89   if reset_in = '1' then
90      intr_enable_reg <= '0';
91   elsif rising_edge(clk) then
92      if rd_index = "101110" then --reg_epc CP0 14
93         intr_enable_reg <= '0'; --disable interrupts
94      elsif rd_index = "101100" then
95         intr_enable_reg <= reg_dest_new(0);
96      end if;
97   end if;
98
99   intr_enable <= intr_enable_reg;
100end process;
101
102
103--------------------------------------------------------------
104---- Pick only ONE of the dual-port RAM implementations below!
105--------------------------------------------------------------
106
107   -- Option #1
108   -- One tri-port RAM, two read-ports, one write-port
109   -- 32 registers 32-bits wide
110   tri_port_mem:
111   if memory_type = "TRI_PORT_X" generate
112      ram_proc: process(clk, addr_read1, addr_read2,
113            addr_write, reg_dest_new, write_enable)
114      variable tri_port_ram : ram_type := (others => ZERO);
115      begin
116         data_out1 <= tri_port_ram(conv_integer(addr_read1));
117         data_out2 <= tri_port_ram(conv_integer(addr_read2));
118         if rising_edge(clk) then
119            if write_enable = '1' then
120               tri_port_ram(conv_integer(addr_write)) := reg_dest_new;
121            end if;
122         end if;
123      end process;
124   end generate; --tri_port_mem
125
126
127   -- Option #2
128   -- Two dual-port RAMs, each with one read-port and one write-port
129   dual_port_mem:
130   if memory_type = "DUAL_PORT_" generate
131      ram_proc2: process(clk, addr_read1, addr_read2,
132            addr_write, reg_dest_new, write_enable)
133      variable dual_port_ram1 : ram_type := (others => ZERO);
134      variable dual_port_ram2 : ram_type := (others => ZERO);
135      begin
136         data_out1 <= dual_port_ram1(conv_integer(addr_read1));
137         data_out2 <= dual_port_ram2(conv_integer(addr_read2));
138         if rising_edge(clk) then
139            if write_enable = '1' then
140               dual_port_ram1(conv_integer(addr_write)) := reg_dest_new;
141               dual_port_ram2(conv_integer(addr_write)) := reg_dest_new;
142            end if;
143         end if;
144      end process;
145   end generate; --dual_port_mem
146
147
148   -- Option #3
149   -- RAM16X1D: 16 x 1 positive edge write, asynchronous read dual-port
150   -- distributed RAM for all Xilinx FPGAs
151   -- From library UNISIM; use UNISIM.vcomponents.all;
152   xilinx_16x1d:
153   if memory_type = "XILINX_16X" generate
154      signal data_out1A, data_out1B : std_logic_vector(31 downto 0);
155      signal data_out2A, data_out2B : std_logic_vector(31 downto 0);
156      signal weA, weB : std_logic;
157      signal no_connect : std_logic_vector(127 downto 0);
158   begin
159      weA <= write_enable and not addr_write(4); --lower 16 registers
160      weB <= write_enable and addr_write(4); --upper 16 registers
161
162      reg_loop: for i in 0 to 31 generate
163      begin
164         --Read port 1 lower 16 registers
165         reg_bit1a : RAM16X1D
166         port map (
167            WCLK => clk, -- Port A write clock input
168            WE => weA, -- Port A write enable input
169            A0 => addr_write(0), -- Port A address[0] input bit
170            A1 => addr_write(1), -- Port A address[1] input bit
171            A2 => addr_write(2), -- Port A address[2] input bit
172            A3 => addr_write(3), -- Port A address[3] input bit
173            D => reg_dest_new(i), -- Port A 1-bit data input
174            DPRA0 => addr_read1(0), -- Port B address[0] input bit
175            DPRA1 => addr_read1(1), -- Port B address[1] input bit
176            DPRA2 => addr_read1(2), -- Port B address[2] input bit
177            DPRA3 => addr_read1(3), -- Port B address[3] input bit
178            DPO => data_out1A(i), -- Port B 1-bit data output
179            SPO => no_connect(i) -- Port A 1-bit data output
180         );
181         --Read port 1 upper 16 registers
182         reg_bit1b : RAM16X1D
183         port map (
184            WCLK => clk, -- Port A write clock input
185            WE => weB, -- Port A write enable input
186            A0 => addr_write(0), -- Port A address[0] input bit
187            A1 => addr_write(1), -- Port A address[1] input bit
188            A2 => addr_write(2), -- Port A address[2] input bit
189            A3 => addr_write(3), -- Port A address[3] input bit
190            D => reg_dest_new(i), -- Port A 1-bit data input
191            DPRA0 => addr_read1(0), -- Port B address[0] input bit
192            DPRA1 => addr_read1(1), -- Port B address[1] input bit
193            DPRA2 => addr_read1(2), -- Port B address[2] input bit
194            DPRA3 => addr_read1(3), -- Port B address[3] input bit
195            DPO => data_out1B(i), -- Port B 1-bit data output
196            SPO => no_connect(32+i) -- Port A 1-bit data output
197         );
198         --Read port 2 lower 16 registers
199         reg_bit2a : RAM16X1D
200         port map (
201            WCLK => clk, -- Port A write clock input
202            WE => weA, -- Port A write enable input
203            A0 => addr_write(0), -- Port A address[0] input bit
204            A1 => addr_write(1), -- Port A address[1] input bit
205            A2 => addr_write(2), -- Port A address[2] input bit
206            A3 => addr_write(3), -- Port A address[3] input bit
207            D => reg_dest_new(i), -- Port A 1-bit data input
208            DPRA0 => addr_read2(0), -- Port B address[0] input bit
209            DPRA1 => addr_read2(1), -- Port B address[1] input bit
210            DPRA2 => addr_read2(2), -- Port B address[2] input bit
211            DPRA3 => addr_read2(3), -- Port B address[3] input bit
212            DPO => data_out2A(i), -- Port B 1-bit data output
213            SPO => no_connect(64+i) -- Port A 1-bit data output
214         );
215         --Read port 2 upper 16 registers
216         reg_bit2b : RAM16X1D
217         port map (
218            WCLK => clk, -- Port A write clock input
219            WE => weB, -- Port A write enable input
220            A0 => addr_write(0), -- Port A address[0] input bit
221            A1 => addr_write(1), -- Port A address[1] input bit
222            A2 => addr_write(2), -- Port A address[2] input bit
223            A3 => addr_write(3), -- Port A address[3] input bit
224            D => reg_dest_new(i), -- Port A 1-bit data input
225            DPRA0 => addr_read2(0), -- Port B address[0] input bit
226            DPRA1 => addr_read2(1), -- Port B address[1] input bit
227            DPRA2 => addr_read2(2), -- Port B address[2] input bit
228            DPRA3 => addr_read2(3), -- Port B address[3] input bit
229            DPO => data_out2B(i), -- Port B 1-bit data output
230            SPO => no_connect(96+i) -- Port A 1-bit data output
231         );
232      end generate; --reg_loop
233
234      data_out1 <= data_out1A when addr_read1(4)='0' else data_out1B;
235      data_out2 <= data_out2A when addr_read2(4)='0' else data_out2B;
236   end generate; --xilinx_16x1d
237
238
239   -- Option #4
240   -- Altera LPM_RAM_DP
241   altera_mem:
242   if memory_type = "ALTERA_LPM" generate
243      signal clk_delayed : std_logic;
244      signal addr_reg : std_logic_vector(4 downto 0);
245      signal data_reg : std_logic_vector(31 downto 0);
246      signal q1 : std_logic_vector(31 downto 0);
247      signal q2 : std_logic_vector(31 downto 0);
248   begin
249      -- Altera dual port RAMs must have the addresses registered (sampled
250      -- at the rising edge). This is very unfortunate.
251      -- Therefore, the dual port RAM read clock must delayed so that
252      -- the read address signal can be sent from the mem_ctrl block.
253      -- This solution also delays the how fast the registers are read so the
254      -- maximum clock speed is cut in half (12.5 MHz instead of 25 MHz).
255
256      clk_delayed <= not clk; --Could be delayed by 1/4 clock cycle instead
257      dpram_bypass: process(clk, addr_write, reg_dest_new)
258      begin
259         if rising_edge(clk) and write_enable = '1' then
260            addr_reg <= addr_write;
261            data_reg <= reg_dest_new;
262         end if;
263      end process; --dpram_bypass
264
265      -- Bypass dpram if reading what was just written (Altera limitation)
266      data_out1 <= q1 when addr_read1 /= addr_reg else data_reg;
267      data_out2 <= q2 when addr_read2 /= addr_reg else data_reg;
268
269      lpm_ram_dp_component1 : lpm_ram_dp
270      generic map (
271         LPM_WIDTH => 32,
272         LPM_WIDTHAD => 5,
273         --LPM_NUMWORDS => 0,
274         LPM_INDATA => "REGISTERED",
275         LPM_OUTDATA => "UNREGISTERED",
276         LPM_RDADDRESS_CONTROL => "REGISTERED",
277         LPM_WRADDRESS_CONTROL => "REGISTERED",
278         LPM_FILE => "UNUSED",
279         LPM_TYPE => "LPM_RAM_DP",
280         USE_EAB => "ON",
281         INTENDED_DEVICE_FAMILY => "UNUSED",
282         RDEN_USED => "FALSE",
283         LPM_HINT => "UNUSED")
284      port map (
285         RDCLOCK => clk_delayed,
286         RDCLKEN => '1',
287         RDADDRESS => addr_read1,
288         RDEN => '1',
289         DATA => reg_dest_new,
290         WRADDRESS => addr_write,
291         WREN => write_enable,
292         WRCLOCK => clk,
293         WRCLKEN => '1',
294         Q => q1);
295      lpm_ram_dp_component2 : lpm_ram_dp
296      generic map (
297         LPM_WIDTH => 32,
298         LPM_WIDTHAD => 5,
299         --LPM_NUMWORDS => 0,
300         LPM_INDATA => "REGISTERED",
301         LPM_OUTDATA => "UNREGISTERED",
302         LPM_RDADDRESS_CONTROL => "REGISTERED",
303         LPM_WRADDRESS_CONTROL => "REGISTERED",
304         LPM_FILE => "UNUSED",
305         LPM_TYPE => "LPM_RAM_DP",
306         USE_EAB => "ON",
307         INTENDED_DEVICE_FAMILY => "UNUSED",
308         RDEN_USED => "FALSE",
309         LPM_HINT => "UNUSED")
310      port map (
311         RDCLOCK => clk_delayed,
312         RDCLKEN => '1',
313         RDADDRESS => addr_read2,
314         RDEN => '1',
315         DATA => reg_dest_new,
316         WRADDRESS => addr_write,
317         WREN => write_enable,
318         WRCLOCK => clk,
319         WRCLKEN => '1',
320         Q => q2);
321   end generate; --altera_mem
322
323end; --architecture ram_block
plasma/logic/shifter.vhd
1---------------------------------------------------------------------
2-- TITLE: Shifter Unit
3-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4-- Matthias Gruenewald
5-- DATE CREATED: 2/2/01
6-- FILENAME: shifter.vhd
7-- PROJECT: Plasma CPU core
8-- COPYRIGHT: Software placed into the public domain by the author.
9-- Software 'as is' without warranty. Author liable for nothing.
10-- DESCRIPTION:
11-- Implements the 32-bit shifter unit.
12---------------------------------------------------------------------
13library ieee;
14use ieee.std_logic_1164.all;
15use work.mlite_pack.all;
16
17entity shifter is
18   generic(shifter_type : string := "DEFAULT");
19   port(value : in std_logic_vector(31 downto 0);
20        shift_amount : in std_logic_vector(4 downto 0);
21        shift_func : in shift_function_type;
22        c_shift : out std_logic_vector(31 downto 0));
23end; --entity shifter
24
25architecture logic of shifter is
26-- type shift_function_type is (
27-- shift_nothing, shift_left_unsigned,
28-- shift_right_signed, shift_right_unsigned);
29
30signal shift1L, shift2L, shift4L, shift8L, shift16L : std_logic_vector(31 downto 0);
31signal shift1R, shift2R, shift4R, shift8R, shift16R : std_logic_vector(31 downto 0);
32signal fills : std_logic_vector(31 downto 16);
33
34begin
35   fills <= "1111111111111111" when shift_func = SHIFT_RIGHT_SIGNED
36                                and value(31) = '1'
37                                         else "0000000000000000";
38   shift1L <= value(30 downto 0) & '0' when shift_amount(0) = '1' else value;
39   shift2L <= shift1L(29 downto 0) & "00" when shift_amount(1) = '1' else shift1L;
40   shift4L <= shift2L(27 downto 0) & "0000" when shift_amount(2) = '1' else shift2L;
41   shift8L <= shift4L(23 downto 0) & "00000000" when shift_amount(3) = '1' else shift4L;
42   shift16L <= shift8L(15 downto 0) & ZERO(15 downto 0) when shift_amount(4) = '1' else shift8L;
43
44   shift1R <= fills(31) & value(31 downto 1) when shift_amount(0) = '1' else value;
45   shift2R <= fills(31 downto 30) & shift1R(31 downto 2) when shift_amount(1) = '1' else shift1R;
46   shift4R <= fills(31 downto 28) & shift2R(31 downto 4) when shift_amount(2) = '1' else shift2R;
47   shift8R <= fills(31 downto 24) & shift4R(31 downto 8) when shift_amount(3) = '1' else shift4R;
48   shift16R <= fills(31 downto 16) & shift8R(31 downto 16) when shift_amount(4) = '1' else shift8R;
49
50GENERIC_SHIFTER: if shifter_type = "DEFAULT" generate
51   c_shift <= shift16L when shift_func = SHIFT_LEFT_UNSIGNED else
52              shift16R when shift_func = SHIFT_RIGHT_UNSIGNED or
53                                shift_func = SHIFT_RIGHT_SIGNED else
54              ZERO;
55end generate;
56
57AREA_OPTIMIZED_SHIFTER: if shifter_type /= "DEFAULT" generate
58   c_shift <= shift16L when shift_func = SHIFT_LEFT_UNSIGNED else (others => 'Z');
59   c_shift <= shift16R when shift_func = SHIFT_RIGHT_UNSIGNED or
60                            shift_func = SHIFT_RIGHT_SIGNED else (others => 'Z');
61   c_shift <= ZERO when shift_func = SHIFT_NOTHING else (others => 'Z');
62end generate;
63
64end; --architecture logic
65
plasma/logic/simulation/output.txt
1
2Greetings from the bootloader Apr 21 2010 19:05:48:
3
4Waiting for binary image linked at 0x10000000
5Other Menu Options:
61. Memory read word
72. Memory write word
83. Memory read byte
94. Memory write byte
105. Jump to address
116. Raw memory read
127. Raw memory write
138. Checksum
149. Dump
15F. Copy 128KB from DDR to flash
16>
17Waiting for binary image linked at 0x10000000
18Other Menu Options:
191. Memory read word
202. Memory write word
213. Memory read byte
224. Memory write byte
235. Jump to address
246. Raw memory read
257. Raw memory write
268. Checksum
279. Dump
28F. Copy 128KB from DDR to flash
29> 4
plasma/logic/simulation/plasma_3e_TB.do
1vlib work
2vmap work
3vcom -93 -work work ../mlite_pack.vhd
4vcom -93 -work work ../plasma.vhd
5vcom -93 -work work ../alu.vhd
6vcom -93 -work work ../control.vhd
7vcom -93 -work work ../mem_ctrl.vhd
8vcom -93 -work work ../mult.vhd
9vcom -93 -work work ../shifter.vhd
10vcom -93 -work work ../bus_mux.vhd
11vcom -93 -work work ../ddr_ctrl.vhd
12vcom -93 -work work ../mlite_cpu.vhd
13vcom -93 -work work ../pc_next.vhd
14vcom -93 -work work ../cache.vhd
15vcom -93 -work work ../eth_dma.vhd
16vcom -93 -work work ../pipeline.vhd
17vcom -93 -work work ../reg_bank.vhd
18vcom -93 -work work ../uart.vhd
19vcom -93 -work work ../plasma_3e.vhd
20vcom -93 -work work ../ram_image.vhd
21vcom -93 -work work ../tbench.vhd
22
23vsim -t 1ps tbench
24view wave
25add wave *
26
27view structure
28view signals
29run 15ms
plasma/logic/simulation/transcript
1# // ModelSim SE 6.0d Apr 25 2005 Linux 2.6.32-21-generic
2# //
3# // Copyright Mentor Graphics Corporation 2005
4# // All Rights Reserved.
5# //
6# // THIS WORK CONTAINS TRADE SECRET AND
7# // PROPRIETARY INFORMATION WHICH IS THE PROPERTY
8# // OF MENTOR GRAPHICS CORPORATION OR ITS LICENSORS
9# // AND IS SUBJECT TO LICENSE TERMS.
10# //
11# do plasma_3e_TB.do
12# Reading /home/opt/cad/modeltech/linux/../modelsim.ini
13# "work" maps to directory work. (Default mapping)
14# Model Technology ModelSim SE vcom 6.0d Compiler 2005.04 Apr 25 2005
15# -- Loading package standard
16# -- Loading package std_logic_1164
17# -- Compiling package mlite_pack
18# -- Compiling package body mlite_pack
19# -- Loading package mlite_pack
20# Model Technology ModelSim SE vcom 6.0d Compiler 2005.04 Apr 25 2005
21# -- Loading package standard
22# -- Loading package std_logic_1164
23# -- Loading package mlite_pack
24# -- Compiling entity plasma
25# -- Compiling architecture logic of plasma
26# Model Technology ModelSim SE vcom 6.0d Compiler 2005.04 Apr 25 2005
27# -- Loading package standard
28# -- Loading package std_logic_1164
29# -- Loading package mlite_pack
30# -- Compiling entity alu
31# -- Compiling architecture logic of alu
32# Model Technology ModelSim SE vcom 6.0d Compiler 2005.04 Apr 25 2005
33# -- Loading package standard
34# -- Loading package std_logic_1164
35# -- Loading package mlite_pack
36# -- Compiling entity control
37# -- Compiling architecture logic of control
38# Model Technology ModelSim SE vcom 6.0d Compiler 2005.04 Apr 25 2005
39# -- Loading package standard
40# -- Loading package std_logic_1164
41# -- Loading package mlite_pack
42# -- Compiling entity mem_ctrl
43# -- Compiling architecture logic of mem_ctrl
44# Model Technology ModelSim SE vcom 6.0d Compiler 2005.04 Apr 25 2005
45# -- Loading package standard
46# -- Loading package std_logic_1164
47# -- Loading package std_logic_arith
48# -- Loading package std_logic_unsigned
49# -- Loading package mlite_pack
50# -- Compiling entity mult
51# -- Compiling architecture logic of mult
52# Model Technology ModelSim SE vcom 6.0d Compiler 2005.04 Apr 25 2005
53# -- Loading package standard
54# -- Loading package std_logic_1164
55# -- Loading package mlite_pack
56# -- Compiling entity shifter
57# -- Compiling architecture logic of shifter
58# Model Technology ModelSim SE vcom 6.0d Compiler 2005.04 Apr 25 2005
59# -- Loading package standard
60# -- Loading package std_logic_1164
61# -- Loading package mlite_pack
62# -- Compiling entity bus_mux
63# -- Compiling architecture logic of bus_mux
64# Model Technology ModelSim SE vcom 6.0d Compiler 2005.04 Apr 25 2005
65# -- Loading package standard
66# -- Loading package std_logic_1164
67# -- Loading package std_logic_arith
68# -- Loading package std_logic_unsigned
69# -- Loading package mlite_pack
70# -- Compiling entity ddr_ctrl
71# -- Compiling architecture logic of ddr_ctrl
72# Model Technology ModelSim SE vcom 6.0d Compiler 2005.04 Apr 25 2005
73# -- Loading package standard
74# -- Loading package std_logic_1164
75# -- Loading package mlite_pack
76# -- Loading package std_logic_arith
77# -- Loading package std_logic_unsigned
78# -- Compiling entity mlite_cpu
79# -- Compiling architecture logic of mlite_cpu
80# Model Technology ModelSim SE vcom 6.0d Compiler 2005.04 Apr 25 2005
81# -- Loading package standard
82# -- Loading package std_logic_1164
83# -- Loading package mlite_pack
84# -- Compiling entity pc_next
85# -- Compiling architecture logic of pc_next
86# Model Technology ModelSim SE vcom 6.0d Compiler 2005.04 Apr 25 2005
87# -- Loading package standard
88# -- Loading package std_logic_1164
89# -- Loading package std_logic_arith
90# -- Loading package std_logic_unsigned
91# -- Loading package vcomponents
92# -- Loading package mlite_pack
93# -- Compiling entity cache
94# -- Compiling architecture logic of cache
95# Model Technology ModelSim SE vcom 6.0d Compiler 2005.04 Apr 25 2005
96# -- Loading package standard
97# -- Loading package std_logic_1164
98# -- Loading package std_logic_arith
99# -- Loading package std_logic_unsigned
100# -- Loading package mlite_pack
101# -- Compiling entity eth_dma
102# -- Compiling architecture logic of eth_dma
103# Model Technology ModelSim SE vcom 6.0d Compiler 2005.04 Apr 25 2005
104# -- Loading package standard
105# -- Loading package std_logic_1164
106# -- Loading package mlite_pack
107# -- Compiling entity pipeline
108# -- Compiling architecture logic of pipeline
109# Model Technology ModelSim SE vcom 6.0d Compiler 2005.04 Apr 25 2005
110# -- Loading package standard
111# -- Loading package std_logic_1164
112# -- Loading package std_logic_arith
113# -- Loading package std_logic_unsigned
114# -- Loading package mlite_pack
115# -- Compiling entity reg_bank
116# -- Compiling architecture ram_block of reg_bank
117# Model Technology ModelSim SE vcom 6.0d Compiler 2005.04 Apr 25 2005
118# -- Loading package standard
119# -- Loading package std_logic_1164
120# -- Loading package attributes
121# -- Loading package std_logic_misc
122# -- Loading package std_logic_arith
123# -- Loading package textio
124# -- Loading package std_logic_textio
125# -- Loading package std_logic_unsigned
126# -- Loading package mlite_pack
127# -- Compiling entity uart
128# -- Compiling architecture logic of uart
129# Model Technology ModelSim SE vcom 6.0d Compiler 2005.04 Apr 25 2005
130# -- Loading package standard
131# -- Loading package std_logic_1164
132# -- Loading package std_logic_arith
133# -- Loading package std_logic_unsigned
134# -- Compiling entity plasma_3e
135# -- Compiling architecture logic of plasma_3e
136# Model Technology ModelSim SE vcom 6.0d Compiler 2005.04 Apr 25 2005
137# -- Loading package standard
138# -- Loading package std_logic_1164
139# -- Loading package attributes
140# -- Loading package std_logic_misc
141# -- Loading package std_logic_arith
142# -- Loading package std_logic_unsigned
143# -- Loading package mlite_pack
144# -- Loading package vcomponents
145# -- Compiling entity ram
146# -- Compiling architecture logic of ram
147# Model Technology ModelSim SE vcom 6.0d Compiler 2005.04 Apr 25 2005
148# -- Loading package standard
149# -- Loading package std_logic_1164
150# -- Loading package mlite_pack
151# -- Loading package std_logic_arith
152# -- Loading package std_logic_unsigned
153# -- Compiling entity tbench
154# -- Compiling architecture logic of tbench
155# vsim -t 1ps tbench
156# Loading /home/opt/cad/modeltech/linux/../std.standard
157# Loading /home/opt/cad/modeltech/linux/../ieee.std_logic_1164(body)
158# Loading work.mlite_pack(body)
159# Loading /home/opt/cad/modeltech/linux/../ieee.std_logic_arith(body)
160# Loading /home/opt/cad/modeltech/linux/../ieee.std_logic_unsigned(body)
161# Loading work.tbench(logic)
162# Loading work.plasma(logic)
163# Loading work.mlite_cpu(logic)
164# Loading work.pc_next(logic)
165# Loading work.mem_ctrl(logic)
166# Loading work.control(logic)
167# Loading work.reg_bank(ram_block)
168# Loading work.bus_mux(logic)
169# Loading work.alu(logic)
170# Loading work.shifter(logic)
171# Loading work.mult(logic)
172# Loading /opt/cad/modeltech/xilinx/vhdl/unisim.vcomponents
173# Loading work.cache(logic)
174# Loading /home/opt/cad/modeltech/linux/../synopsys.attributes
175# Loading /home/opt/cad/modeltech/linux/../ieee.std_logic_misc(body)
176# Loading work.ram(logic)
177# Loading /home/opt/cad/modeltech/linux/../std.textio(body)
178# Loading /home/opt/cad/modeltech/linux/../ieee.vital_timing(body)
179# Loading /home/opt/cad/modeltech/linux/../ieee.vital_primitives(body)
180# Loading /opt/cad/modeltech/xilinx/vhdl/unisim.vpkg(body)
181# Loading /opt/cad/modeltech/xilinx/vhdl/unisim.ramb16_s9(ramb16_s9_v)
182# Loading /home/opt/cad/modeltech/linux/../ieee.std_logic_textio(body)
183# Loading work.uart(logic)
184# Loading work.eth_dma(logic)
185# .main_pane.mdi.interior.cs.vm.paneset.cli_0.wf.clip.cs
186# .main_pane.workspace
187# .main_pane.signals.interior.cs
188# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
189# Time: 0 ps Iteration: 0 Instance: /tbench
190# ** Warning: CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, and it has been converted to 0.
191# Time: 0 ps Iteration: 0 Instance: /tbench
192# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
193# Time: 0 ps Iteration: 0 Instance: /tbench/u1_plasma/dma_gen2/u4_eth
194# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
195# Time: 0 ps Iteration: 0 Instance: /tbench/u1_plasma/dma_gen2/u4_eth
196# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
197# Time: 0 ps Iteration: 0 Instance: /tbench/u1_plasma/u3_uart
198# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
199# Time: 0 ps Iteration: 0 Instance: /tbench/u1_plasma/opt_cache2/u_cache
200# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
201# Time: 0 ps Iteration: 0 Instance: /tbench/u1_plasma/opt_cache2/u_cache
202# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
203# Time: 0 ps Iteration: 0 Instance: /tbench/u1_plasma/opt_cache2/u_cache
204# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
205# Time: 0 ps Iteration: 0 Instance: /tbench/u1_plasma/u1_cpu/u8_mult
206# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
207# Time: 0 ps Iteration: 0 Instance: /tbench/u1_plasma/u1_cpu/u8_mult
208# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
209# Time: 0 ps Iteration: 0 Instance: /tbench/u1_plasma/u1_cpu/u8_mult
210# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
211# Time: 0 ps Iteration: 0 Instance: /tbench/u1_plasma/u1_cpu/u8_mult
212# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
213# Time: 0 ps Iteration: 0 Instance: /tbench/u1_plasma/u1_cpu/u8_mult
214# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
215# Time: 0 ps Iteration: 0 Instance: /tbench/u1_plasma/u1_cpu/u8_mult
216# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
217# Time: 0 ps Iteration: 0 Instance: /tbench/u1_plasma/u1_cpu/u4_reg_bank/tri_port_mem
218# ** Warning: CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, and it has been converted to 0.
219# Time: 0 ps Iteration: 0 Instance: /tbench/u1_plasma/u1_cpu/u4_reg_bank/tri_port_mem
220# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
221# Time: 0 ps Iteration: 0 Instance: /tbench/u1_plasma/u1_cpu/u4_reg_bank/tri_port_mem
222# ** Warning: CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, and it has been converted to 0.
223# Time: 0 ps Iteration: 0 Instance: /tbench/u1_plasma/u1_cpu/u4_reg_bank/tri_port_mem
224# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
225# Time: 0 ps Iteration: 0 Instance: /tbench/u1_plasma/u1_cpu/u4_reg_bank
226# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
227# Time: 0 ps Iteration: 0 Instance: /tbench/u1_plasma/u1_cpu/u4_reg_bank
228# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
229# Time: 0 ps Iteration: 0 Instance: /tbench/u1_plasma/u1_cpu/u4_reg_bank
230# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
231# Time: 0 ps Iteration: 0 Instance: /tbench/u1_plasma/u1_cpu/u4_reg_bank
232# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
233# Time: 0 ps Iteration: 0 Instance: /tbench/u1_plasma/u1_cpu
234# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
235# Time: 0 ps Iteration: 1 Instance: /tbench/u1_plasma/u1_cpu/u4_reg_bank/tri_port_mem
236# ** Warning: CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, and it has been converted to 0.
237# Time: 0 ps Iteration: 1 Instance: /tbench/u1_plasma/u1_cpu/u4_reg_bank/tri_port_mem
238# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
239# Time: 0 ps Iteration: 1 Instance: /tbench/u1_plasma/u1_cpu/u4_reg_bank/tri_port_mem
240# ** Warning: CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, and it has been converted to 0.
241# Time: 0 ps Iteration: 1 Instance: /tbench/u1_plasma/u1_cpu/u4_reg_bank/tri_port_mem
242# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
243# Time: 0 ps Iteration: 1 Instance: /tbench/u1_plasma/opt_cache2/u_cache
244# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
245# Time: 0 ps Iteration: 1 Instance: /tbench/u1_plasma/u1_cpu/u4_reg_bank
246# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
247# Time: 0 ps Iteration: 1 Instance: /tbench/u1_plasma/u1_cpu/u4_reg_bank
248# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
249# Time: 0 ps Iteration: 1 Instance: /tbench/u1_plasma/u1_cpu/u4_reg_bank
250# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
251# Time: 0 ps Iteration: 1 Instance: /tbench/u1_plasma/u1_cpu/u4_reg_bank
252# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
253# Time: 0 ps Iteration: 1 Instance: /tbench
254# ** Warning: CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, and it has been converted to 0.
255# Time: 0 ps Iteration: 1 Instance: /tbench
256# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
257# Time: 0 ps Iteration: 2 Instance: /tbench/u1_plasma/u1_cpu/u4_reg_bank
258# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
259# Time: 0 ps Iteration: 2 Instance: /tbench
260# ** Warning: CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, and it has been converted to 0.
261# Time: 0 ps Iteration: 2 Instance: /tbench
262# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
263# Time: 0 ps Iteration: 2 Instance: /tbench/u1_plasma/opt_cache2/u_cache
264# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
265# Time: 0 ps Iteration: 3 Instance: /tbench/u1_plasma/u1_cpu/u4_reg_bank/tri_port_mem
266# ** Warning: CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, and it has been converted to 0.
267# Time: 0 ps Iteration: 3 Instance: /tbench/u1_plasma/u1_cpu/u4_reg_bank/tri_port_mem
268# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
269# Time: 0 ps Iteration: 3 Instance: /tbench/u1_plasma/u1_cpu/u4_reg_bank/tri_port_mem
270# ** Warning: CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, and it has been converted to 0.
271# Time: 0 ps Iteration: 3 Instance: /tbench/u1_plasma/u1_cpu/u4_reg_bank/tri_port_mem
272# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
273# Time: 0 ps Iteration: 3 Instance: /tbench/u1_plasma/opt_cache2/u_cache
274# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
275# Time: 0 ps Iteration: 4 Instance: /tbench/u1_plasma/u1_cpu/u4_reg_bank/tri_port_mem
276# ** Warning: CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, and it has been converted to 0.
277# Time: 0 ps Iteration: 4 Instance: /tbench/u1_plasma/u1_cpu/u4_reg_bank/tri_port_mem
278# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
279# Time: 0 ps Iteration: 4 Instance: /tbench/u1_plasma/u1_cpu/u4_reg_bank/tri_port_mem
280# ** Warning: CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, and it has been converted to 0.
281# Time: 0 ps Iteration: 4 Instance: /tbench/u1_plasma/u1_cpu/u4_reg_bank/tri_port_mem
282# Break key hit
283# Simulation stop requested.
plasma/logic/tbench.vhd
1---------------------------------------------------------------------
2-- TITLE: Test Bench
3-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4-- DATE CREATED: 4/21/01
5-- FILENAME: tbench.vhd
6-- PROJECT: Plasma CPU core
7-- COPYRIGHT: Software placed into the public domain by the author.
8-- Software 'as is' without warranty. Author liable for nothing.
9-- DESCRIPTION:
10-- This entity provides a test bench for testing the Plasma CPU core.
11---------------------------------------------------------------------
12library ieee;
13use ieee.std_logic_1164.all;
14use work.mlite_pack.all;
15use ieee.std_logic_unsigned.all;
16
17entity tbench is
18end; --entity tbench
19
20architecture logic of tbench is
21   constant memory_type : string :=
22   "TRI_PORT_X";
23-- "DUAL_PORT_";
24-- "ALTERA_LPM";
25-- "XILINX_16X";
26
27   constant log_file : string :=
28-- "UNUSED";
29   "output.txt";
30
31   signal clk : std_logic := '1';
32   signal reset : std_logic := '1';
33   signal interrupt : std_logic := '0';
34   signal mem_write : std_logic;
35   signal address : std_logic_vector(31 downto 2);
36   signal data_write : std_logic_vector(31 downto 0);
37   signal data_read : std_logic_vector(31 downto 0);
38   signal pause1 : std_logic := '0';
39   signal pause2 : std_logic := '0';
40   signal pause : std_logic;
41   signal no_ddr_start: std_logic;
42   signal no_ddr_stop : std_logic;
43   signal byte_we : std_logic_vector(3 downto 0);
44   signal uart_write : std_logic;
45   signal gpioA_in : std_logic_vector(31 downto 0) := (others => '0');
46begin --architecture
47   --Uncomment the line below to test interrupts
48   interrupt <= '1' after 20 us when interrupt = '0' else '0' after 445 ns;
49
50   clk <= not clk after 50 ns;
51   reset <= '0' after 500 ns;
52   pause1 <= '1' after 700 ns when pause1 = '0' else '0' after 200 ns;
53   pause2 <= '1' after 300 ns when pause2 = '0' else '0' after 200 ns;
54   pause <= pause1 or pause2;
55   gpioA_in(20) <= not gpioA_in(20) after 200 ns; --E_RX_CLK
56   gpioA_in(19) <= not gpioA_in(19) after 20 us; --E_RX_DV
57   gpioA_in(18 downto 15) <= gpioA_in(18 downto 15) + 1 after 400 ns; --E_RX_RXD
58   gpioA_in(14) <= not gpioA_in(14) after 200 ns; --E_TX_CLK
59
60   u1_plasma: plasma
61      generic map (memory_type => memory_type,
62                   ethernet => '1',
63                   use_cache => '1',
64                   log_file => log_file)
65      PORT MAP (
66         clk => clk,
67         reset => reset,
68         uart_read => uart_write,
69         uart_write => uart_write,
70
71         address => address,
72         byte_we => byte_we,
73         data_write => data_write,
74         data_read => data_read,
75         mem_pause_in => pause,
76         no_ddr_start => no_ddr_start,
77         no_ddr_stop => no_ddr_stop,
78
79         gpio0_out => open,
80         gpioA_in => gpioA_in);
81
82   dram_proc: process(clk, address, byte_we, data_write, pause)
83      constant ADDRESS_WIDTH : natural := 16;
84      type storage_array is
85         array(natural range 0 to (2 ** ADDRESS_WIDTH) / 4 - 1) of
86         std_logic_vector(31 downto 0);
87      variable storage : storage_array;
88      variable data : std_logic_vector(31 downto 0);
89      variable index : natural := 0;
90   begin
91      index := conv_integer(address(ADDRESS_WIDTH-1 downto 2));
92      data := storage(index);
93
94      if byte_we(0) = '1' then
95         data(7 downto 0) := data_write(7 downto 0);
96      end if;
97      if byte_we(1) = '1' then
98         data(15 downto 8) := data_write(15 downto 8);
99      end if;
100      if byte_we(2) = '1' then
101         data(23 downto 16) := data_write(23 downto 16);
102      end if;
103      if byte_we(3) = '1' then
104         data(31 downto 24) := data_write(31 downto 24);
105      end if;
106
107      if rising_edge(clk) then
108         if address(30 downto 28) = "001" and byte_we /= "0000" then
109            storage(index) := data;
110         end if;
111      end if;
112
113      if pause = '0' then
114         data_read <= data;
115      end if;
116   end process;
117
118
119end; --architecture logic
plasma/logic/uart.vhd
1---------------------------------------------------------------------
2-- TITLE: UART
3-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4-- DATE CREATED: 5/29/02
5-- FILENAME: uart.vhd
6-- PROJECT: Plasma CPU core
7-- COPYRIGHT: Software placed into the public domain by the author.
8-- Software 'as is' without warranty. Author liable for nothing.
9-- DESCRIPTION:
10-- Implements the UART.
11---------------------------------------------------------------------
12library ieee;
13use ieee.std_logic_1164.all;
14use ieee.std_logic_misc.all;
15use ieee.std_logic_arith.all;
16use ieee.std_logic_textio.all;
17use ieee.std_logic_unsigned.all;
18use std.textio.all;
19use work.mlite_pack.all;
20
21entity uart is
22   generic(log_file : string := "UNUSED");
23   port(clk : in std_logic;
24        reset : in std_logic;
25        enable_read : in std_logic;
26        enable_write : in std_logic;
27        data_in : in std_logic_vector(7 downto 0);
28        data_out : out std_logic_vector(7 downto 0);
29        uart_read : in std_logic;
30        uart_write : out std_logic;
31        busy_write : out std_logic;
32        data_avail : out std_logic);
33end; --entity uart
34
35architecture logic of uart is
36   signal delay_write_reg : std_logic_vector(9 downto 0);
37   signal bits_write_reg : std_logic_vector(3 downto 0);
38   signal data_write_reg : std_logic_vector(8 downto 0);
39   signal delay_read_reg : std_logic_vector(9 downto 0);
40   signal bits_read_reg : std_logic_vector(3 downto 0);
41   signal data_read_reg : std_logic_vector(7 downto 0);
42   signal data_save_reg : std_logic_vector(17 downto 0);
43   signal busy_write_sig : std_logic;
44   signal read_value_reg : std_logic_vector(6 downto 0);
45   signal uart_read2 : std_logic;
46
47begin
48
49uart_proc: process(clk, reset, enable_read, enable_write, data_in,
50                   data_write_reg, bits_write_reg, delay_write_reg,
51                   data_read_reg, bits_read_reg, delay_read_reg,
52                   data_save_reg, read_value_reg, uart_read2,
53                   busy_write_sig, uart_read)
54   constant COUNT_VALUE : std_logic_vector(9 downto 0) :=
55-- "0100011110"; --33MHz/2/57600Hz = 0x11e
56-- "1101100100"; --50MHz/57600Hz = 0x364
57      "0110110010"; --25MHz/57600Hz = 0x1b2 -- Plasma IF uses div2
58-- "0011011001"; --12.5MHz/57600Hz = 0xd9
59-- "0000000100"; --for debug (shorten read_value_reg)
60begin
61   uart_read2 <= read_value_reg(read_value_reg'length - 1);
62
63   if reset = '1' then
64      data_write_reg <= ZERO(8 downto 1) & '1';
65      bits_write_reg <= "0000";
66      delay_write_reg <= ZERO(9 downto 0);
67      read_value_reg <= ONES(read_value_reg'length-1 downto 0);
68      data_read_reg <= ZERO(7 downto 0);
69      bits_read_reg <= "0000";
70      delay_read_reg <= ZERO(9 downto 0);
71      data_save_reg <= ZERO(17 downto 0);
72   elsif rising_edge(clk) then
73
74      --Write UART
75      if bits_write_reg = "0000" then --nothing left to write?
76         if enable_write = '1' then
77            delay_write_reg <= ZERO(9 downto 0); --delay before next bit
78            bits_write_reg <= "1010"; --number of bits to write
79            data_write_reg <= data_in & '0'; --remember data & start bit
80         end if;
81      else
82         if delay_write_reg /= COUNT_VALUE then
83            delay_write_reg <= delay_write_reg + 1; --delay before next bit
84         else
85            delay_write_reg <= ZERO(9 downto 0); --reset delay
86            bits_write_reg <= bits_write_reg - 1; --bits left to write
87            data_write_reg <= '1' & data_write_reg(8 downto 1);
88         end if;
89      end if;
90
91      --Average uart_read signal
92      if uart_read = '1' then
93         if read_value_reg /= ONES(read_value_reg'length - 1 downto 0) then
94            read_value_reg <= read_value_reg + 1;
95         end if;
96      else
97         if read_value_reg /= ZERO(read_value_reg'length - 1 downto 0) then
98            read_value_reg <= read_value_reg - 1;
99         end if;
100      end if;
101
102      --Read UART
103      if delay_read_reg = ZERO(9 downto 0) then --done delay for read?
104         if bits_read_reg = "0000" then --nothing left to read?
105            if uart_read2 = '0' then --wait for start bit
106               delay_read_reg <= '0' & COUNT_VALUE(9 downto 1); --half period
107               bits_read_reg <= "1001"; --bits left to read
108            end if;
109         else
110            delay_read_reg <= COUNT_VALUE; --initialize delay
111            bits_read_reg <= bits_read_reg - 1; --bits left to read
112            data_read_reg <= uart_read2 & data_read_reg(7 downto 1);
113         end if;
114      else
115         delay_read_reg <= delay_read_reg - 1; --delay
116      end if;
117
118      --Control character buffer
119      if bits_read_reg = "0000" and delay_read_reg = COUNT_VALUE then
120         if data_save_reg(8) = '0' or
121               (enable_read = '1' and data_save_reg(17) = '0') then
122            --Empty buffer
123            data_save_reg(8 downto 0) <= '1' & data_read_reg;
124         else
125            --Second character in buffer
126            data_save_reg(17 downto 9) <= '1' & data_read_reg;
127            if enable_read = '1' then
128               data_save_reg(8 downto 0) <= data_save_reg(17 downto 9);
129            end if;
130         end if;
131      elsif enable_read = '1' then
132         data_save_reg(17) <= '0'; --data_available
133         data_save_reg(8 downto 0) <= data_save_reg(17 downto 9);
134      end if;
135   end if; --rising_edge(clk)
136
137   uart_write <= data_write_reg(0);
138   if bits_write_reg /= "0000"
139-- Comment out the following line for full UART simulation (much slower)
140   and log_file = "UNUSED"
141   then
142      busy_write_sig <= '1';
143   else
144      busy_write_sig <= '0';
145   end if;
146   busy_write <= busy_write_sig;
147   data_avail <= data_save_reg(8);
148   data_out <= data_save_reg(7 downto 0);
149
150end process; --uart_proc
151
152-- synthesis_off
153   uart_logger:
154   if log_file /= "UNUSED" generate
155      uart_proc: process(clk, enable_write, data_in)
156         file store_file : text open write_mode is log_file;
157         variable hex_file_line : line;
158         variable c : character;
159         variable index : natural;
160         variable line_length : natural := 0;
161      begin
162         if rising_edge(clk) and busy_write_sig = '0' then
163            if enable_write = '1' then
164               index := conv_integer(data_in(6 downto 0));
165               if index /= 10 then
166                  c := character'val(index);
167                  write(hex_file_line, c);
168                  line_length := line_length + 1;
169               end if;
170               if index = 10 or line_length >= 72 then
171--The following line may have to be commented out for synthesis
172                  writeline(store_file, hex_file_line);
173                  line_length := 0;
174               end if;
175            end if; --uart_sel
176         end if; --rising_edge(clk)
177      end process; --uart_proc
178   end generate; --uart_logger
179-- synthesis_on
180
181end; --architecture logic
plasma/src/Makefile
1VHDL_DIR = ../logic
2TOOLS_DIR = ../bin
3LIB_DIR = ../lib
4TARGET = bootldr
5CROSS = mips-elf
6GCC = $(CROSS)-gcc
7AS = $(CROSS)-as
8LD = $(CROSS)-ld
9DUMP = $(CROSS)-objdump
10OBJCOPY = $(CROSS)-objcopy
11INC_PATH = ../include
12CFLAGS = -O2 -I$(INC_PATH) -Wall -c -s
13ILDFLAGS = -Ttext 0 -eentry -Map $@.map -s -N
14LDFLAGS = -Ttext 0x10000000 -eentry -Map $@.map -s -N
15
16#Internal RAM 0x00
17#External RAM 0x10000000
18
19vpath %.c $(LIB_DIR)
20vpath %.S $(LIB_DIR)
21
22.c.o:
23    $(GCC) $(CFLAGS) $<
24.S.o:
25    $(AS) -o $@ $<
26
27all: $(TARGET)
28
29clean:
30    -rm -rf *.o *.txt *.map *.lst *.bin opcodes_iram opcodes_ram test bootldr
31
32$(TARGET): crt0.o $(TARGET).o no_os.o ddr_init.o
33    $(LD) $(ILDFLAGS) -o $@ $^
34    $(OBJCOPY) -I elf32-big -O binary $@ $@.bin
35
36vhdl_mem: $(TARGET)
37    $(TOOLS_DIR)/ramimage $(VHDL_DIR)/ram_xilinx.vhd $@.bin $(VHDL_DIR)/ram_image.vhd
38
39upload: $(TARGET)
40    sudo cat $^.bin > /dev/ttyUSB0
41
42run: $(TARGET)
43    $(TOOLS_DIR)/mlite $^.bin
plasma/src/bootldr.c
1/*--------------------------------------------------------------------
2 * TITLE: Plasma Bootloader
3 * AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4 * DATE CREATED: 12/17/05
5 * FILENAME: bootldr.c
6 * PROJECT: Plasma CPU core
7 * COPYRIGHT: Software placed into the public domain by the author.
8 * Software 'as is' without warranty. Author liable for nothing.
9 * DESCRIPTION:
10 * Plasma bootloader.
11 *--------------------------------------------------------------------*/
12#include "plasma.h"
13
14#define MemoryRead(A) (*(volatile unsigned long*)(A))
15#define MemoryWrite(A,V) *(volatile unsigned long*)(A)=(V)
16
17extern int putchar(int ch);
18extern int puts(const char *string);
19extern int getch(void);
20extern int kbhit(void);
21extern int DdrInit(void);
22
23typedef void (*FuncPtr)(void);
24typedef unsigned long uint32;
25typedef unsigned short uint16;
26
27
28void FlashRead(uint16 *dst, uint32 byteOffset, int bytes)
29{
30   volatile uint32 *ptr=(uint32*)(FLASH_BASE + (byteOffset << 1));
31   *ptr = 0xff; //read mode
32   while(bytes > 0)
33   {
34      *dst++ = (uint16)*ptr++;
35      bytes -= 2;
36   }
37}
38
39
40void FlashWrite(uint16 *src, uint32 byteOffset, int bytes)
41{
42   volatile uint32 *ptr=(uint32*)(FLASH_BASE + (byteOffset << 1));
43   while(bytes > 0)
44   {
45      *ptr = 0x40; //write mode
46      *ptr++ = *src++; //write data
47      while((*ptr & 0x80) == 0) //check status
48         ;
49      bytes -= 2;
50   }
51}
52
53
54void FlashErase(uint32 byteOffset)
55{
56   volatile uint32 *ptr=(uint32*)(FLASH_BASE + (byteOffset << 1));
57   *ptr = 0x20; //erase block
58   *ptr = 0xd0; //confirm
59   while((*ptr & 0x80) == 0) //check status
60      ;
61}
62
63
64char *xtoa(unsigned long num)
65{
66   static char buf[12];
67   int i, digit;
68   buf[8] = 0;
69   for (i = 7; i >= 0; --i)
70   {
71      digit = num & 0xf;
72      buf[i] = digit + (digit < 10 ? '0' : 'A' - 10);
73      num >>= 4;
74   }
75   return buf;
76}
77
78
79unsigned long getnum(void)
80{
81   int i;
82   unsigned long ch, ch2, value=0;
83   for(i = 0; i < 16; )
84   {
85      ch = ch2 = getch();
86      if(ch == '\n' || ch == '\r')
87         break;
88      if('0' <= ch && ch <= '9')
89         ch -= '0';
90      else if('A' <= ch && ch <= 'Z')
91         ch = ch - 'A' + 10;
92      else if('a' <= ch && ch <= 'z')
93         ch = ch - 'a' + 10;
94      else if(ch == 8)
95      {
96         if(i > 0)
97         {
98            --i;
99            putchar(ch);
100            putchar(' ');
101            putchar(ch);
102         }
103         value >>= 4;
104         continue;
105      }
106      putchar(ch2);
107      value = (value << 4) + ch;
108      ++i;
109   }
110   putchar('\r');
111   putchar('\n');
112   return value;
113}
114
115
116int main(void)
117{
118   int i, j, ch;
119   unsigned long address, value, count;
120   FuncPtr funcPtr;
121   unsigned char *ptr1;
122
123   DdrInit(); //Harmless if SDRAM instead of DDR
124
125   puts("\nGreetings from the bootloader ");
126   puts(__DATE__);
127   puts(" ");
128   puts(__TIME__);
129   puts(":\n");
130   MemoryWrite(FLASH_BASE, 0xff); //read mode
131   if((MemoryRead(GPIOA_IN) & 1) && (MemoryRead(FLASH_BASE) & 0xffff) == 0x3c1c)
132   {
133      puts("Boot from flash\n");
134      FlashRead((uint16*)RAM_EXTERNAL_BASE, 0, 1024*128);
135      funcPtr = (FuncPtr)RAM_EXTERNAL_BASE;
136      funcPtr();
137   }
138   for(;;)
139   {
140      puts("\nWaiting for binary image linked at 0x10000000\n");
141      puts("Other Menu Options:\n");
142      puts("1. Memory read word\n");
143      puts("2. Memory write word\n");
144      puts("3. Memory read byte\n");
145      puts("4. Memory write byte\n");
146      puts("5. Jump to address\n");
147      puts("6. Raw memory read\n");
148      puts("7. Raw memory write\n");
149      puts("8. Checksum\n");
150      puts("9. Dump\n");
151      puts("F. Copy 128KB from DDR to flash\n");
152      puts("> ");
153      ch = getch();
154      address = 0;
155      if('0' <= ch && ch <= '9')
156      {
157         putchar(ch);
158         puts("\nAddress in hex> ");
159         address = getnum();
160         puts("Address = ");
161         puts(xtoa(address));
162         puts("\n");
163      }
164      switch(ch)
165      {
166      case '1':
167         value = MemoryRead(address);
168         puts(xtoa(value));
169         puts("\n");
170         break;
171      case '2':
172         puts("\nValue in hex> ");
173         value = getnum();
174         puts(xtoa(value));
175         MemoryWrite(address, value);
176         break;
177      case '3':
178         value = *(unsigned char*)address;
179         puts(xtoa(value));
180         puts("\n");
181         break;
182      case '4':
183         puts("\nValue in hex> ");
184         value = getnum();
185         puts(xtoa(value));
186         *(unsigned char*)address = value;
187         break;
188      case '5':
189         funcPtr = (FuncPtr)address;
190         funcPtr();
191         break;
192      case '6':
193         puts("\nCount in hex> ");
194         count = getnum();
195         for(i = 0; i < count; ++i)
196         {
197            ch = *(unsigned char*)(address + i);
198            putchar(ch);
199         }
200         break;
201      case '7':
202         puts("\nCount in hex> ");
203         count = getnum();
204         for(i = 0; i < count; ++i)
205         {
206            ch = getch();
207            *(unsigned char*)(address+i) = ch;
208         }
209         break;
210      case '8':
211         puts("\nCount in hex> ");
212         count = getnum();
213         value = 0;
214         for(i = 0; i < count; ++i)
215         {
216            value += *(unsigned char*)(address+i);
217         }
218         puts(xtoa(value));
219         putchar('\n');
220         break;
221      case '9':
222         puts("\nCount in hex> ");
223         count = getnum();
224         value = 0;
225         for(i = 0; i < count; i += 4)
226         {
227            if((i & 15) == 0)
228               puts("\r\n");
229            value = *(unsigned long*)(address+i);
230            puts(xtoa(value));
231            putchar(' ');
232         }
233         puts("\r\n");
234         break;
235      case 'F':
236         puts("\nConfirm with 12345678> ");
237         value = getnum();
238         if(value == 0x12345678)
239         {
240            FlashErase(0);
241            FlashWrite((uint16*)RAM_EXTERNAL_BASE, 0, 1024*128);
242         }
243         break;
244      case 0x3c: //raw test.bin file
245         ptr1 = (unsigned char*)0x10000000;
246         for(i = 0; i < 1024*1024; ++i)
247         {
248            ptr1[i] = (unsigned char)ch;
249            for(j = 0; j < 10000; ++j)
250            {
251               if(kbhit())
252                  break;
253            }
254            if(j >= 10000)
255               break; //assume end of file
256            ch = getch();
257         }
258         funcPtr = (FuncPtr)0x10000000;
259         funcPtr();
260         break;
261      }
262   }
263   return 0;
264}
265
plasma/tools/Makefile
1CC_X86 = gcc -Wall -O -g
2CP = cp
3RM = rm -rf
4DWIN32 =
5BIN_MIPS =
6VHDL_DIR = ../logic
7LINUX_PWD = ./
8CONVERT_BIN = $(LINUX_PWD)convert_bin
9
10CFLAGS = -O2 -Wall -c -s
11
12all: ramimage mlite
13    rm -rf ../bin
14    mkdir ../bin; mv ramimage ../bin; mv mlite ../bin
15
16clean:
17    -$(RM) *.o *.obj *.map *.lst *.hex *.txt
18
19ramimage: ramimage.c
20    @$(CC_X86) -o ramimage ramimage.c
21
22mlite: mlite.c
23    @$(CC_X86) -o mlite mlite.c
24
plasma/tools/mlite.c
1/*-------------------------------------------------------------------
2-- TITLE: Plasma CPU in software. Executes MIPS(tm) opcodes.
3-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4-- DATE CREATED: 1/31/01
5-- FILENAME: mlite.c
6-- PROJECT: Plasma CPU core
7-- COPYRIGHT: Software placed into the public domain by the author.
8-- Software 'as is' without warranty. Author liable for nothing.
9-- DESCRIPTION:
10-- Plasma CPU simulator in C code.
11-- This file served as the starting point for the VHDL code.
12-- Assumes running on a little endian PC.
13--------------------------------------------------------------------*/
14#include <stdio.h>
15#include <stdlib.h>
16#include <string.h>
17#include <ctype.h>
18#include <assert.h>
19
20//#define ENABLE_CACHE
21#define SIMPLE_CACHE
22
23#define MEM_SIZE (1024*1024*2)
24#define ntohs(A) ( ((A)>>8) | (((A)&0xff)<<8) )
25#define htons(A) ntohs(A)
26#define ntohl(A) ( ((A)>>24) | (((A)&0xff0000)>>8) | (((A)&0xff00)<<8) | ((A)<<24) )
27#define htonl(A) ntohl(A)
28
29#ifndef WIN32
30//Support for Linux
31#define putch putchar
32#include <termios.h>
33#include <unistd.h>
34
35void Sleep(unsigned int value)
36{
37   usleep(value * 1000);
38}
39
40int kbhit(void)
41{
42   struct termios oldt, newt;
43   struct timeval tv;
44   fd_set read_fd;
45
46   tcgetattr(STDIN_FILENO, &oldt);
47   newt = oldt;
48   newt.c_lflag &= ~(ICANON | ECHO);
49   tcsetattr(STDIN_FILENO, TCSANOW, &newt);
50   tv.tv_sec=0;
51   tv.tv_usec=0;
52   FD_ZERO(&read_fd);
53   FD_SET(0,&read_fd);
54   if(select(1, &read_fd, NULL, NULL, &tv) == -1)
55      return 0;
56   //tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
57   if(FD_ISSET(0,&read_fd))
58      return 1;
59   return 0;
60}
61
62int getch(void)
63{
64   struct termios oldt, newt;
65   int ch;
66
67   tcgetattr(STDIN_FILENO, &oldt);
68   newt = oldt;
69   newt.c_lflag &= ~(ICANON | ECHO);
70   tcsetattr(STDIN_FILENO, TCSANOW, &newt);
71   ch = getchar();
72   //tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
73   return ch;
74}
75#else
76//Support for Windows
77#include <conio.h>
78extern void __stdcall Sleep(unsigned long value);
79#endif
80
81#define UART_WRITE 0x20000000
82#define UART_READ 0x20000000
83#define IRQ_MASK 0x20000010
84#define IRQ_STATUS 0x20000020
85#define CONFIG_REG 0x20000070
86#define MMU_PROCESS_ID 0x20000080
87#define MMU_FAULT_ADDR 0x20000090
88#define MMU_TLB 0x200000a0
89
90#define IRQ_UART_READ_AVAILABLE 0x001
91#define IRQ_UART_WRITE_AVAILABLE 0x002
92#define IRQ_COUNTER18_NOT 0x004
93#define IRQ_COUNTER18 0x008
94#define IRQ_MMU 0x200
95
96#define MMU_ENTRIES 4
97#define MMU_MASK (1024*4-1)
98
99typedef struct
100{
101   unsigned int virtualAddress;
102   unsigned int physicalAddress;
103} MmuEntry;
104
105typedef struct {
106   int r[32];
107   int pc, pc_next, epc;
108   unsigned int hi;
109   unsigned int lo;
110   int status;
111   int userMode;
112   int processId;
113   int exceptionId;
114   int faultAddr;
115   int irqStatus;
116   int skip;
117   unsigned char *mem;
118   int wakeup;
119   int big_endian;
120   MmuEntry mmuEntry[MMU_ENTRIES];
121} State;
122
123static char *opcode_string[]={
124   "SPECIAL","REGIMM","J","JAL","BEQ","BNE","BLEZ","BGTZ",
125   "ADDI","ADDIU","SLTI","SLTIU","ANDI","ORI","XORI","LUI",
126   "COP0","COP1","COP2","COP3","BEQL","BNEL","BLEZL","BGTZL",
127   "?","?","?","?","?","?","?","?",
128   "LB","LH","LWL","LW","LBU","LHU","LWR","?",
129   "SB","SH","SWL","SW","?","?","SWR","CACHE",
130   "LL","LWC1","LWC2","LWC3","?","LDC1","LDC2","LDC3"
131   "SC","SWC1","SWC2","SWC3","?","SDC1","SDC2","SDC3"
132};
133
134static char *special_string[]={
135   "SLL","?","SRL","SRA","SLLV","?","SRLV","SRAV",
136   "JR","JALR","MOVZ","MOVN","SYSCALL","BREAK","?","SYNC",
137   "MFHI","MTHI","MFLO","MTLO","?","?","?","?",
138   "MULT","MULTU","DIV","DIVU","?","?","?","?",
139   "ADD","ADDU","SUB","SUBU","AND","OR","XOR","NOR",
140   "?","?","SLT","SLTU","?","DADDU","?","?",
141   "TGE","TGEU","TLT","TLTU","TEQ","?","TNE","?",
142   "?","?","?","?","?","?","?","?"
143};
144
145static char *regimm_string[]={
146   "BLTZ","BGEZ","BLTZL","BGEZL","?","?","?","?",
147   "TGEI","TGEIU","TLTI","TLTIU","TEQI","?","TNEI","?",
148   "BLTZAL","BEQZAL","BLTZALL","BGEZALL","?","?","?","?",
149   "?","?","?","?","?","?","?","?"
150};
151
152static unsigned int HWMemory[8];
153
154
155static int mem_read(State *s, int size, unsigned int address)
156{
157   unsigned int value=0, ptr;
158
159   s->irqStatus |= IRQ_UART_WRITE_AVAILABLE;
160   switch(address)
161   {
162      case UART_READ:
163         if(kbhit())
164            HWMemory[0] = getch();
165         s->irqStatus &= ~IRQ_UART_READ_AVAILABLE; //clear bit
166         return HWMemory[0];
167      case IRQ_MASK:
168         return HWMemory[1];
169      case IRQ_MASK + 4:
170         Sleep(10);
171         return 0;
172      case IRQ_STATUS:
173         if(kbhit())
174            s->irqStatus |= IRQ_UART_READ_AVAILABLE;
175         return s->irqStatus;
176      case MMU_PROCESS_ID:
177         return s->processId;
178      case MMU_FAULT_ADDR:
179         return s->faultAddr;
180   }
181
182   ptr = (unsigned int)s->mem + (address % MEM_SIZE);
183
184   if(0x10000000 <= address && address < 0x10000000 + 1024*1024)
185      ptr += 1024*1024;
186
187   switch(size)
188   {
189      case 4:
190         if(address & 3)
191            printf("Unaligned access PC=0x%x address=0x%x\n", (int)s->pc, (int)address);
192         assert((address & 3) == 0);
193         value = *(int*)ptr;
194         if(s->big_endian)
195            value = ntohl(value);
196         break;
197      case 2:
198         assert((address & 1) == 0);
199         value = *(unsigned short*)ptr;
200         if(s->big_endian)
201            value = ntohs((unsigned short)value);
202         break;
203      case 1:
204         value = *(unsigned char*)ptr;
205         break;
206      default:
207         printf("ERROR");
208   }
209   return(value);
210}
211
212static void mem_write(State *s, int size, int unsigned address, unsigned int value)
213{
214   unsigned int ptr;
215
216   switch(address)
217   {
218      case UART_WRITE:
219         putch(value);
220         fflush(stdout);
221         return;
222      case IRQ_MASK:
223         HWMemory[1] = value;
224         return;
225      case IRQ_STATUS:
226         s->irqStatus = value;
227         return;
228      case CONFIG_REG:
229         return;
230      case MMU_PROCESS_ID:
231         //printf("processId=%d\n", value);
232         s->processId = value;
233         return;
234   }
235
236   if(MMU_TLB <= address && address <= MMU_TLB+MMU_ENTRIES * 8)
237   {
238      //printf("TLB 0x%x 0x%x\n", address - MMU_TLB, value);
239      ptr = (unsigned int)s->mmuEntry + address - MMU_TLB;
240      *(int*)ptr = value;
241      s->irqStatus &= ~IRQ_MMU;
242      return;
243   }
244
245   ptr = (unsigned int)s->mem + (address % MEM_SIZE);
246
247   if(0x10000000 <= address && address < 0x10000000 + 1024*1024)
248      ptr += 1024*1024;
249
250   switch(size)
251   {
252      case 4:
253         assert((address & 3) == 0);
254         if(s->big_endian)
255            value = htonl(value);
256         *(int*)ptr = value;
257         break;
258      case 2:
259         assert((address & 1) == 0);
260         if(s->big_endian)
261            value = htons((unsigned short)value);
262         *(short*)ptr = (unsigned short)value;
263         break;
264      case 1:
265         *(char*)ptr = (unsigned char)value;
266         break;
267      default:
268         printf("ERROR");
269   }
270}
271
272#ifdef ENABLE_CACHE
273/************* Optional MMU and cache implementation *************/
274/* TAG = VirtualAddress | ProcessId | WriteableBit */
275unsigned int mmu_lookup(State *s, unsigned int processId,
276                         unsigned int address, int write)
277{
278   int i;
279   unsigned int compare, tag;
280
281   if(processId == 0 || s->userMode == 0)
282      return address;
283   //if(address < 0x30000000)
284   // return address;
285   compare = (address & ~MMU_MASK) | (processId << 1);
286   for(i = 0; i < MMU_ENTRIES; ++i)
287   {
288      tag = s->mmuEntry[i].virtualAddress;
289      if((tag & ~1) == compare && (write == 0 || (tag & 1)))
290         return s->mmuEntry[i].physicalAddress | (address & MMU_MASK);
291   }
292   //printf("\nMMUTlbMiss 0x%x PC=0x%x w=%d pid=%d user=%d\n",
293   // address, s->pc, write, processId, s->userMode);
294   //printf("m");
295   s->exceptionId = 1;
296   s->faultAddr = address & ~MMU_MASK;
297   s->irqStatus |= IRQ_MMU;
298   return address;
299}
300
301
302#define CACHE_SET_ASSOC_LN2 0
303#define CACHE_SET_ASSOC (1 << CACHE_SET_ASSOC_LN2)
304#define CACHE_SIZE_LN2 (13 - CACHE_SET_ASSOC_LN2) //8 KB
305#define CACHE_SIZE (1 << CACHE_SIZE_LN2)
306#define CACHE_LINE_SIZE_LN2 2 //4 bytes
307#define CACHE_LINE_SIZE (1 << CACHE_LINE_SIZE_LN2)
308
309static int cacheData[CACHE_SET_ASSOC][CACHE_SIZE/sizeof(int)];
310static int cacheAddr[CACHE_SET_ASSOC][CACHE_SIZE/CACHE_LINE_SIZE];
311static int cacheSetNext;
312static int cacheMiss, cacheWriteBack, cacheCount;
313
314static void cache_init(void)
315{
316   int set, i;
317   for(set = 0; set < CACHE_SET_ASSOC; ++set)
318   {
319      for(i = 0; i < CACHE_SIZE/CACHE_LINE_SIZE; ++i)
320         cacheAddr[set][i] = 0xffff0000;
321   }
322}
323
324/* Write-back cache memory tagged by virtual address and processId */
325/* TAG = virtualAddress | processId | dirtyBit */
326static int cache_load(State *s, unsigned int address, int write)
327{
328   int set, i, pid, miss, offsetAddr, offsetData, offsetMem;
329   unsigned int addrTagMatch, addrPrevMatch=0;
330   unsigned int addrPrev;
331   unsigned int addressPhysical, tag;
332
333   ++cacheCount;
334   addrTagMatch = address & ~(CACHE_SIZE-1);
335   offsetAddr = (address & (CACHE_SIZE-1)) >> CACHE_LINE_SIZE_LN2;
336
337   /* Find match */
338   miss = 1;
339   for(set = 0; set < CACHE_SET_ASSOC; ++set)
340   {
341      addrPrevMatch = cacheAddr[set][offsetAddr] & ~(CACHE_SIZE-1);
342      if(addrPrevMatch == addrTagMatch)
343      {
344         miss = 0;
345         break;
346      }
347   }
348
349   /* Cache miss? */
350   if(miss)
351   {
352      ++cacheMiss;
353      set = cacheSetNext;
354      cacheSetNext = (cacheSetNext + 1) & (CACHE_SET_ASSOC-1);
355   }
356   //else if(write || (address >> 28) != 0x1)
357   //{
358   // tag = cacheAddr[set][offsetAddr];
359   // pid = (tag & (CACHE_SIZE-1)) >> 1;
360   // if(pid != s->processId)
361   // miss = 1;
362   //}
363
364   if(miss)
365   {
366      offsetData = address & (CACHE_SIZE-1) & ~(CACHE_LINE_SIZE-1);
367
368      /* Cache line dirty? */
369      if(cacheAddr[set][offsetAddr] & 1)
370      {
371         /* Write back cache line */
372         tag = cacheAddr[set][offsetAddr];
373         addrPrev = tag & ~(CACHE_SIZE-1);
374         addrPrev |= address & (CACHE_SIZE-1);
375         pid = (tag & (CACHE_SIZE-1)) >> 1;
376         addressPhysical = mmu_lookup(s, pid, addrPrev, 1); //virtual->physical
377         if(s->exceptionId)
378            return 0;
379         offsetMem = addressPhysical & ~(CACHE_LINE_SIZE-1);
380         for(i = 0; i < CACHE_LINE_SIZE; i += 4)
381            mem_write(s, 4, offsetMem + i, cacheData[set][(offsetData + i) >> 2]);
382         ++cacheWriteBack;
383      }
384
385      /* Read cache line */
386      addressPhysical = mmu_lookup(s, s->processId, address, write); //virtual->physical
387      if(s->exceptionId)
388         return 0;
389      offsetMem = addressPhysical & ~(CACHE_LINE_SIZE-1);
390      cacheAddr[set][offsetAddr] = addrTagMatch;
391      for(i = 0; i < CACHE_LINE_SIZE; i += 4)
392         cacheData[set][(offsetData + i) >> 2] = mem_read(s, 4, offsetMem + i);
393   }
394   cacheAddr[set][offsetAddr] |= write;
395   return set;
396}
397
398static int cache_read(State *s, int size, unsigned int address)
399{
400   int set, offset;
401   int value;
402
403   if((address & 0xfe000000) != 0x10000000)
404      return mem_read(s, size, address);
405
406   set = cache_load(s, address, 0);
407   if(s->exceptionId)
408      return 0;
409   offset = (address & (CACHE_SIZE-1)) >> 2;
410   value = cacheData[set][offset];
411   if(s->big_endian)
412      address ^= 3;
413   switch(size)
414   {
415      case 2:
416         value = (value >> ((address & 2) << 3)) & 0xffff;
417         break;
418      case 1:
419         value = (value >> ((address & 3) << 3)) & 0xff;
420         break;
421   }
422   return value;
423}
424
425static void cache_write(State *s, int size, int unsigned address, unsigned int value)
426{
427   int set, offset;
428   unsigned int mask;
429
430   if((address >> 28) != 0x1) // && (s->processId == 0 || s->userMode == 0))
431   {
432      mem_write(s, size, address, value);
433      return;
434   }
435
436   set = cache_load(s, address, 1);
437   if(s->exceptionId)
438      return;
439   offset = (address & (CACHE_SIZE-1)) >> 2;
440   if(s->big_endian)
441      address ^= 3;
442   switch(size)
443   {
444      case 2:
445         value &= 0xffff;
446         value |= value << 16;
447         mask = 0xffff << ((address & 2) << 3);
448         break;
449      case 1:
450         value &= 0xff;
451         value |= (value << 8) | (value << 16) | (value << 24);
452         mask = 0xff << ((address & 3) << 3);
453         break;
454      case 4:
455      default:
456         mask = 0xffffffff;
457         break;
458   }
459   cacheData[set][offset] = (value & mask) | (cacheData[set][offset] & ~mask);
460}
461
462#define mem_read cache_read
463#define mem_write cache_write
464
465#else
466static void cache_init(void) {}
467#endif
468
469
470#ifdef SIMPLE_CACHE
471
472//Write through direct mapped 4KB cache
473#define CACHE_MISS 0x1ff
474static unsigned int cacheData[1024];
475static unsigned int cacheAddr[1024]; //9-bit addresses
476static int cacheTry, cacheMiss, cacheInit;
477
478static int cache_read(State *s, int size, unsigned int address)
479{
480   int offset;
481   unsigned int value, value2, address2=address;
482
483   if(cacheInit == 0)
484   {
485      cacheInit = 1;
486      for(offset = 0; offset < 1024; ++offset)
487         cacheAddr[offset] = CACHE_MISS;
488   }
489
490   offset = address >> 20;
491   if(offset != 0x100 && offset != 0x101)
492      return mem_read(s, size, address);
493
494   ++cacheTry;
495   offset = (address >> 2) & 0x3ff;
496   if(cacheAddr[offset] != (address >> 12) || cacheAddr[offset] == CACHE_MISS)
497   {
498      ++cacheMiss;
499      cacheAddr[offset] = address >> 12;
500      cacheData[offset] = mem_read(s, 4, address & ~3);
501   }
502   value = cacheData[offset];
503   if(s->big_endian)
504      address ^= 3;
505   switch(size)
506   {
507      case 2:
508         value = (value >> ((address & 2) << 3)) & 0xffff;
509         break;
510      case 1:
511         value = (value >> ((address & 3) << 3)) & 0xff;
512         break;
513   }
514
515   //Debug testing
516   value2 = mem_read(s, size, address2);
517   if(value != value2)
518      printf("miss match\n");
519   //if((cacheTry & 0xffff) == 0) printf("\n***cache(%d,%d)\n ", cacheMiss, cacheTry);
520   return value;
521}
522
523static void cache_write(State *s, int size, int unsigned address, unsigned int value)
524{
525   int offset;
526
527   mem_write(s, size, address, value);
528
529   offset = address >> 20;
530   if(offset != 0x100 && offset != 0x101)
531      return;
532
533   offset = (address >> 2) & 0x3ff;
534   if(size != 4)
535   {
536      cacheAddr[offset] = CACHE_MISS;
537      return;
538   }
539   cacheAddr[offset] = address >> 12;
540   cacheData[offset] = value;
541}
542
543#define mem_read cache_read
544#define mem_write cache_write
545#endif //SIMPLE_CACHE
546/************* End optional cache implementation *************/
547
548
549void mult_big(unsigned int a,
550              unsigned int b,
551              unsigned int *hi,
552              unsigned int *lo)
553{
554   unsigned int ahi, alo, bhi, blo;
555   unsigned int c0, c1, c2;
556   unsigned int c1_a, c1_b;
557
558   ahi = a >> 16;
559   alo = a & 0xffff;
560   bhi = b >> 16;
561   blo = b & 0xffff;
562
563   c0 = alo * blo;
564   c1_a = ahi * blo;
565   c1_b = alo * bhi;
566   c2 = ahi * bhi;
567
568   c2 += (c1_a >> 16) + (c1_b >> 16);
569   c1 = (c1_a & 0xffff) + (c1_b & 0xffff) + (c0 >> 16);
570   c2 += (c1 >> 16);
571   c0 = (c1 << 16) + (c0 & 0xffff);
572   *hi = c2;
573   *lo = c0;
574}
575
576void mult_big_signed(int a,
577                     int b,
578                     unsigned int *hi,
579                     unsigned int *lo)
580{
581   unsigned int ahi, alo, bhi, blo;
582   unsigned int c0, c1, c2;
583   unsigned int c1_a, c1_b;
584
585   ahi = a >> 16;
586   alo = a & 0xffff;
587   bhi = b >> 16;
588   blo = b & 0xffff;
589
590   c0 = alo * blo;
591   c1_a = ahi * blo;
592   c1_b = alo * bhi;
593   c2 = ahi * bhi;
594
595   c2 += (c1_a >> 16) + (c1_b >> 16);
596   c1 = (c1_a & 0xffff) + (c1_b & 0xffff) + (c0 >> 16);
597   c2 += (c1 >> 16);
598   c0 = (c1 << 16) + (c0 & 0xffff);
599   *hi = c2;
600   *lo = c0;
601}
602
603//execute one cycle of a Plasma CPU
604void cycle(State *s, int show_mode)
605{
606   unsigned int opcode;
607   unsigned int op, rs, rt, rd, re, func, imm, target;
608   int imm_shift, branch=0, lbranch=2, skip2=0;
609   int *r=s->r;
610   unsigned int *u=(unsigned int*)s->r;
611   unsigned int ptr, epc, rSave;
612
613   opcode = mem_read(s, 4, s->pc);
614   op = (opcode >> 26) & 0x3f;
615   rs = (opcode >> 21) & 0x1f;
616   rt = (opcode >> 16) & 0x1f;
617   rd = (opcode >> 11) & 0x1f;
618   re = (opcode >> 6) & 0x1f;
619   func = opcode & 0x3f;
620   imm = opcode & 0xffff;
621   imm_shift = (((int)(short)imm) << 2) - 4;
622   target = (opcode << 6) >> 4;
623   ptr = (short)imm + r[rs];
624   r[0] = 0;
625   if(show_mode)
626   {
627      printf("%8.8x %8.8x ", s->pc, opcode);
628      if(op == 0)
629         printf("%8s ", special_string[func]);
630      else if(op == 1)
631         printf("%8s ", regimm_string[rt]);
632      else
633         printf("%8s ", opcode_string[op]);
634      printf("$%2.2d $%2.2d $%2.2d $%2.2d ", rs, rt, rd, re);
635      printf("%4.4x", imm);
636      if(show_mode == 1)
637         printf(" r[%2.2d]=%8.8x r[%2.2d]=%8.8x", rs, r[rs], rt, r[rt]);
638      printf("\n");
639   }
640   if(show_mode > 5)
641      return;
642   epc = s->pc + 4;
643   if(s->pc_next != s->pc + 4)
644      epc |= 2; //branch delay slot
645   s->pc = s->pc_next;
646   s->pc_next = s->pc_next + 4;
647   if(s->skip)
648   {
649      s->skip = 0;
650      return;
651   }
652   rSave = r[rt];
653   switch(op)
654   {
655      case 0x00:/*SPECIAL*/
656         switch(func)
657         {
658            case 0x00:/*SLL*/ r[rd]=r[rt]<<re; break;
659            case 0x02:/*SRL*/ r[rd]=u[rt]>>re; break;
660            case 0x03:/*SRA*/ r[rd]=r[rt]>>re; break;
661            case 0x04:/*SLLV*/ r[rd]=r[rt]<<r[rs]; break;
662            case 0x06:/*SRLV*/ r[rd]=u[rt]>>r[rs]; break;
663            case 0x07:/*SRAV*/ r[rd]=r[rt]>>r[rs]; break;
664            case 0x08:/*JR*/ s->pc_next=r[rs]; break;
665            case 0x09:/*JALR*/ r[rd]=s->pc_next; s->pc_next=r[rs]; break;
666            case 0x0a:/*MOVZ*/ if(!r[rt]) r[rd]=r[rs]; break; /*IV*/
667            case 0x0b:/*MOVN*/ if(r[rt]) r[rd]=r[rs]; break; /*IV*/
668            case 0x0c:/*SYSCALL*/ epc|=1; s->exceptionId=1; break;
669            case 0x0d:/*BREAK*/ epc|=1; s->exceptionId=1; break;
670            case 0x0f:/*SYNC*/ s->wakeup=1; break;
671            case 0x10:/*MFHI*/ r[rd]=s->hi; break;
672            case 0x11:/*FTHI*/ s->hi=r[rs]; break;
673            case 0x12:/*MFLO*/ r[rd]=s->lo; break;
674            case 0x13:/*MTLO*/ s->lo=r[rs]; break;
675            case 0x18:/*MULT*/ mult_big_signed(r[rs],r[rt],&s->hi,&s->lo); break;
676            case 0x19:/*MULTU*/ mult_big(r[rs],r[rt],&s->hi,&s->lo); break;
677            case 0x1a:/*DIV*/ s->lo=r[rs]/r[rt]; s->hi=r[rs]%r[rt]; break;
678            case 0x1b:/*DIVU*/ s->lo=u[rs]/u[rt]; s->hi=u[rs]%u[rt]; break;
679            case 0x20:/*ADD*/ r[rd]=r[rs]+r[rt]; break;
680            case 0x21:/*ADDU*/ r[rd]=r[rs]+r[rt]; break;
681            case 0x22:/*SUB*/ r[rd]=r[rs]-r[rt]; break;
682            case 0x23:/*SUBU*/ r[rd]=r[rs]-r[rt]; break;
683            case 0x24:/*AND*/ r[rd]=r[rs]&r[rt]; break;
684            case 0x25:/*OR*/ r[rd]=r[rs]|r[rt]; break;
685            case 0x26:/*XOR*/ r[rd]=r[rs]^r[rt]; break;
686            case 0x27:/*NOR*/ r[rd]=~(r[rs]|r[rt]); break;
687            case 0x2a:/*SLT*/ r[rd]=r[rs]<r[rt]; break;
688            case 0x2b:/*SLTU*/ r[rd]=u[rs]<u[rt]; break;
689            case 0x2d:/*DADDU*/r[rd]=r[rs]+u[rt]; break;
690            case 0x31:/*TGEU*/ break;
691            case 0x32:/*TLT*/ break;
692            case 0x33:/*TLTU*/ break;
693            case 0x34:/*TEQ*/ break;
694            case 0x36:/*TNE*/ break;
695            default: printf("ERROR0(*0x%x~0x%x)\n", s->pc, opcode);
696               s->wakeup=1;
697         }
698         break;
699      case 0x01:/*REGIMM*/
700         switch(rt) {
701            case 0x10:/*BLTZAL*/ r[31]=s->pc_next;
702            case 0x00:/*BLTZ*/ branch=r[rs]<0; break;
703            case 0x11:/*BGEZAL*/ r[31]=s->pc_next;
704            case 0x01:/*BGEZ*/ branch=r[rs]>=0; break;
705            case 0x12:/*BLTZALL*/r[31]=s->pc_next;
706            case 0x02:/*BLTZL*/ lbranch=r[rs]<0; break;
707            case 0x13:/*BGEZALL*/r[31]=s->pc_next;
708            case 0x03:/*BGEZL*/ lbranch=r[rs]>=0; break;
709            default: printf("ERROR1\n"); s->wakeup=1;
710          }
711         break;
712      case 0x03:/*JAL*/ r[31]=s->pc_next;
713      case 0x02:/*J*/ s->pc_next=(s->pc&0xf0000000)|target; break;
714      case 0x04:/*BEQ*/ branch=r[rs]==r[rt]; break;
715      case 0x05:/*BNE*/ branch=r[rs]!=r[rt]; break;
716      case 0x06:/*BLEZ*/ branch=r[rs]<=0; break;
717      case 0x07:/*BGTZ*/ branch=r[rs]>0; break;
718      case 0x08:/*ADDI*/ r[rt]=r[rs]+(short)imm; break;
719      case 0x09:/*ADDIU*/ u[rt]=u[rs]+(short)imm; break;
720      case 0x0a:/*SLTI*/ r[rt]=r[rs]<(short)imm; break;
721      case 0x0b:/*SLTIU*/ u[rt]=u[rs]<(unsigned int)(short)imm; break;
722      case 0x0c:/*ANDI*/ r[rt]=r[rs]&imm; break;
723      case 0x0d:/*ORI*/ r[rt]=r[rs]|imm; break;
724      case 0x0e:/*XORI*/ r[rt]=r[rs]^imm; break;
725      case 0x0f:/*LUI*/ r[rt]=(imm<<16); break;
726      case 0x10:/*COP0*/
727         if((opcode & (1<<23)) == 0) //move from CP0
728         {
729            if(rd == 12)
730               r[rt]=s->status;
731            else
732               r[rt]=s->epc;
733         }
734         else //move to CP0
735         {
736            s->status=r[rt]&1;
737            if(s->processId && (r[rt]&2))
738            {
739               s->userMode|=r[rt]&2;
740               //printf("CpuStatus=%d %d %d\n", r[rt], s->status, s->userMode);
741               //s->wakeup = 1;
742               //printf("pc=0x%x\n", epc);
743            }
744         }
745         break;
746// case 0x11:/*COP1*/ break;
747// case 0x12:/*COP2*/ break;
748// case 0x13:/*COP3*/ break;
749      case 0x14:/*BEQL*/ lbranch=r[rs]==r[rt]; break;
750      case 0x15:/*BNEL*/ lbranch=r[rs]!=r[rt]; break;
751      case 0x16:/*BLEZL*/ lbranch=r[rs]<=0; break;
752      case 0x17:/*BGTZL*/ lbranch=r[rs]>0; break;
753// case 0x1c:/*MAD*/ break; /*IV*/
754      case 0x20:/*LB*/ r[rt]=(signed char)mem_read(s,1,ptr); break;
755      case 0x21:/*LH*/ r[rt]=(signed short)mem_read(s,2,ptr); break;
756      case 0x22:/*LWL*/
757                         //target=8*(ptr&3);
758                         //r[rt]=(r[rt]&~(0xffffffff<<target))|
759                         // (mem_read(s,4,ptr&~3)<<target); break;
760      case 0x23:/*LW*/ r[rt]=mem_read(s,4,ptr); break;
761      case 0x24:/*LBU*/ r[rt]=(unsigned char)mem_read(s,1,ptr); break;
762      case 0x25:/*LHU*/ r[rt]=(unsigned short)mem_read(s,2,ptr); break;
763      case 0x26:/*LWR*/
764                         //target=32-8*(ptr&3);
765                         //r[rt]=(r[rt]&~((unsigned int)0xffffffff>>target))|
766                         //((unsigned int)mem_read(s,4,ptr&~3)>>target);
767                         break;
768      case 0x28:/*SB*/ mem_write(s,1,ptr,r[rt]); break;
769      case 0x29:/*SH*/ mem_write(s,2,ptr,r[rt]); break;
770      case 0x2a:/*SWL*/
771                         //mem_write(s,1,ptr,r[rt]>>24);
772                         //mem_write(s,1,ptr+1,r[rt]>>16);
773                         //mem_write(s,1,ptr+2,r[rt]>>8);
774                         //mem_write(s,1,ptr+3,r[rt]); break;
775      case 0x2b:/*SW*/ mem_write(s,4,ptr,r[rt]); break;
776      case 0x2e:/*SWR*/ break; //fixme
777      case 0x2f:/*CACHE*/break;
778      case 0x30:/*LL*/ r[rt]=mem_read(s,4,ptr); break;
779// case 0x31:/*LWC1*/ break;
780// case 0x32:/*LWC2*/ break;
781// case 0x33:/*LWC3*/ break;
782// case 0x35:/*LDC1*/ break;
783// case 0x36:/*LDC2*/ break;
784// case 0x37:/*LDC3*/ break;
785// case 0x38:/*SC*/ *(int*)ptr=r[rt]; r[rt]=1; break;
786      case 0x38:/*SC*/ mem_write(s,4,ptr,r[rt]); r[rt]=1; break;
787// case 0x39:/*SWC1*/ break;
788// case 0x3a:/*SWC2*/ break;
789// case 0x3b:/*SWC3*/ break;
790// case 0x3d:/*SDC1*/ break;
791// case 0x3e:/*SDC2*/ break;
792// case 0x3f:/*SDC3*/ break;
793      default: printf("ERROR2 address=0x%x opcode=0x%x\n", s->pc, opcode);
794         s->wakeup=1;
795   }
796   s->pc_next += (branch || lbranch == 1) ? imm_shift : 0;
797   s->pc_next &= ~3;
798   s->skip = (lbranch == 0) | skip2;
799
800   if(s->exceptionId)
801   {
802      r[rt] = rSave;
803      s->epc = epc;
804      s->pc_next = 0x3c;
805      s->skip = 1;
806      s->exceptionId = 0;
807      s->userMode = 0;
808      //s->wakeup = 1;
809      return;
810   }
811}
812
813void show_state(State *s)
814{
815   int i,j;
816   printf("pid=%d userMode=%d, epc=0x%x\n", s->processId, s->userMode, s->epc);
817   for(i = 0; i < 4; ++i)
818   {
819      printf("%2.2d ", i * 8);
820      for(j = 0; j < 8; ++j)
821      {
822         printf("%8.8x ", s->r[i*8+j]);
823      }
824      printf("\n");
825   }
826   //printf("%8.8lx %8.8lx %8.8lx %8.8lx\n", s->pc, s->pc_next, s->hi, s->lo);
827   j = s->pc;
828   for(i = -4; i <= 8; ++i)
829   {
830      printf("%c", i==0 ? '*' : ' ');
831      s->pc = j + i * 4;
832      cycle(s, 10);
833   }
834   s->pc = j;
835}
836
837void do_debug(State *s)
838{
839   int ch;
840   int i, j=0, watch=0, addr;
841   s->pc_next = s->pc + 4;
842   s->skip = 0;
843   s->wakeup = 0;
844   show_state(s);
845   ch = ' ';
846   for(;;)
847   {
848      if(ch != 'n')
849      {
850         if(watch)
851            printf("0x%8.8x=0x%8.8x\n", watch, mem_read(s, 4, watch));
852         printf("1=Debug 2=Trace 3=Step 4=BreakPt 5=Go 6=Memory ");
853         printf("7=Watch 8=Jump 9=Quit> ");
854      }
855      ch = getch();
856      if(ch != 'n')
857         printf("\n");
858      switch(ch)
859      {
860      case '1': case 'd': case ' ':
861         cycle(s, 0); show_state(s); break;
862      case 'n':
863         cycle(s, 1); break;
864      case '2': case 't':
865         cycle(s, 0); printf("*"); cycle(s, 10); break;
866      case '3': case 's':
867         printf("Count> ");
868         scanf("%d", &j);
869         for(i = 0; i < j; ++i)
870            cycle(s, 1);
871         show_state(s);
872         break;
873      case '4': case 'b':
874         printf("Line> ");
875         scanf("%x", &j);
876         printf("break point=0x%x\n", j);
877         break;
878      case '5': case 'g':
879         s->wakeup = 0;
880         cycle(s, 0);
881         while(s->wakeup == 0)
882         {
883            if(s->pc == j)
884               break;
885            cycle(s, 0);
886         }
887         show_state(s);
888         break;
889      case 'G':
890         s->wakeup = 0;
891         cycle(s, 1);
892         while(s->wakeup == 0)
893         {
894            if(s->pc == j)
895               break;
896            cycle(s, 1);
897         }
898         show_state(s);
899         break;
900      case '6': case 'm':
901         printf("Memory> ");
902         scanf("%x", &j);
903         for(i = 0; i < 8; ++i)
904         {
905            printf("%8.8x ", mem_read(s, 4, j+i*4));
906         }
907         printf("\n");
908         break;
909      case '7': case 'w':
910         printf("Watch> ");
911         scanf("%x", &watch);
912         break;
913      case '8': case 'j':
914         printf("Jump> ");
915         scanf("%x", &addr);
916         s->pc = addr;
917         s->pc_next = addr + 4;
918         show_state(s);
919         break;
920      case '9': case 'q':
921         return;
922      }
923   }
924}
925/************************************************************/
926
927int main(int argc,char *argv[])
928{
929   State state, *s=&state;
930   FILE *in;
931   int bytes, index;
932   printf("Plasma emulator\n");
933   memset(s, 0, sizeof(State));
934   s->big_endian = 1;
935   s->mem = (unsigned char*)malloc(MEM_SIZE);
936   memset(s->mem, 0, MEM_SIZE);
937   if(argc <= 1)
938   {
939      printf(" Usage: mlite file.exe\n");
940      printf(" mlite file.exe B {for big_endian}\n");
941      printf(" mlite file.exe L {for little_endian}\n");
942      printf(" mlite file.exe BD {disassemble big_endian}\n");
943      printf(" mlite file.exe LD {disassemble little_endian}\n");
944
945      return 0;
946   }
947   in = fopen(argv[1], "rb");
948   if(in == NULL)
949   {
950      printf("Can't open file %s!\n",argv[1]);
951      getch();
952      return(0);
953   }
954   bytes = fread(s->mem, 1, MEM_SIZE, in);
955   fclose(in);
956   memcpy(s->mem + 1024*1024, s->mem, 1024*1024); //internal 8KB SRAM
957   printf("Read %d bytes.\n", bytes);
958   cache_init();
959   if(argc == 3 && argv[2][0] == 'B')
960   {
961      printf("Big Endian\n");
962      s->big_endian = 1;
963   }
964   if(argc == 3 && argv[2][0] == 'L')
965   {
966      printf("Big Endian\n");
967      s->big_endian = 0;
968   }
969   s->processId = 0;
970   if(argc == 3 && argv[2][0] == 'S')
971   { /*make big endian*/
972      printf("Big Endian\n");
973      for(index = 0; index < bytes+3; index += 4)
974      {
975         *(unsigned int*)&s->mem[index] = htonl(*(unsigned int*)&s->mem[index]);
976      }
977      in = fopen("big.exe", "wb");
978      fwrite(s->mem, bytes, 1, in);
979      fclose(in);
980      return(0);
981   }
982   if(argc == 3 && argv[2][1] == 'D')
983   { /*dump image*/
984      for(index = 0; index < bytes; index += 4) {
985         s->pc = index;
986         cycle(s, 10);
987      }
988      free(s->mem);
989      return(0);
990   }
991   s->pc = 0x0;
992   index = mem_read(s, 4, 0);
993   if((index & 0xffffff00) == 0x3c1c1000)
994      s->pc = 0x10000000;
995   do_debug(s);
996   free(s->mem);
997   return(0);
998}
999
plasma/tools/ramimage.c
1/* ram_image.c by Steve Rhoads 11/7/05
2 * This program take the ram_xilinx.vhd file as input
3 * and the code.txt file as input.
4 * It then creates ram_image.vhd as output with the
5 * initialization vectors set to the contents of code.txt.
6 */
7#include <stdio.h>
8#include <stdlib.h>
9#include <string.h>
10
11#define BUF_SIZE (1024*1024)
12
13unsigned int swap_int (unsigned int data)
14{
15  unsigned char* b=(unsigned char*)&data;
16  unsigned char t;
17  t=b[3]; b[3]=b[0]; b[0]=t;
18  t=b[2]; b[2]=b[1]; b[1]=t;
19  return data;
20}
21
22
23
24int main(int argc, char *argv[])
25{
26   FILE *file;
27   int i, j, index, size, count;
28   char *buf, *ptr, *ptr_list[64*4], text[80];
29   unsigned int *code;
30
31   if(argc < 4)
32   {
33      printf("Usage: ram_image <in.vhd> <file.bin> <out.vhd>\n");
34      printf("Usage: ram_image ram_xilinx.vhd <file.bin> ram_image.vhd\n");
35      return 0;
36   }
37
38   buf = (char*)malloc(BUF_SIZE);
39   code = (unsigned int*)malloc(BUF_SIZE);
40
41   //Read ram_xilinx.vhd
42   file = fopen(argv[1], "rb");
43   if(file == NULL)
44   {
45      printf("Can't open %s!\n", argv[1]);
46      return -1;
47   }
48   size = fread(buf, 1, BUF_SIZE, file);
49   fclose(file);
50
51   //Read binary file
52   file = fopen(argv[2], "r");
53   if(file == NULL)
54   {
55      printf("Can't open %s!\n", argv[2]);
56      return -1;
57   }
58   for(count = 0; count < 16*1024; ++count)
59   {
60      if(feof(file))
61         break;
62      fread ( &code[count], 1, sizeof(unsigned int), file);
63   }
64   fclose(file);
65
66   //Find 'INIT_00 => X"'
67   ptr = buf;
68   for(i = 0; i < 64*4; ++i)
69   {
70      sprintf(text, "INIT_%2.2X => X\"", i % 64);
71      ptr = strstr(ptr, text);
72      if(ptr == NULL)
73      {
74         printf("ERROR: Can't find '%s' in file!\n", text);
75         return -1;
76      }
77      ptr_list[i] = ptr + strlen(text);
78   }
79
80   //Modify vhdl source code
81   //ptr_list[64*4] four banks of 64 bytes: Bank0 D31-D24 Bank1 D23-D16 Bank2 D15-D8 Bank3 D7-D0
82   j = 62;
83   for(i = 0; i < count; ++i)
84   {
85      sprintf(text, "%8.8x", swap_int(code[i]));
86      index = i / 32;
87      ptr_list[index][j] = text[0]; // Bank0 D31- D28
88      ptr_list[index][j+1] = text[1]; // Bank0 D27- D24
89      ptr_list[index+64][j] = text[2]; // Bank0 D23- D20
90      ptr_list[index+64][j+1] = text[3]; // Bank0 D19- D16
91      ptr_list[index+128][j] = text[4]; // Bank0 D15- D12
92      ptr_list[index+128][j+1] = text[5]; // Bank0 D11- D8
93      ptr_list[index+192][j] = text[6]; // Bank0 D7 - D4
94      ptr_list[index+192][j+1] = text[7]; // Bank0 D3 - D0
95      j -= 2;
96      if(j < 0)
97         j = 62;
98   }
99
100   //Write ram_image.vhd
101   file = fopen(argv[3], "wb");
102   if(file == NULL)
103   {
104      printf("Can't write %s!\n", argv[3]);
105      return -1;
106   }
107   fwrite(buf, 1, size, file);
108   fclose(file);
109   free(buf);
110   free(code);
111   return 0;
112}

Archive Download the corresponding diff file

Branches:
master



interactive