Forums - Open Redstone Engineers
DIO 2, my new CPU project - Printable Version

+- Forums - Open Redstone Engineers (https://forum.openredstone.org)
+-- Forum: ORE General (https://forum.openredstone.org/forum-39.html)
+--- Forum: Projects & Inventions (https://forum.openredstone.org/forum-19.html)
+---- Forum: In Progress (https://forum.openredstone.org/forum-20.html)
+---- Thread: DIO 2, my new CPU project (/thread-6002.html)



DIO 2, my new CPU project - Magic :^) - 03-18-2015

So I'm working properly on my next CPU. I've been humming and hawing for a while about what to actually include, but now I have a preliminary IS that I can post here:

(instruction names are expanded so they make more sense to read here)
Code:
regSelect [regA] [regB]
aluOp [regC]

portWrite [portNum] [pointerAddr]
portWrite [portNum] [pointerAddr] [immediate]
portWrite [portNum] [immAddr]
portWrite [portNum] [immAddr] [immediate]

portRead [portNum] [regC] [pointerAddr]
portRead [portNum] [regC] [immAddr]

interruptSet [interruptCode] [subroutineAddress]
interuptRemove [interruptCode]
enableInterrupts
disableInterrupts

contextSet [regContext] [aluFlagContext] [regSelContext]

jump [immAddr]
call [immAddr]
return
branchIf [condition] [immAddr]
branchIfNot [condition] [immAddr]

In a way I will still be using memory mapped locations. It's just that I'll use 3 of 11 bits as an immediate 'port' address so I don't have to deal with awkwardly sized 11-bit pointer registers

also aluOp is a placeholder name for all alu operations. I plan on providing support for all possible operations so the aluOp control bits will just be the ALU control lines. I have room in this instruction to do that, as all I'm sharing in this word is the register destination address.

The IS is based loosely on my previous CPU's IS. (DIO 1)
The biggest thing in common is the way I handle my dataloop. Instead of loading my registers to an A and B input for the dataloop, I lock the input register addresses with regSelect instruction. Basically it 'opens' the two selected registers so that when I write to a register I am also reading from, It will also update the ALU's input as the read of that register is still open.
It allows me to do code like this, assuming that there is a 1 stored in registers 001 and 010:
(The # and $ are macros I like to use for declaring and using address placeholders)
Code:
regSelect r001 r010
# loopStart
add r001
add r010
jump $loopStart

The above is a fully functional fibonacci program. Barring the checks for overflow of course.
As you can see, I only needed to load my registers once and after that I could treat the system as an accumulator setup.
Of course, you can accumulate to different registers simply by using regSelect again to use a different pair.

The IS isn't completely finished yet. There are a few more things I want to explore.

If you have any questions about what these instructions do, ask away :3

oh and the DIO stands for Derpy I/O, in honour of the posthumously named DIO 1


RE: DIO 2, my new CPU project - LordDecapo - 03-18-2015

Can't wait Mag Big Grin
just pray tuchi doesn't take the entire CPU as hostage lol!
I like the whole regSelect functionality, I want to program something with that to see how fluid it is.


RE: DIO 2, my new CPU project - Magic :^) - 03-18-2015

:3 It's a pretty cool way of handling registers imo, but it also means you can't have input buffers.
I'm using a 9 tick dataloop so there shouldn't be any problems there though.
What isn't mentioned in the IS is the amount of time the operations will take. I'm going for a VERY fast regSel instruction which will hopefully be 3-5 ticks.

Here's the port mappings I've come up with:
Code:
000: RAM
001: Stack
010: Pointers
011: immediate
100: Port 1
101: Port 2
110: Port 3
111: Port 4

I'm finding that the immediate port would be the best way to put imms in my dataloop. I could load imms like this using this setup:
(r=register, p=port, i=imm)
Code:
regSelect r000 r001
portRead p011 r000 i00000001
portRead p011 r001 i00000001
#loopStart
add r000
add r001
jump $loopStart
e.g. the imm port just takes what's normally used as the address immediate and sends it directly to the specified register.
(I did regSelect first, as it isn't dependent on the immediate loads. I'd recommend coding like this to take advantage of DIO 2's ability to execute different instructions simultaneously)

I had a spare port to mess with anyways, and I could still map a portWrite to a different location.
having a dedicated imm instruction would bloat my IS too much anyways. It is already getting pretty full.
(If I have space i may change this, as the portRead method with an imm is a double width instruction)


RE: DIO 2, my new CPU project - Magic :^) - 03-18-2015

Also here's a nice 16bit addition subroutine:

Code:
disableInterrupts

regSel r100 r101

add r111

branchIf Cout $enableCin

contextSet c100
add r111
jump $endFunc

#enableCin
contextSet c100
addC r111

#endFunc
contextSet c000
enableInterrupts

return

The dataloop that DIO 2 uses has context switchable registers from addresses 100 to 111
As illustrated above, you could use the context switch to hold two bytes of related information at the same address. Depending on how you use your registers in your program, you can theoretically hold 4 8-bit numbers and 4 16-bit numbers in the dataloop.

I will probably have a separate instruction to perform a context switch on the regSelect addresses. Doing this would allow passing arguments as two sets of register addresses to the dataloop and this opens a LOT of possibilities!


Actually I found another way to do the 16bit addition function. The above method is more linear, but the below method is a bit faster if there is no ripple between the two bytes:
Code:
disableInterrupts

regSel r100 r101

contextSet c100
add r111
contextSet c000
add r111

branchIfNot Cout $endFunc

contextSet c100
addC r111
contextSet c000

#endFunc
enableInterrupts

return
the penalty for a true 16bit addition is much higher, but if there is no ripple between the two bytes it is considerably faster.
It's a bit odd though as I add the top byte before the bottom byte xD

I will talk about the contextSet instruction in more detail later. I will also describe how the interrupt instructions will be used. I am heading off to London in like an hour and need to pack though, so I gotta go! :O


RE: DIO 2, my new CPU project - Magic :^) - 03-22-2015

I'm still working on the finer points of the IS. I'm looking particularily into more ways to memory map the io and also to see if I can do more with the context switching mechanics


RE: DIO 2, my new CPU project - LordDecapo - 03-23-2015

Nice! Very nice. A part of me wants to add back those kinda registers into iizr xD


RE: DIO 2, my new CPU project - Magic :^) - 03-24-2015

:3

Also to save me going back and editing everything behind me, I'll just post as I change the IS, and do complete documentation with progs using the final IS on a separate thread. That new thread may be done before or after I build the CPU. Probably before the build, as I'd like a solid blueprint to work off.


RE: DIO 2, my new CPU project - LordDecapo - 03-24-2015

Nice! Big Grin


RE: DIO 2, my new CPU project - Magic :^) - 03-25-2015

