Jump to content

[0.90] ProgCom - CPU Emulator V0.11.1


SimplySimon

Recommended Posts

I thought I'd give an update on what I have been working on.

I have created a new system for adding hardware for ProgCom, which will be the backbone for all the hardware type stuff I add to the emulator. I have made some progress on moving over most of the current functionality over to the new system, the tape drive and data relating to orientation now use it, but there is still some things left to do, such as the display and the keyboard.

I have also been working on a compiler. Since I decided to go with reverse polish notation rather than infix notation the syntax is somewhat different from c/c-derived languages. Here's an example of the syntax as well as the equivalent statements in c:


def main : int {//int main(void)
int x y z;//int x, y, z;
x 2 =;//x = 2;
y 3 =;//y = 3;

z x y * =;//z = x * y;
x y z add2 $ =;//x = add2(y, z);

y x x + z z + * =;//y = (x+x)*(z+z);

int# pointer;//int* pointer;
pointer z@ =;//pointer = &z;
x pointer# =;//x = *pointer;
pointer x <-;//*pointer = x;

if x y <; {//if(x < y) {
while x y <; x++;//while(x < y) x++;
}

float f;//float f;
f z (float) =;//f = (float)z;

"Hello, World!" print$;//print("Hello, World!");

return 0;
}

def add2 int a b : int {//int add2(int a, int
return a b +;//return a + b;
}

def print char# string: {
asm string;
"push ra"
"call print_asm"
"pop ra"
;;
return;
}

It still needs a bit of work though, since it is quite buggy at the moment.

Other misc changes:

I moved the EX register into the range of registers addressable by normal operations. This made the ax, sx, bx and rdx instructions redundant and they have been removed.

The fp, sp, ra, ex, es, ea registers can no longer be accessed as r13, r14, r15, a13, a14 and a15. The only register that can be accessed by two names is r0, which can also be accessed as 'zero'.

I fixed the bootloader bug where the computer would not load a program if the tape was inserted after the computer was turned on.

The "serial interface" stuff that was used for the keyboard and the tape drive in the previous few versions has been removed in favor of the new hardware system.

I have updated the text printing library. The new version works a bit better.

Hopefully I can release the next update in a week or two, but given how large a rewrite this has turned out to be it could take longer.

Edited by SimplySimon
Link to comment
Share on other sites

...

I have also been working on a compiler.

...

A compiler is exactly what I need.

I used kOS till now, but it is too laggy with my "real-time" closed-loop control algorithms (though my PC is pretty powerful), so much that I had to stop including further refinements. And beyond that, kOS script language is not being developed to support even basic control flow program structures that would mean more efficiency.

Therefore, I will be waiting for your updated ProgCom.

Link to comment
Share on other sites

  • 4 weeks later...

I have updated progcom with the compiler and a bunch of other changes :). Most of the stuff is pretty behind-the-scenes, but there are quite a few visible changes too. I have not tested this as thoroughly as I probably should have so there might still be a few bugs in there, but as far as I can tell it works correctly. If anyone finds a bug or something that does not seem to work as the documentation says it should, please inform me and I'll try to fix it as soon as possible.

The issues I currently know about are:

The compiler:

* The &&, || and ^^ operators can produce the wrong value if you assign the result of the operation to a variable that was a part of the operation.

* The syntax for assigning an initial value to a global variable in inconsistent with the rest of the language (infix instead of postfix)

* Some error messages are not very helpful

* There is no way to specify what files need to be included in the source code yet

The assembler:

* If you include a file containing macros the macros might not get recognised properly, giving odd error messages.

* Some error messages are very vague, bordering on useless

The emulator:

* Some instructions seem to have strange execution times some of the time

I'm not sure if I've done a good job explaining the compiler in the documentation, so if anyone has any questions feel free to ask.

Link to comment
Share on other sites

Now I have no more excuses, I have to dust off my ASM skills :).

Impressive work. A lot of documentation with the download. Happy to see some example programs, really needed, and references. Lots of material to read carefully. And then try in practice.

EDIT: I would suggest to repack the files for ease while installing. Now the package installable files are nested in "ProgCom/GameData/Parts" and "ProgCom/GameData/Plugins"; if reversed in "GameData/ProgCom/Parts" and "GameData/ProgCom/Plugins" it would take just one step to install and have everything in order in its own subfolder (and, automatic mod installers would also work better).

