# Napia Napia Specifications, Revised 2021.11.30. ## About Welcome to Napia! This is a virtual computing system I'm implementing to serve my needs going forward. It draws from my earlier systems (Maunga, Ngaro, Nga), adding in additional functionality and adaptions to make it a tighter, more flexible system. This specification is intended to provide a basis for building a Napia system. It is expected that implementors will extend or modify the I/O devices as necessary for the underlying hardware. ## Overview * Napia is a 32-bit system. * The data stack stack holds 32 elements. * The address stack holds 128 elements. * All stack elements and internal registers are 32 bits. * There are 8 virtual CPU cores operating in a simple, round-robin fashion. * Each core has 24 words of internal memory, a data stack, an address stack, and dedicated IP, SP, and RP, registers. * Cores can be enabled or disabled as needed. * All cores share a single common memory pool. * The reference implementation provides access to 64KiB of RAM ## Memory The system memory consists of a single address space, with addresses assigned sequentially. ### Addressing Memory can be addressed as byte, halfword, or word size values. ## Alignment Word access must be aligned to a four byte boundary. Halfwords and bytes do not have to be aligned when used for data. E.g., +-----------------------------+ | 0000 byte half word | | 0001 byte half | | 0010 byte half | | 0011 byte half | | 0100 byte half word | | 0101 byte half | | 0110 byte half | | 0111 byte half | +-----------------------------+ ### Memory Mappings The first 192 bytes of memory are reserved for the I/O interface area. Memory beyond this is generally free for application use, though some devices may allocate space for memory mapped I/O. Devices can map additional memory areas. See your implementation for details. ## Instruction Set & Processing Napia processes instructions as word-sized bundles. Each bundle can hold up to four instructions and related data. Instructions and their data must fit into a single bundle. Instruction bundles must be aligned on word boundaries. E.g., you can have a series of bundles like: lb 1 ad re du mu re .. But the inline parameters must be in the same word. This would be valid: du mu lb 45 Whereas this would be invalid: du mu lh 45 As the *45* would extend beyond the end of the word. Special Cases - `lw` pushes the value in the following memory word to the stack. - `lh` pushes the halfword (16-bit) value in the following two instruction fields to the stack. - `lb` pushes the byte (8-bit) value in the following instruction field to the stack. - `ca`, `cc`, `ju`, `cj`, `re`, `cr`, and `ti` modify the instruction pointer and can not be followed by any other instructions except `no`. Any instructions inlined after them in the bundle will be treated as `no` instructions by Napia. Instructions are bundled into a single 32-bit word divided into four eight bit slots. The `lh` instruction can be used in slot 0 or 1 as it is followed by a 16-bit value (two slots) which can not cross a word boundary as this would place the data outside the instruction bundle. `lb` can be in slots 0, 1, or 2 as it is followed by an 8-bit value. Any instructions that follow an instruction modifying the `IP` register will be ignored (or treated as if they were `no`n operation.). These are `ca`, `cc`, `ju`, `cj`, `re`, `cr`, and `ti`. The `IP` register is incremented after the bundle is processed. ## Instruction Listing ``` 00 00 .. .. .. .. (-) non operation 01 01 lw .. .. .. nnnnnnnn (-n) push 32 bit value nnnnnnnn to stack 02 02 lh nn nn .. (-n) push 16 bit value nnnn to stack 03 03 lb nn .. .. (-n) push 8 bit value nn to stack 04 04 fw .. .. .. (a-n) fetch 05 05 fh .. .. .. (a-n) fetch 16-bit value 06 06 fb .. .. .. (a-n) fetch byte 07 07 sw .. .. .. (na-) store 08 08 sh .. .. .. (na-) store 16-bit value 09 09 sb .. .. .. (na-) store byte 10 0A du .. .. .. (n-nn) duplicate tos 11 0B dr .. .. .. (n-) drop tos 12 0C sp .. .. .. (nm-mn) swap tos and nos 13 0D pu .. .. .. (n-) a(-n) tos to address stack 14 0E po .. .. .. (-n) a(n-) top of address stack to data stack 15 0F eq .. .. .. (nn-f) equality 16 10 ne .. .. .. (nn-f) inequality 17 11 lt .. .. .. (nn-f) less than 18 12 gt .. .. .. (nn-f) greater than 19 13 ad .. .. .. (nn-n) addition 20 14 su .. .. .. (nn-n) subtract 21 15 mu .. .. .. (nn-n) multiply 22 16 dm .. .. .. (nn-nn) divide & remainder 23 17 md .. .. .. (xyz-nn) multiply, divide & remainder 24 18 an .. .. .. (nn-n) and 25 19 or .. .. .. (nn-n) or 26 1A xo .. .. .. (nn-n) xor 27 1B nt .. .. .. (n-n) not 28 1C sl .. .. .. (nn-n) left shift 29 1D sr .. .. .. (nn-n) right shift 30 1E pa .. .. .. (nnnn-n) pack 4 bytes into a 32-bit value 31 1F un .. .. .. (n-nnnn) unpack a 32-bit value into bytes 32 20 rl .. .. .. (-) treat next call or jump as relative 33 21 ca -- -- -- (a-) a(-a) call 34 22 cc -- -- -- (fa-) a(-?) conditional call 35 23 ju -- -- -- (a-) jump 36 24 cj -- -- -- (fa-) conditional jump 37 25 re -- -- -- (-) a(a-) return 38 26 cr -- -- -- (f-) a(a-) conditional return 39 27 sv .. .. .. (an-) set interrupt vector 40 28 hi .. .. .. (-) halt interrupts 41 29 si .. .. .. (-) start interrupts 42 2A ti .. .. .. (n-) trigger interrput 43 2B ii .. .. .. (n-) io interaction 44 2C ha .. .. .. (-) halt system 45 2D ic .. .. .. (an-) initialize core 46 2E ac .. .. .. (n-) activate core 47 2F pc .. .. .. (n-) pause core 48 30 sc .. .. .. (-) suspend current core 49 31 rr .. .. .. (n-v) read (current core) register 50 32 rw .. .. .. (vn-) write (current core) register 51 33 cy .. .. .. (aan-) copy n words from a1 to a2 52 34 bc .. .. .. (aan-f) compare n words from a1 to a2 53 35 uu .. .. .. (-) next operation is unsigned ``` ## Devices Up to 16 devices can be provided by the system. The first few devices are hard coded into the system, with the rest being left available to the implementation. Each device gets 12 bytes of RAM, allocated from address 0 and ending at 191 (decimal). Devices can map memory (e.g., for a framebuffer or audio). Interactions can be triggered via the instruction set (see `ii`) or memory mapings. Additionally, I/O devices can trigger interrupts (e.g., when a key is pressed or a pointing device is moved). +----+--------------------+--------------+ | ID | Usage | Memory Range | +----+--------------------+--------------+ | 0 | System Information | 0 - 11 | | 1 | Display | 12 - 23 | | 2 | Keyboard | 24 - 35 | | 3 | Pointing Device | 36 - 47 | | 4 | Block Storage | 48 - 59 | | 5 | | 60 - 71 | | 6 | | 72 - 83 | | 7 | | 84 - 95 | | 8 | | 96 - 107 | | 9 | | 108 - 119 | | 10 | | 120 - 131 | | 11 | | 132 - 143 | | 12 | User | 144 - 155 | | 13 | User | 156 - 167 | | 14 | User | 168 - 179 | | 15 | User | 180 - 191 | +----+--------------------+--------------+ Devices 12, 13, 14, and 15 are intended to be user devices, allowing the user to expand the functionality. ### 0: System Information +---------+------+---------------------------------------+ | Address | Size | Contents / Use | +---------+------+---------------------------------------+ | 00000 | BYTE | Display type | | | | 0: text, 1: addressable text, | | | | 2: framebuffer, 3: arks | | 00001 | BYTE | Keyboard | | | | 0: line buffered, 1: char buffered, | | | | 2: non-buffered | | 00002 | BYTE | Pointer (0: none, 1: present) | | 00003 | BYTE | Storage (0: none, 1: present) | | 00004 | | | | 00005 | | | | 00006 | | | | 00007 | | | | 00008 | WORD | Amount of Memory | | 00009 | | | | 00010 | | | | 00011 | | | +---------+------+---------------------------------------+ ### 1: Display For text mode (minimal): +---------+------+---------------------------------------+ | Address | Size | Contents / Use | +---------+------+---------------------------------------+ | 00012 | BYTE | | | 00013 | | | | 00014 | | | | 00015 | | | | 00016 | HALF | Height | | 00017 | | | | 00018 | HALF | Width | | 00019 | | | | 00020 | | | | 00021 | | | | 00022 | | | | 00023 | | | +---------+------+---------------------------------------+ For text mode (addressable): +---------+------+---------------------------------------+ | Address | Size | Contents / Use | +---------+------+---------------------------------------+ | 00012 | BYTE | | | 00013 | | | | 00014 | | | | 00015 | | | | 00016 | HALF | Height | | 00017 | | | | 00018 | HALF | Width | | 00019 | | | | 00020 | WORD | Starting address | | 00021 | | | | 00022 | | | | 00023 | | | +---------+------+---------------------------------------+ For framebuffer mode: +---------+------+---------------------------------------+ | Address | Size | Contents / Use | +---------+------+---------------------------------------+ | 00012 | WORD | Framebuffer address | | 00013 | | | | 00014 | | | | 00015 | | | | 00016 | HALF | Height | | 00017 | | | | 00018 | HALF | Width | | 00019 | | | | 00020 | | | | 00021 | BYTE | Bits per pixel | | 00022 | | | | 00023 | | | +---------+------+---------------------------------------+ For ARKS mode: +---------+------+---------------------------------------+ | Address | Size | Contents / Use | +---------+------+---------------------------------------+ | 00012 | HALF | Command Address | | 00013 | | | | 00014 | HALF | Sprite Data Address | | 00015 | | | | 00016 | BYTE | Color Palette | | 00017 | BYTE | Current Color | | 00018 | BYTE | Fill Mode | | 00019 | BYTE | Screen Mode | | 00020 | HALF | Height | | 00021 | | | | 00022 | HALF | Width | | 00023 | | | +---------+------+---------------------------------------+ ### 2: Keyboard +---------+------+---------------------------------------+ | Address | Size | Contents / Use | +---------+------+---------------------------------------+ | 00024 | BYTE | ASCII Value of most recent key | | 00025 | | | | 00026 | | | | 00027 | | | | 00028 | | | | 00029 | | | | 00030 | | | | 00031 | | | | 00032 | | | | 00033 | | | | 00034 | | | | 00035 | | | +---------+------+---------------------------------------+ ### 3: Pointer +---------+------+---------------------------------------+ | Address | Size | Contents / Use | +---------+------+---------------------------------------+ | 00036 | HALF | x coordinate | | 00037 | | | | 00038 | HALF | y coordinate | | 00039 | | | | 00040 | BYTE | button | | 00041 | | | | 00042 | | | | 00043 | | | | 00044 | | | | 00045 | | | | 00046 | | | | 00047 | | | +---------+------+---------------------------------------+ ### 4: Block Storage +---------+------+---------------------------------------+ | Address | Size | Contents / Use | +---------+------+---------------------------------------+ | 00048 | BYTE | Block Number | | 00049 | BYTE | Pool Number | | 00050 | BYTE | Operation | | 00051 | | | | 00052 | WORD | Buffer Address | | 00053 | | | | 00054 | | | | 00055 | | | | 00056 | HALF | Bytes per block | | 00057 | | | | 00058 | BYTE | Last op. status | | 00059 | BYTE | Number of pools | +---------+------+---------------------------------------+ ## Block Storage Block storage consists of one or more pools of blocks. Each pool provides 256 blocks. The maximum number of pools is 256, allowing for an upper limit of 65,536 blocks. Blocks can be provided in various sizes, which will be reported by reading address 56. A standard system will support one block storage device with 1024 byte blocks. Operations: | 0 | Read block to buffer | | 1 | Write buffer to block | ## Interrupts Napia supports 128 interrupts. The first twelve are reserved for the core system. The next 96 are reserved for I/O devices, and the last 20 are for user defined interrupts. Each of the 16 I/O devices is allotted 6 interrupts. Interrupts break the current exection flow and run specific functions to handle events. Interrupts can only be run on core zero. While the interrupt handler is running, all other cores are disabled. Core Interrupts | 000 | Critical Undefined Error | | 001 | Data Stack Underflow | | 002 | Data Stack Overflow | | 003 | Address Stack Underflow | | 004 | Address Stack Overflow | | 005 | Invalid Memory Access | | 006 | Division by Zero | | 007 | | | 008 | | | 009 | | | 010 | | | 011 | | Information | 012 | | | 013 | | | 014 | | | 015 | | | 016 | | | 017 | | Display | 018 | | | 019 | | | 020 | | | 021 | | | 022 | | | 023 | | Keyboard | 024 | Key pressed | | 025 | Key released | | 026 | | | 027 | | | 028 | | | 029 | | Pointer | 030 | Pointer Moved | | 031 | Button Down | | 032 | Button Up | | 033 | | | 034 | | | 035 | | Block Storage | 036 | Read Completed | | 037 | Write Completed | | 038 | Read Error | | 039 | Write Error | | 040 | | | 041 | | | 042 | | | 043 | | | 044 | | | 045 | | | 046 | | | 047 | | | 048 | | | 049 | | | 050 | | | 051 | | | 052 | | | 053 | | | 054 | | | 055 | | | 056 | | | 057 | | | 058 | | | 059 | | | 060 | | | 061 | | | 062 | | | 063 | | | 064 | | | 065 | | | 066 | | | 067 | | | 068 | | | 069 | | | 070 | | | 071 | | | 072 | | | 073 | | | 074 | | | 075 | | | 076 | | | 077 | | | 078 | | | 079 | | | 080 | | | 081 | | | 082 | | | 083 | | | 084 | | | 085 | | | 086 | | | 087 | | | 088 | | | 089 | | | 090 | | | 091 | | | 092 | | | 093 | | | 094 | | | 095 | | | 096 | | | 097 | | | 098 | | | 099 | | | 100 | | | 101 | | | 102 | | | 103 | | | 104 | | | 105 | | | 106 | | | 107 | | Software Interrupts | 108 | | | 109 | | | 110 | | | 111 | | | 112 | | | 113 | | | 114 | | | 115 | | | 116 | | | 117 | | | 118 | | | 119 | | | 120 | | | 121 | | | 122 | | | 123 | | | 124 | | | 125 | | | 126 | | | 127 | | ## Multiple Cores Napia provides 8 virtual CPU cores. On startup, only core 0 is active; other cores can be enabled and disabled as needed. Cores are processed in a round-robin schedule, switching after each instruction bundle is completed processing. Cores are processed in order, based on the core number. So if core 2 is activated after core 6, it will process first in the ordering. Core 0 acts as the primary core and is the only core active on startup. `ic` initializes a core. This takes an address and a core number, zeros out the stacks and internal registers, and assigns the core IP to the address. It does not activate the core. `ac` activates a core. `pc` pauses a core. `sc` pauses the current core. Cores have 24 words of private memory. This can be accessed via `rr` for reading and `rw` for writing. Notes: - interrupts are only run on core 0 with all others cores disabled until the interrupt handler returns