Running a real OS

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Running a real OS

pm100
Having got an FPGA version of HACK up and running I was conducting thought experiments about what would be needed to allow HACK to run a light weight OS.
- run multiple programs
- a basic shell
.....

Missing things
- memory protection and address space expansion. Probably simple to allow each process a private 64k
- interrupts - otherwise a hard looping program cannot be stopped
- some concept of privilege level
- somehow allow writing to the instruction area

The challenge is fitting this into the HACK CPU model
- one clock cycle = one instruction
- only 2 spare instruction bits (plus some 'forbidden' combinations of existing bits that could be hijacked)

Another really needed think is byte addressability, dealing with IO buffers otherwise would be terrible. Or at least a right shift (by 8?) operation
Reply | Threaded
Open this post in threaded view
|

Re: Running a real OS

dolomiti7
Nice ideas. I have experimented myself a bit with an extended ISA. Here are some of my thoughts:

The number of possible additional instructions is not that small: 3*2^13=24,576 (100, 101, 110 prefixes) - not taking into account the unspecified ALU combinations, which would complicate the decoding significantly. If that is not enough, you can go with variable instruction length and use one or more bits of your new ISA to indicate instructions consisting of more then one 16-bit word.

I'm not sure why the one instruction per cycle should be a requirement. In fact, if you implement the memory with an SDRAM controller, this will be hard to maintain. Even if the internal memory blocks of the FPGA are large enough to hold the whole ROM, RAM and VRAM, you will run into issues here:
  AM=M+1
  D=M
(You need to write the ALU value from M+1 to the "old" address of A while the next read cycle requires the new address). Unless you add complex write-back caches this will likely and frequently result in a wait-state. I don't see a problem here, though.

The most relevant hardware extension from my perspective would be a simple interrupt process and some timing information (i.e. a memory-mapped cycle-count or a hardware clock). For an interrupt driven mechanism, the CPU would need to add functionality to save the state (interrupting to a handler at a certain system-defined address will change the program counter). The old PC must be saved somewhere. Same applies at least to the A-register, because it cannot be saved by the interrupt handler without destroying A or D. The best would probably be to keep them inside the CPU in separate registers until some IRET instruction is executed. Or you go for a micro-coded approach and push everything to the stack.
To run multiple programs, this is not required though in theory, if you go for cooperative multitasking and/or a software-based approach (assuming that the memory is sufficient for all programs...) A purely OS-based idea to implement this could be to extend the convention of your OS so that every routine of the Hack OS will call a (assembler-coded) task-manager routine before returning which updates an internal counter and after a threshold has been reached switches to another task (switching the context, specifically maintaining different stacks). This requires that programs need to ensure that they call OS routines frequently - though I guess that is very likely the case anyway since even multiplication will result in such a call.

Memory protection and more addressable space is probably best to be solved with some kind of bank switching mechanism. Making the instruction are writable (RAM) would make the Hack computer more of a Von-Neumann-Architecture instead of Harvard. That's nice to have, but not absolutely necessary. If you stick to 32k x 16-bit for "ROM" and RAM, you could address the ROM by using bit 15 (requiring 2 Hack instructions to load A though). To bypass the Harvard-Architecture restrictions, you could also just implement an interpreter/emulator in the ROM, that executes code from the RAM. I have implemented a simple BASIC interpreter which effectively does that.

Byte addressability and lack of shift routines are indeed a bit nasty, but couldn't you map individual bytes from I/O devices to different addresses, just wasting the upper 8 bits for each?

If you are thinking about extending the ISA anyway, how about hardware commands for MUL/DIV, SHL/SHR and also adding some hardware registers? I did that with a simple micro-coded approach - slow, but working; similar to the 70s/80s CPUs like the 8088.

Or you go directly for RISC-V ;-)
Reply | Threaded
Open this post in threaded view
|

Re: Running a real OS

pm100

#1 space for more instructions.

I totally forgot that I can remap the meanings of all the instruction bits by switching the 2 spare bits.

So for example one could say that the 3 jump bits only mean jump condition if spare = b11.

#2 one instruction per cycle

wait states are fine. What I mean is no microcoding, no complex sequencing instructions. This precludes a hardware stack for example, JSR instructions, saving of state on interrupt. Looking at 6502 for example (a nice simple cpu) instruction take from 1 to 5 cycles

Going to a multi cycle instruction set goes against the spirit of HACK machine. Simple instructions executed in one logical cycle.

So interupt would need to have dedicated save registers, oldpc, olda, oldd. Then ISR needs to save them somewhere and restore A and D and jump to old pc . That jump would new a new instruction 'jump to oldpc'
 
#3 memory
Yes bank switching works fine. Its the fine detail that will bite

Need to think about you io thoughts