Edited by diomedea
Link to comment
Share on other sites

Now I have no more excuses, I have to dust off my ASM skills :).

Impressive work. A lot of documentation with the download. Happy to see some example programs, really needed, and references. Lots of material to read carefully. And then try in practice.

EDIT: I would suggest to repack the files for ease while installing. Now the package installable files are nested in "ProgCom/GameData/Parts" and "ProgCom/GameData/Plugins"; if reversed in "GameData/ProgCom/Parts" and "GameData/ProgCom/Plugins" it would take just one step to install and have everything in order in its own subfolder (and, automatic mod installers would also work better).

I'm glad you like it :)

I have fixed the folder structure in the new version I just uploaded. I also fixed a bug regarding reading from the last 8 addresses in memory as well as clarified parts of the documentation.

Link to comment
Share on other sites

I found what could be an issue with the ProgCom IC part.

Unfortunately, I wasn't able to find exactly why. So, I can only report my finding, you probably know how to solve that.

I use A LOT of mods with KSP. One of those is Ferram's Aerospace Research (FAR). So, I use to check while in the VAB how a ship would handle with aerodynamics, thanks to the analysis system that FAR provides. So, I build a ship with the ProgCom IC, and now that FAR analysis doesn't work right any more. As soon as I take the ProgCOm IC out, FAR works fine as usual. In KSP debug window, the LOG shows a "NullReference Exception" everytime I run the analysis with ProgCom IC, instead of some nice data from FAR as it happens without the IC. Therefore, I am 100% sure this IC is responsible for this issue.

I tried to see if there was anything in the part.config file clearly out, but couldn't tell. I am sure you know better, so please check it.

Below, if that may come useful, is the excerpt from the log that appears everytime FAR can't complete the analysis.


NullReferenceException: Object reference not set to an instance of an object
at ferram4.FAREditorGUI.CalculateStabilityDerivs (Single u0, Single q, Single M, Single alpha, Single beta, Single phi) [0x00000] in <filename unknown>:0

at ferram4.FAREditorGUI.StabilityDerivativeGUI (Boolean tmp) [0x00000] in <filename unknown>:0

at ferram4.FAREditorGUI.ActualGUI (Int32 windowID) [0x00000] in <filename unknown>:0

at UnityEngine.GUILayout+LayoutedWindow.DoWindow (Int32 windowID) [0x00000] in <filename unknown>:0

at UnityEngine.GUI.CallWindowDelegate (UnityEngine.WindowFunction func, Int32 id, UnityEngine.GUISkin _skin, Int32 forceRect, Single width, Single height, UnityEngine.GUIStyle style) [0x00000] in <filename unknown>:0

Link to comment
Share on other sites

I found what could be an issue with the ProgCom IC part.

Unfortunately, I wasn't able to find exactly why. So, I can only report my finding, you probably know how to solve that.

I use A LOT of mods with KSP. One of those is Ferram's Aerospace Research (FAR). So, I use to check while in the VAB how a ship would handle with aerodynamics, thanks to the analysis system that FAR provides. So, I build a ship with the ProgCom IC, and now that FAR analysis doesn't work right any more. As soon as I take the ProgCOm IC out, FAR works fine as usual. In KSP debug window, the LOG shows a "NullReference Exception" everytime I run the analysis with ProgCom IC, instead of some nice data from FAR as it happens without the IC. Therefore, I am 100% sure this IC is responsible for this issue.

I tried to see if there was anything in the part.config file clearly out, but couldn't tell. I am sure you know better, so please check it.

Below, if that may come useful, is the excerpt from the log that appears everytime FAR can't complete the analysis.


NullReferenceException: Object reference not set to an instance of an object
at ferram4.FAREditorGUI.CalculateStabilityDerivs (Single u0, Single q, Single M, Single alpha, Single beta, Single phi) [0x00000] in <filename unknown>:0

at ferram4.FAREditorGUI.StabilityDerivativeGUI (Boolean tmp) [0x00000] in <filename unknown>:0

at ferram4.FAREditorGUI.ActualGUI (Int32 windowID) [0x00000] in <filename unknown>:0

at UnityEngine.GUILayout+LayoutedWindow.DoWindow (Int32 windowID) [0x00000] in <filename unknown>:0

