This project was my honors project for CSE330 (Computer Organization and Architecture) in Spring of 1999.
I chose to do this project because I am interested in compiler technology. I am also interested in artificial intelligence, and I see this system as a potential coding mechanism for independent AI creatures running around in a virtual world. Although I named this project "EPIC", I do not believe this code is the wave of the future, I just like the name. It is probable that something related out there has the same or similar name, although I do not currently know of any. No infringement is intended.
Since the source code is compiled before executed (and not interpreted), the code executed is naturally more compact than the original source code. Besides being more compact, it will probably also be more efficient when executed. For example, an interpreter that runs directly off the source code would probably have to do an expensive lookup anytime it encounters a symbol. In EPIC, a reference to a symbol will be compiled into the binary integer the symbol represents.
EPIC supports multiple threads in virtual hardware. When a thread is started, its memory access can be restricted to a specified range. The thread can not change its memory access. Therefore, if it goes haywire, it can not crash the entire system. The main thread (#1) has unrestricted access to memory. In my current design, all threads have read access to all memory, but write access can be restricted.
What is the Instruction Code?
For simplicity, I decided to use one-byte opcodes and one-byte register indexes. This allows a great deal of extensibility. This also allows me to start by using only ASCII opcodes and ASCII register indexes.
This is the instruction format:
|Opcode||str1||str2||str3||str4||(Anything else on the line is ignored.)|
If opcode = semicolon, then that line is considered a comment and is ignored by the compiler. Not all opcodes use each str argument, so often, some these will be optional.
Here are some instructions:
|; anything at all||Lines beginning with a semicolon are comments.|
|lw regDest regA regB label32||regDest := mem[label32 + regA + regB]|
|sw regSrc regA regB label32||mem[label32 + regA + regB] := regSrc|
|add reg1 reg2 reg3||reg1 := reg2 + reg3|
|addd reg1 reg2 reg3 int32||reg1 := reg2 + reg3 + int32|
|org int32||The compiler continues compiling at mem[int32].|
|label string1||The symbol string1 is associated with the current program counter.|
|cpudump||The contents of memory and register file #1 are dumped to a file named "CPU_DumpN.txt" where N is the current PC value.|
|cpuhalt||This halts the CPU.|
|jge reg1 reg2 label32||If reg1 is greater than or equal to reg2, then PC is set to the value represented by label32.|
|j label32||PC is set to the value represented by label32|
|thread_start regDest regAND regOR label32||regDest := Thread ID of newly created thread. If no thread could be created,
then regDest := 0.
A new thread will be started with:
PC = label32
reg[AND_Reg] := regAND
reg[OR_Reg] := regOR
|thread_stop regSrc||If regSrc = = 0, then the current thread is stopped, otherwise if the current thread is the main thread, then the thread with ID = reg[regSrc] is stopped.|
|spy regDest regThreadID reg2get||The value of reg2get of the thread with an ID of the value in regThreadID is copied into regDest of the current thread.|
|call label32||The current value of the PC register (for the current thread) is saved in the 'R' register. It is then set to the value of label32.|
|return||The PC register is set to the value in the 'R' register.|
Integrated Development Environment
Here is a screenshot of the IDE:
The simulator executes the code. To monitor the execution of each thread, though, the simulator plots the 'x' and 'y' registers of EACH thread and plots them on the screen. Each thread is plot in a different color. Here is a screenshot of the simulator:
Copyright 1999-2006 by Walton Dell