I'm going to compress the mapping for the immediate and pointer ports, so there is more room for other stuff and then the non-standard hardware for the port system will be all contained in one port Tongue
so:

there will be a special purpose port that is addressed, called x for now.
port x can be used like so:

- write a value to port x at an address y to store a pointer at pointer address y (this is done like writing to ram or any other port)

- read from port x to the dataloop from address y to a register (like reading from ram or any other port)

- write an immediate value to the dataloop by referencing port x


This looks complicated-ish, but it is basically designed so I can use the same instruction format as my port ops, to save IS space and to reduce as much extra hardware as possible.

The instructions will be abstracted in the assembly language so they would look like this:
Code:
imm [regC] [immediate]
pointerWrite [pointerAddr]
pointerRead [regC] [pointerAddr]

they are actually this though:
Code:
portRead [regC] [immediate]
portWrite [portAddress] [pointerAddress]
portRead [regC] [portAddress] [pointerAddress]



RE: DIO 2, my new CPU project - LordDecapo - 03-25-2015

What will that special port be used for? IO?


RE: DIO 2, my new CPU project - Magic :^) - 03-25-2015

that x port will just be handled differently by the hardware than the other ports.

it holds pointers and this port can also be used to pass immediates to the dataloop's registers.

It is a special port because of the above reasons, and also because it is the only port you can't point to with a pointer.
(no pointing to pointers)

and yeah, it is mostly going to be used for I/O stuff. This port will also be faster to access than main RAM though, so you could also use it like a small amount of "fast RAM"

I'm thinking of holding 8-16 pointer regs in this port. Probably 8 due to size constraints.
I may or may not add simple increment and decrement ops for the pointers. It would be really nice for iterating through arrays, but it is also a bit awkward to implement :/
I might use CCA based pointer registers?


I'll probably include the stack in this port aswell, as I only need 1 address location for that. It would also give you the bonus of being able to use the stack as a pointer Tongue


RE: DIO 2, my new CPU project - Magic :^) - 03-25-2015

eh so new port setup, with some empty spaces:
Code:
000: RAM
001: Special (pointers, stack, immediates)
010: ?
011: ?
100: Serial Port 0
101: Serial Port 1
110: Serial Port 2
111: Serial Port 3

any suggestions for the ?s or anything else?


RE: DIO 2, my new CPU project - Magic :^) - 04-02-2015

still ironing out the final form of my internal data busing. I'd love to be able to treat the dataloop as just another port location and allow data transfers between ports without going through the loop first, but... that may be hard.


RE: DIO 2, my new CPU project - LordDecapo - 04-02-2015

Not too hard, well at least in diagnal, not sure about vertical, try using a common data buss that only samples from the reg read, and writes to register via a different wire., (yay read enables!)