at UnityEngine.GUI.CallWindowDelegate (UnityEngine.WindowFunction func, Int32 id, UnityEngine.GUISkin _skin, Int32 forceRect, Single width, Single height, UnityEngine.GUIStyle style) [0x00000] in <filename unknown>:0

I think I've found the problem, apparently the game doesn't like it when you try to activate fly-by-wire functions in the VAB. I have disabled that and will upload an update later today.

Edited by SimplySimon
Link to comment
Share on other sites

  • 4 months later...

Hello everyone! I have been busy for a while, but since I now have some time on my hands I thought I'd start updating ProgCom again :)

This version is mostly bug fixes, though it is fixes for fairly major issues:

* The &&, ^^ and || operators in the compiler should now be working

* I fixed a bug that would occasionally arise when calling functions in the compiler

* The assembler was generating the wrong opcode for the inti instruction, this has been fixed

* The monitor was taking too much processing time, it has now been optimised

* The tape drive had a few bugs with writing data to the tape, these have now been resolved.

* The BUSY flag of the tape drive status register now behaves a bit more consistently

* Various smaller fixes

Link to comment
Share on other sites

  • 1 month later...

This mod needs so much more love :o

I started on a pretty basic drawing library but ran into issues when trying to write an absolute value function. Is there something wrong with the shift right arithmetic instructions or am I just tired? :D

This has been fun to mess around with. Haven't done any assembly since my class last Fall and I've never implemented stuff like Bresenham's algorithms in any language regardless.

Link to comment
Share on other sites

Looked again today. Looks like the bl and ble instructions don't work for negative integers. Is this a bug or by design? Undocumented regardless (afaik).

.text

#include libText.txt

#global main

main:

movi r1, -5 ; r1 = -5

movi r2, 7 ; r2 = 7

bl r1, r2, less ; if (r1 < r2) goto: less

movi r1, 70 ; r1 = F alse

call putChar ; Print

halt ; Halt

less:

movi r1, 84 ; r1 = T rue

call putChar ; Print

halt ; Halt

Should print T, prints F. Changing -5 to 5 will print True.

Link to comment
Share on other sites

Looked again today. Looks like the bl and ble instructions don't work for negative integers. Is this a bug or by design? Undocumented regardless (afaik).

.text

#include libText.txt

#global main

main:

movi r1, -5 ; r1 = -5

movi r2, 7 ; r2 = 7

bl r1, r2, less ; if (r1 < r2) goto: less

movi r1, 70 ; r1 = F alse

call putChar ; Print

halt ; Halt

less:

movi r1, 84 ; r1 = T rue

call putChar ; Print

halt ; Halt

Should print T, prints F. Changing -5 to 5 will print True.

Hi, sorry for the late reply!

As far as I can tell bl and ble should work with negative integers, however "movi r1, -5" will not do what you expect. movi puts a 16-bit value in the specified register, so while the instruction will gladly accept the value -5, it will in fact put the value 65531 in r1. The workaround for this currently is to use "subi r1, r0, 5", which will subtract 5 from r0, which is always 0, and thus put the right value in r1. I think I might need to document this behavior better.

I'm glad you like the mod :)

Edited by SimplySimon
Link to comment
Share on other sites

Hey thanks a bunch for the reply. That seemed to help quite a bit. I've now implemented a few routines for a drawing library (drawPixel, fillScreen, clearScreen, and drawLine). drawLine is not really finished unfortunately. Seems to fail horribly with positive slope among others hehe.

http://pastebin.com/Nj09Cm73 - There's my drawing library libDraw.

http://i.imgur.com/1WLXaKy.png - There's an example of it in action.

http://pastebin.com/BWuwLGSd - The code for that image.

It has a very very long way to go (and its not even remotely optimized) but I'm pretty stoked for it to draw lines :D

If you have some free time and can figure out why it bombs out on certain coordinates let me know. The template algorithm pseudocode I used can be found here: http://en.wikipedia.org/wiki?title=Talk:Bresenham%27s_line_algorithm#General_Line_drawing_algorithm I'm sure it has something to do with a poorly written branch :D

Link to comment
Share on other sites

Hey thanks a bunch for the reply. That seemed to help quite a bit. I've now implemented a few routines for a drawing library (drawPixel, fillScreen, clearScreen, and drawLine). drawLine is not really finished unfortunately. Seems to fail horribly with positive slope among others hehe.

http://pastebin.com/Nj09Cm73 - There's my drawing library libDraw.

http://i.imgur.com/1WLXaKy.png - There's an example of it in action.

http://pastebin.com/BWuwLGSd - The code for that image.

It has a very very long way to go (and its not even remotely optimized) but I'm pretty stoked for it to draw lines :D

If you have some free time and can figure out why it bombs out on certain coordinates let me know. The template algorithm pseudocode I used can be found here: http://en.wikipedia.org/wiki?title=Talk:Bresenham%27s_line_algorithm#General_Line_drawing_algorithm I'm sure it has something to do with a poorly written branch :D

Cool stuff! I took a look at the code, and I think I got it to work.

The problem is that instead of "subi a7/a8, r0, 1" you have written "subi a7/a8, a0, 1". a0 is used by the bootloader to store the start address of the program, so it will not contain 0 when the program starts.

Here's the function I used to test the changes:


.text
#include libText.txt
#include libDraw.txt

#global main
main:
mov fp, sp
addi sp, sp, 8
movi r1, 128
movi r2, 8
initLoop:
subi r2, r2, 1
wrr r1, fp, r2
bne r2, r0, initLoop
mainLoop:
call clearScreen

;draw a square
rd r1, fp, 0
rd r2, fp, 1
rd r3, fp, 2
rd r4, fp, 3
call drawLine

rd r1, fp, 2
rd r2, fp, 3
rd r3, fp, 4
rd r4, fp, 5
call drawLine

rd r1, fp, 4
rd r2, fp, 5
rd r3, fp, 6
rd r4, fp, 7
call drawLine

rd r1, fp, 6
rd r2, fp, 7
rd r3, fp, 0
rd r4, fp, 1
call drawLine


;draw inner square
rd r1, fp, 0
rd r2, fp, 1
rd r3, fp, 2
rd r4, fp, 3
add r1, r1, r3
sri r1, r1, 1
add r2, r2, r4
sri r2, r2, 1

rd r3, fp, 2
rd r4, fp, 3
rd r5, fp, 4
rd r6, fp, 5
add r3, r3, r5
sri r3, r3, 1
add r4, r4, r6
sri r4, r4, 1
call drawLine

rd r1, fp, 2
rd r2, fp, 3
rd r3, fp, 4
rd r4, fp, 5
add r1, r1, r3
sri r1, r1, 1
add r2, r2, r4
sri r2, r2, 1

rd r3, fp, 4
rd r4, fp, 5
rd r5, fp, 6
rd r6, fp, 7
add r3, r3, r5
sri r3, r3, 1
add r4, r4, r6
sri r4, r4, 1
call drawLine

rd r1, fp, 4
rd r2, fp, 5
rd r3, fp, 6
rd r4, fp, 7
add r1, r1, r3
sri r1, r1, 1
add r2, r2, r4
sri r2, r2, 1

rd r3, fp, 6
rd r4, fp, 7
rd r5, fp, 0
rd r6, fp, 1
add r3, r3, r5
sri r3, r3, 1
add r4, r4, r6
sri r4, r4, 1
call drawLine

rd r1, fp, 6
rd r2, fp, 7
rd r3, fp, 0
rd r4, fp, 1
add r1, r1, r3
sri r1, r1, 1
add r2, r2, r4
sri r2, r2, 1

rd r3, fp, 0
rd r4, fp, 1
rd r5, fp, 2
rd r6, fp, 3
add r3, r3, r5
sri r3, r3, 1
add r4, r4, r6
sri r4, r4, 1
call drawLine

rd r1, fp, 0
addi r1, r1, 7
andi r1, r1, 255
wr r1, fp, 0
rd r1, fp, 1
addi r1, r1, 5
andi r1, r1, 255
wr r1, fp, 1

rd r1, fp, 2
addi r1, r1, 5
andi r1, r1, 255
wr r1, fp, 2
rd r1, fp, 3
subi r1, r1, 7
andi r1, r1, 255
wr r1, fp, 3

rd r1, fp, 4
subi r1, r1, 7
andi r1, r1, 255
wr r1, fp, 4
rd r1, fp, 5
subi r1, r1, 5
andi r1, r1, 255
wr r1, fp, 5

rd r1, fp, 6
subi r1, r1, 5
andi r1, r1, 255
wr r1, fp, 6
rd r1, fp, 7
addi r1, r1, 7
andi r1, r1, 255
wr r1, fp, 7

rd r5, r0, GLOBAL_NUMPAD_OUT
addi r5, r5, 1
wr r5, r0, GLOBAL_NUMPAD_OUT

movi r6, 15000
delayLoop:
subi r6, r6, 1
bne r6, r0, delayLoop

br mainLoop
halt

Some other minor stuff I noticed:

* in the drawPixel function you have the instruction "mov r0, r3" which will try to put the value of r3 into r0, not the other way around.

* You seem to have a third condition in the line drawing code, but I think that part should add offsetX/offsetY to x/y instead of constant 1. I might be wrong though. Either way it does not seem to be needed, I commented it out and the code worked anyway.

* Your line drawing function does not follow the example code calling convention, although it is up to you if you want to follow that or not.

Link to comment
Share on other sites

Cool stuff! I took a look at the code, and I think I got it to work.

The problem is that instead of "subi a7/a8, r0, 1" you have written "subi a7/a8, a0, 1". a0 is used by the bootloader to store the start address of the program, so it will not contain 0 when the program starts.

Some other minor stuff I noticed:

* in the drawPixel function you have the instruction "mov r0, r3" which will try to put the value of r3 into r0, not the other way around.

* You seem to have a third condition in the line drawing code, but I think that part should add offsetX/offsetY to x/y instead of constant 1. I might be wrong though. Either way it does not seem to be needed, I commented it out and the code worked anyway.

* Your line drawing function does not follow the example code calling convention, although it is up to you if you want to follow that or not.

Hey thanks a bunch! After awhile r and a start to look the same :)

I went ahead and replaced all the muls/divs with shifts as well as hopefully made it compliant to your calling conventions. Also removed some unnecessary code. That third condition was one such, suggested as being needed on that talk page but it isnt. That drawPixel mov is also unnecessary and has been removed.

You've been a huge help. I'm still not sure what I will actually do with any of this but it's been fun nonetheless. :D

Updated libDraw with some changes/optimizations. A call to initializeDraw is now required at the beginning to set the display mode. Not sure if I'll keep it this way but I wanted to move that out of clearScreen for performance reasons.

Added circles. Wohoo. Slightly modified your drawing test.

libDraw.txt - http://pastebin.com/jth4Bi4a

drawTest.txt - http://pastebin.com/jYvD6cjE

Edited by mjsmith
Link to comment
Share on other sites

Hey thanks a bunch! After awhile r and a start to look the same :)

I went ahead and replaced all the muls/divs with shifts as well as hopefully made it compliant to your calling conventions. Also removed some unnecessary code. That third condition was one such, suggested as being needed on that talk page but it isnt. That drawPixel mov is also unnecessary and has been removed.

You've been a huge help. I'm still not sure what I will actually do with any of this but it's been fun nonetheless. :D

Updated libDraw with some changes/optimizations. A call to initializeDraw is now required at the beginning to set the display mode. Not sure if I'll keep it this way but I wanted to move that out of clearScreen for performance reasons.

Added circles. Wohoo. Slightly modified your drawing test.

libDraw.txt - http://pastebin.com/jth4Bi4a

drawTest.txt - http://pastebin.com/jYvD6cjE

Neato! Glad I could help :)

Also, I thought I'd give an update on what I've been working on for the next version:

* Expanded instruction set: more comparison instructions, bit manipulation stuff and logical and/or instructions

* Hardware support for text/bitmap scrolling

* Some minor improvements to the text printing library

* A BASIC interpreter

* A simple operating system

Link to comment
Share on other sites

Neato! Glad I could help :)

Also, I thought I'd give an update on what I've been working on for the next version:

* Expanded instruction set: more comparison instructions, bit manipulation stuff and logical and/or instructions

* Hardware support for text/bitmap scrolling

* Some minor improvements to the text printing library

* A BASIC interpreter

* A simple operating system

Sounds awesome. I'd love to see the simple os (minix based?). Also as somewhat of a feature request, maybe page flipping if feasible. I implemented double buffering and while it works pretty well, there's definitely a performance hit :D

Also on that note, I had my back buffer mapped to a memory address range that should be way out of bounds (138265). I thought the max address (as defined in libLabel) is 65535 or am I missing something? Not sure how I came up with that address either.

Link to comment
Share on other sites

Sounds awesome. I'd love to see the simple os (minix based?). Also as somewhat of a feature request, maybe page flipping if feasible. I implemented double buffering and while it works pretty well, there's definitely a performance hit :D

Also on that note, I had my back buffer mapped to a memory address range that should be way out of bounds (138265). I thought the max address (as defined in libLabel) is 65535 or am I missing something? Not sure how I came up with that address either.

Simple might have been the wrong word to describe the OS, rudimentary might be better. It's basically an interrupt handler with some task switching and IO functionality attached. It's not really based on anything.

Page flipping could be implemented, but it would require me to double the memory attached to the monitor, which I'm hesitant to do for various reasons. It would be very simple to implement however, so I might do it anyway. Regarding the performance hit, some of that might come from the memory access times being calculated badly. Currently writing to cacheable memory (ie memory that does not share a cache line with a memory mapped hardware device) can be a lot slower for random access than writing to uncacheable memory (random access to the monitor is currently about 3x faster than an offscreen buffer). This will be fixed in the next update. I'm also considering increasing the clock rate again, but I'm less sure about that.

Regarding that address range: when reading from memory, only the lowest 16 bits of the address are considered. Therefore 138265 is treated the same as 7193. So 65535 is the highest address you can read from in memory, if you try to read one address past it you will end up reading from address 0.

Link to comment
Share on other sites

  • 7 months later...
Simple might have been the wrong word to describe the OS, rudimentary might be better. It's basically an interrupt handler with some task switching and IO functionality attached. It's not really based on anything.

Page flipping could be implemented, but it would require me to double the memory attached to the monitor, which I'm hesitant to do for various reasons. It would be very simple to implement however, so I might do it anyway. Regarding the performance hit, some of that might come from the memory access times being calculated badly. Currently writing to cacheable memory (ie memory that does not share a cache line with a memory mapped hardware device) can be a lot slower for random access than writing to uncacheable memory (random access to the monitor is currently about 3x faster than an offscreen buffer). This will be fixed in the next update. I'm also considering increasing the clock rate again, but I'm less sure about that.

Regarding that address range: when reading from memory, only the lowest 16 bits of the address are considered. Therefore 138265 is treated the same as 7193. So 65535 is the highest address you can read from in memory, if you try to read one address past it you will end up reading from address 0.

Fell off the map here. Busy busy. Currently taking an operating systems class for college and was wondering how your progress on this and progcom has been? Thinking about making a simple OS myself given enough time (i.e. Summer).

Its been quite awhile since I looked at the docs for progcom so I can't remember the major limitations but hopefully it would be preemptive not cooperatively driven. Like you described, interrupt handler, dispatcher/scheduler and maybe some i/o routines would be the goal.

*edit*

Did some basic investigation. I think this would be exceedingly time consuming without struct support in the compiler. Also I couldn't find documentation on if it supported macros or not (I know the assembler does). For now I might just start by seeing if I can add struct support. Then move onto writing a simple malloc/free.

*edit2*

Added extremely rudamentary and incomplete struct support. It's basically variable renaming at this point. No global support, no pointer support or member pointer support. Probably numerous other limitations and will need a proper redo (a bit more comfortable with the compiler layout now). Fork here: https://github.com/mjsmith707/KSPCompiler

Edited by mjsmith
Link to comment
Share on other sites

Fell off the map here. Busy busy. Currently taking an operating systems class for college and was wondering how your progress on this and progcom has been? Thinking about making a simple OS myself given enough time (i.e. Summer).

Its been quite awhile since I looked at the docs for progcom so I can't remember the major limitations but hopefully it would be preemptive not cooperatively driven. Like you described, interrupt handler, dispatcher/scheduler and maybe some i/o routines would be the goal.

*edit*

Did some basic investigation. I think this would be exceedingly time consuming without struct support in the compiler. Also I couldn't find documentation on if it supported macros or not (I know the assembler does). For now I might just start by seeing if I can add struct support. Then move onto writing a simple malloc/free.

*edit2*

Added extremely rudamentary and incomplete struct support. It's basically variable renaming at this point. No global support, no pointer support or member pointer support. Probably numerous other limitations and will need a proper redo (a bit more comfortable with the compiler layout now). Fork here: https://github.com/mjsmith707/KSPCompiler

I got a bit busy too, and haven't worked on progcom for a while.

Preemptive multitasking, as long as I've understood it correctly, is possible. There is a timer that can generate interrupts at certain intervals, so you can use that to switch tasks regularly. Of course, there is nothing keeping a task from stopping the timer, so any multitasking support is always going to be a bit odd.

I was more-or-less done with the operating system. The major problem was the file system, which was tricky to get running properly. There were also some minor issues with how stack space for new threads was going to be allocated (I had no good solution) and I still needed to make sure that the floating point stack state got saved in the interrupt manager.

I also did some improvements to the emulator: extended functionality for the monitor, GUI for the tape drive and some minor improvements I can't remember. I don't think I ever got around to testing them properly though.

I'll probably finish up what I've done so far and release it at some point.

Nice job implementing structs :) I hadn't thought of that way of doing it before.

Although since the compiler is basically a pile of hacks a proper implementation of structs might need a fairly major rewrite. For instance, currently all parameters to a function are passed in registers, so there is a maximum limit of 16 primitive-type parameters. A struct can grow larger than 16 words, and one would reasonably expect to be able to pass a copy to a function. Thus a rewrite of the calling convention would probably be needed. Also, there is currently no robust type system and various points of the compiler assumes that all variables are 1 word long and are of one of four types (int, float, char, pointer). For instance, if you add one to a pointer to a struct you'd probably expect the compiler to add sizeof(struct) instead, so that if the pointer was pointing to an array it'd now be pointing to the next entry, but that doesn't happen at the moment.

Link to comment
Share on other sites

Thanks for the reply and I'd love to see the operating system. My original simple OS idea was something far more hardcoded. That is, every task was predefined, not dynamically loaded etc. It would have a hardcoded limit of something like 4 tasks and would switch on them. This way their program locations, state information, stacks etc. would all be known at compile time. Basically it would be an operating system from the 1940s lol. Yours sounds far more sophisticated.

The compiler design definitely seemed a bit odd but I can't blame you for that. See: https://github.com/mjsmith707/InterpretedCPU/tree/master/Assembler/Assembler for a single night assembler implementation of dubious quality :D. Shortly after working on yours I realized how much modification would probably be needed to properly implement structs and others. I'll probably revisit writing code for ProgCom when I've got some free time but I am highly allergic to large project assembly programming lol so instead of focusing on my weak point (compiler design) I decided to focus on something I'm a bit more comfortable with:

A MIPS32R2 emulator. Only been working on it for about 3 days now but it supports (albeit unverified, needs unit testing) roughly 65% of the ISA. It is about the most basic of designs at this point. A directly interpreted, single-cycle, non-pipelined, non-caching implementation. It can however decode and execute mips32r2 machine code (testing with GCC cross-compiler) so it's off to a good start in that respect. I'm planning on implementing the coprocessor0 stuff in the near future and then interrupts. Both of those should be relatively easy. A proper MMU implementation will likely be a bit more difficult but I'll get to that, floating point and some basic device emulation later.

The ultimate goal is full compatibility but I'd settle for just getting very very early Linux or NetBSD boot output as validation. Performance will certainly be lousy as its directly interpreted but as long as it's good enough to target with GCC I'll be happy. It's being written in C# (for eventual implementation as a KSP plugin) and all help is welcome if you're interested. I'm using Xamarin and dumped the whole project on it. https://github.com/mjsmith707/Standalone_MIPS_Emulator

Edited by mjsmith
Link to comment
Share on other sites

Thanks for the reply and I'd love to see the operating system. My original simple OS idea was something far more hardcoded. That is, every task was predefined, not dynamically loaded etc. It would have a hardcoded limit of something like 4 tasks and would switch on them. This way their program locations, state information, stacks etc. would all be known at compile time. Basically it would be an operating system from the 1940s lol. Yours sounds far more sophisticated.

The compiler design definitely seemed a bit odd but I can't blame you for that. See: https://github.com/mjsmith707/InterpretedCPU/tree/master/Assembler/Assembler for a single night assembler implementation of dubious quality :D. Shortly after working on yours I realized how much modification would probably be needed to properly implement structs and others. I'll probably revisit writing code for ProgCom when I've got some free time but I am highly allergic to large project assembly programming lol so instead of focusing on my weak point (compiler design) I decided to focus on something I'm a bit more comfortable with:

A MIPS32R2 emulator. Only been working on it for about 3 days now but it supports (albeit unverified, needs unit testing) roughly 65% of the ISA. It is about the most basic of designs at this point. A directly interpreted, single-cycle, non-pipelined, non-caching implementation. It can however decode and execute mips32r2 machine code (testing with GCC cross-compiler) so it's off to a good start in that respect. I'm planning on implementing the coprocessor0 stuff in the near future and then interrupts. Both of those should be relatively easy. A proper MMU implementation will likely be a bit more difficult but I'll get to that, floating point and some basic device emulation later.

The ultimate goal is full compatibility but I'd settle for just getting very very early Linux or NetBSD boot output as validation. Performance will certainly be lousy as its directly interpreted but as long as it's good enough to target with GCC I'll be happy. It's being written in C# (for eventual implementation as a KSP plugin) and all help is welcome if you're interested. I'm using Xamarin and dumped the whole project on it. https://github.com/mjsmith707/Standalone_MIPS_Emulator

I have uploaded the operating system with the latest update. It is not very sophisticated, it can basically only run one program at a time(though you can have many threads in that program) since there is no memory management stuff that ensures you don't try to load two programs into the same area of memory. You can also not give any starting parameters to a new process. Lots of other restrictions and missing features. I cut out most of the file system stuff since it wasn't working, it currently works for loading programs, but I'm not sure if it works for anything else.

You'll find the OS source in the compiler folder.

How to use it:

1: compile the os.pcc file into os.asm

2: copy os.asm and osasm.asm into the progCom code directory

3: assemble the osasm.asm file with "asm osasm.asm"

4: due to the new tape drive interface you need to open the "TAP" interface, enter "osasm.pct" into the lower text box and press load

5: operating system is up and running

If you want to use the basic interpreter, which is the only program that takes advantage of the operating system:

6: compile the basic.pcc file into basic.asm

7: copy the file to the progcom code directory

8: assemble the file with "asm basic.asm 6000" in order to set the program to start at address 6000, the lowest address the OS will permit a program to start at

9: Press "eject" on the "TAP" interface

10: load the assembled file the same way as the OS. Filename should be "basic.pct".

11: in order for the OS to load the program the tape needs to be formatted, open the keyboard and press enter to avoid a bug, then enter "format" and press enter again.

12: when prompted whether you want to keep the executable or not, type "y"

13: Optional Step: Type "list" and enter to see the files that are now on the tape. "boot" should be the only file there.

14: when the tape is formatted type "boot" and press enter into the keyboard.

15: you should now be able to use the basic interpreter, you can test this with the following program: PRINT "Hello, World!\n\r"

There is a bug with the interpreter that causes the program to crash if you type "10 IF (A/B)*B = A PRINT 11", just fyi. I have no idea what causes it.

Yeah, the compiler is pretty bad. It suffers from not being thought through enough beforehand, being hastily implemented and being the first (working) high[er]-level compiler I've written. I also didn't really do a whole lot of research on how to code one, so it was mostly improvisation the whole way through. In the latest patch I added some very basic optimisations though so it should at least generate slightly more optimal code now.

Your project sounds very interesting. :) I don't have any time to work on it right now though, but thanks for the offer. If you get around to implementing it in ksp, feel free to borrow any code from progCom if you can find anything that is of use.

Changes in the new version:

*Added a 4 color character mode for the monitor, as well as a 4-bit CLUT bitmap mode, 8-bit color monochrome bitmap mode, and a 16-bit color bitmap mode. You can also adjust the resolution of the monitor between 256x256, 128x256, 128x128 and 64x64 pixels now. I have only written rudimentary documentation for this yet though, will do that later. The old modes should still be usable, but since I expanded the screen ram to 4096 words instead of 2048 all older programs will need a recompile.

*Added more instructions for boolean arithmetic, bit twiddling, and some other things I forget.

*added the OS and BASIC interpreter I have been talking about

*Added A GUI for the tape drive, programs are now loaded by entering "tapeName.pct" into the lower text field of the "TAP" interface and pressing "load". If a tape is already in the tape drive, you need to press "eject" first. If you want to save the changes made to a tape, press "save". If you want to inster an empty tape, press the button called "new" or something like that.

Many of the new features are poorly documented since I wanted to release this update asap, and writing documentation is time consuming. I will do a pass on the documentation later. No previous features have been changed though (aside from how programs are loaded, see changelog above) so the current documentation should work just fine for most use cases. If anyone has any questions regarding how to use the new features, or about ProgCom in general, feel free to ask in this thread.

Edited by SimplySimon
Link to comment
Share on other sites

This thread is quite old. Please consider starting a new thread rather than reviving this one.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...