diff options
| -rw-r--r-- | .gitignore | 2 | ||||
| -rw-r--r-- | README.md | 138 | ||||
| -rw-r--r-- | emux64/.gitignore | 1 | ||||
| -rw-r--r-- | emux64/Makefile | 16 | ||||
| -rw-r--r-- | emux64/sample/add.rom | bin | 0 -> 18 bytes | |||
| -rw-r--r-- | emux64/sample/nop.rom | bin | 0 -> 14 bytes | |||
| -rw-r--r-- | emux64/src/cpu/cpu_cycle.c | 321 | ||||
| -rw-r--r-- | emux64/src/cpu/cpu_subr.c | 90 | ||||
| -rw-r--r-- | emux64/src/include/cpu/cpu.h | 117 | ||||
| -rw-r--r-- | emux64/src/include/memmap.h | 36 | ||||
| -rw-r--r-- | emux64/src/include/rom.h | 67 | ||||
| -rw-r--r-- | emux64/src/main.c | 111 | ||||
| -rw-r--r-- | emux64/src/rom.c | 84 | ||||
| -rw-r--r-- | sv/soc/bus/dmactl.sv | 8 | ||||
| -rw-r--r-- | sv/soc/irq/pimc.sv | 4 | ||||
| -rw-r--r-- | tb/soc/irq/tb_pimc.cpp | 4 |
16 files changed, 980 insertions, 19 deletions
@@ -1,2 +1,4 @@ obj_dir/ +emux64/bin/ *.vcd +*.o @@ -16,6 +16,21 @@ Registers store data which can be accessed at any time. These include special re | `fp` | 64 bits | Frame pointer | | `ptp` | 64 bits | Page tree pointer | +## Link Registers + +The link registers are for storing specific return addresses from a subroutine + +| Name | Size | Purpose | +| ---------- | -------- | --------------------------- +| `blr` | 64 bits | Branch Link Register | +| `ilr` | 64 bits | Interrupt Link Register | + +When calling a subroutine, it will need to know where to return to +when the execution finishes. To achieve this, we use the branch link +register (BLR). In situations where an interrupt has occurred on the +system, the CPU would need to know where to return to from the interrupt +context, in cases such as this, we'd use the Interrupt Link Register (ILR). + ### Internal Registers Only accessed by the CPU for certain instructions. Cannot be directly read/written. @@ -25,17 +40,69 @@ Only accessed by the CPU for certain instructions. Cannot be directly read/writt | `rp` | 64 bits | Return pointer for branches | | `ins` | 64 bits | Current instruction at `pc` | +## Special Registers + +OSMX64 provides "special" control registers that may vary depending on the chip +revision. These registers typically include chip-specific mode/control bits to +configure the processor for certain modes of operations, etc. These registers +cannot be accessed via the "mov" instruction and instead rely on independent wrs/rrs +(i.e., special register write / special register read) instructions. + +### Common Special Registers + +| Name | Size | Purpose | +| --------- | ------- | --------------------------- | +| `SR_STATE`| 64 bits | Processor state bits | + + +### SR\_STATE + +| Bit | Meaning | Purpose +|------|---------------------- | ---------------------- | +| 0 | Reserved | Must be zero | +| 1 | Supervisor | Supervisor mode enable | +| 2 | Carry | Arithmetic carry flag | +| 3-31 | Reserved (must be 0) | Must be zero | + + +#### Supervisor bit +The supervisor bit may only be writable in a privileged mode of execution +and is therefore readonly in user contexts (writes ignored). It may be unset +by system software to transition the processor into a user context. This bit +may only transition from a 0 to a 1 during an interrupt/trap, therefore manually +writing a 1 to this bit is ignored by the processor. + +#### Carry bit +Indicates whether an arithmetic operation has resulted in a +carry/borrow. + ## Instructions + +### Special Register Access + +Special registers are identified with a 16-bit Special Register ID (SRID) +and can be accessed through two special instructions. + +| Mnemonic | Effect | +| -------------------------------- | ----------------------- | +| `wrs` srid: r/imm, val: r | `SREGS[srid]` = `val` | +| `rrs` dest: r, srid: r/imm | `dest` = `SREGS[srid]` | + + ### Bitwise Instructions Bitwise logic operations can write to all registers except `v0`-`v7`, `x0` and `pc`. Can read from all registers except `v0`-`v7`. -| Mnemonic | Effect | -| -------------------------------- | ---------------------- | -| `and` dst: r, reg: r, val: r/imm | `dst` = `dst` & `val` | -| `or` dst: r, reg: r, val: r/imm | `dst` = `dst` \| `val` | -| `xor` dst: r, reg: r, val: r/imm | `dst` = `dst` ^ `val` | +| Mnemonic | Effect | +| -------------------------------- | ------------------------------- | +| `and` dst: r, reg: r, val: r/imm | `dst` = `dst` & `val` | +| `or` dst: r, reg: r, val: r/imm | `dst` = `dst` \| `val` | +| `xor` dst: r, reg: r, val: r/imm | `dst` = `dst` ^ `val` | +| `mrob` dst: r: mask [bit]: imm | Fill byte of 'dst' with 'mask' | +| `mrow` dst: r: mask [bit]: imm | Fill word of 'dst' with 'mask' | +| `mrod` dst: r: mask [bit]: imm | Fill dword of 'dst' with 'mask' | +| `mroq` dst: r: mask [bit]: imm | Fill qword of 'dst' with 'mask' | #### Example ``` @@ -82,10 +149,10 @@ Arithmetic operations can write to all registers except `v0`-`v7`, `x0` and `pc` | Mnemonic | Effect | | ------------------------------------ | --------------------- | -| `add` dst: r, reg: r, val: r/imm | `dst` = `dst` + `val` | -| `sub` dst: r, reg: r, val: r/imm | `dst` = `dst` - `val` | -| `mul` dst: r, reg: r, val: r/imm | `dst` = `dst` * `val` | -| `div` dst: r, reg: r, val: r/imm | `dst` = `dst` / `val` | +| `add` dst: r, val: r/imm | `dst` = `dst` + `val` | +| `sub` dst: r, val: r/imm | `dst` = `dst` - `val` | +| `mul` dst: r, val: r/imm | `dst` = `dst` * `val` | +| `div` dst: r, val: r/imm | `dst` = `dst` / `val` | | `inc` dst: r | `dst` = `dst` + `1` | | `dec` dst: r | `dst` = `dst` - `1` | @@ -105,8 +172,8 @@ Control flow instructions are used to control which instructions the CPU execute | Mnemonic | Effect | | -------------------------------------- | ----------------------------------------------- | | `hlt` | Execution halted | -| `br` dst: r/m/imm | `pc` = `dst` | -| `brl` dst: r/m/imm | `rp` = `pc` + size of opcode, then `pc` = `dst` | +| `br` dst: r | `pc` = `dst` | +| `brl` dst: r | `rp` = `pc` + size of opcode, then `pc` = `dst` | | `bret` | `pc` = `rp` | | `beq` a: r/m, b: r/m/imm, dst: r/m/imm | Iff `a` = `b`, `pc` = `dst` | | `bne` a: r/m, b: r/m/imm, dst: r/m/imm | Iff `a` != `b`, `pc` = `dst` | @@ -127,5 +194,54 @@ mov x1, #3 /* Iff x1 - x1 != 0, x1 equals 2 */ ``` +### Operand specifier + +Some opcodes require an operand specifier after them +to indicate whether or not the second operand [OP2] is +a register or an immediate, for example: + +``` +ADD 0b1 DEST, SRC, IMM_OP +ADD 0b0 DEST, SRC_REG, REG_OP +``` + +A value of 0b1 indicates an immediate value is used for the second +operand (``IMM_OP``) and a value of 0b0 indicates a register is used for +the second operand (``REG_OP``). + +### Bring up area + +Upon power up, all general purpose registers (excluding x0), as well as the stack pointer +and frame pointer registers are to all go high (all 1s), PC is to be set to an initial value +of 0xFFF00000 referencing whats known as the "bring up area" containing platform firmware and +initialization code located in the ROM. + +### Opcode list + +- `NOP`: `0x00` +- `ADD`: `0x01` +- `SUB`: `0x02` +- `MUL`: `0x03` +- `DIV`: `0x04` +- `INC`: `0x05` +- `DEC`: `0x06` +- `OR`: `0x07` +- `XOR`: `0x08` +- `AND`: `0x09` +- `NOT`: `0x0A` +- `SLL`: `0x0B` +- `SRL`: `0x0C` +- `MOV_IMM`: `0x0D` +- `HLT`: `0x0E` +- `BR`: `0x0F` +- `MROB`: `0x10` +- `MROW`: `0x11` +- `MROD`: `0x12` +- `MROQ`: `0x13` + +### Register encoding identifiers + +- `X0 - X15`: `0x00 - 0x0E` + Copyright (c) 2024 Quinn Stephens and Ian Marco Moffett. All rights reserved. diff --git a/emux64/.gitignore b/emux64/.gitignore new file mode 100644 index 0000000..e660fd9 --- /dev/null +++ b/emux64/.gitignore @@ -0,0 +1 @@ +bin/ diff --git a/emux64/Makefile b/emux64/Makefile new file mode 100644 index 0000000..c66d461 --- /dev/null +++ b/emux64/Makefile @@ -0,0 +1,16 @@ +CC = gcc +CFLAGS = -pedantic -Isrc/include/ +CFILES = $(shell find src/ -name "*.c") +OFILES = $(CFILES:.c=.o) + +.PHONY: all +all: $(OFILES) + mkdir -p bin/ + $(CC) $^ $(CFLAGS) -o bin/emux + +%.o: %.c + $(CC) -c $< $(CFLAGS) -o $@ + +.PHONY: clean +clean: + rm $(OFILES) diff --git a/emux64/sample/add.rom b/emux64/sample/add.rom Binary files differnew file mode 100644 index 0000000..3b6e5e3 --- /dev/null +++ b/emux64/sample/add.rom diff --git a/emux64/sample/nop.rom b/emux64/sample/nop.rom Binary files differnew file mode 100644 index 0000000..ddeddbc --- /dev/null +++ b/emux64/sample/nop.rom diff --git a/emux64/src/cpu/cpu_cycle.c b/emux64/src/cpu/cpu_cycle.c new file mode 100644 index 0000000..dda1794 --- /dev/null +++ b/emux64/src/cpu/cpu_cycle.c @@ -0,0 +1,321 @@ +/* + * Copyright (c) 2025 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdio.h> +#include <errno.h> +#include <stdbool.h> +#include "rom.h" +#include "cpu/cpu.h" + +/* + * Represents arithmetic arguments + * + * @dest_reg: Destination register [R] + * @op1: Operand 1 [IMM] + * op2: Operand 2 [IMM] + */ +struct arithop { + uint8_t dest_reg; + uint64_t op1; + uint64_t op2; +}; + +/* + * Returns true if the register is an + * X<n> type register + * + * @reg: Register to check + */ +static inline bool +reg_is_xn(uint8_t reg) +{ + return reg >= REG_XN_BASE && reg <= REG_XN_LIMIT; +} + +/* + * Fetch an instruction byte from memory + * + * @core: Core to fetch for + * @byte_res: Result is written here + * + * XXX: Caller is to increment `core->pc' + * + * Returns zero on success + */ +static int +cpu_fetch(struct osmx_core *core, uint8_t *byte_res) +{ + uint8_t *rom; + size_t rom_len; + + if (core == NULL || byte_res == NULL) { + printf("fatal: bad arg in %s()\n", __func__); + return -1; + } + + if ((rom = g_firmware.buf) == NULL) { + printf("fatal: ROM is uninitialized\n"); + return -1; + } + + rom_len = g_firmware.length; + if (core->pc >= (CPU_BUA_PBASE + rom_len)) { + printf("fatal: PC outside of ROM\n"); + return -1; + } + + if (core->pc >= CPU_BUA_PBASE) { + *byte_res = rom[core->pc - CPU_BUA_PBASE]; + } + + return 0; +} + +/* + * Get a 32-bit value from values @ PC + */ +static int +cpu_fetch32(struct osmx_core *core, uint64_t *res) +{ + uint64_t v = 0; + uint8_t byte; + int error; + + if (core == NULL || res == NULL) { + return -EINVAL; + } + + for (int i = 0; i < 32; i += 8) { + error = cpu_fetch(core, &byte); + if (error < 0) { + return error; + } + + v |= (byte << i); + core->pc++; + } + + *res = v; + return 0; +} + +/* + * Get arithmetic parameters + * + * @core: Core that is executing + * @res: Result written here + * + * Returns zero on success + */ +static int +cpu_arithop(struct osmx_core *core, struct arithop *res) +{ + uint8_t dest, op1, op2; + uint64_t op2_val; + bool op2_is_imm; + bool op2_is_big; + int error = 0; + + if (core == NULL || res == NULL) { + return -EINVAL; + } + + /* Grab the dest register */ + error = cpu_fetch(core, &dest); + if (error < 0) { + return error; + } + + ++core->pc; + + error = cpu_fetch(core, &op1); + if (error < 0) { + return error; + } + + ++core->pc; + + /* + * Operand one is 7 bits as the first bit in the + * byte is used for indicating if the second operand + * is an immediate value (1) or a register (0) + */ + op2_is_imm = op1 & 1; + op1 >>= 1; + + /* Verify the register types */ + if (!reg_is_xn(dest) || dest == 0) + return -1; + if (!reg_is_xn(op1)) + return -1; + + if (op2_is_imm) { + error = cpu_fetch32(core, &op2_val); + } else { + op2_val = core->xn[op2 - REG_XN_BASE]; + } + + if (error != 0) { + return error; + } + + res->dest_reg = dest; + res->op1 = core->xn[op1]; + res->op2 = op2_val; + return 0; +} + +static int +cpu_do_add(struct osmx_core *core) +{ + struct arithop ops; + int error; + + error = cpu_arithop(core, &ops); + if (error < 0) { + return error; + } + + core->xn[ops.dest_reg] = ops.op1 + ops.op2; + return 0; + +} + +static int +cpu_do_sub(struct osmx_core *core) +{ + struct arithop ops; + int error; + + error = cpu_arithop(core, &ops); + if (error < 0) { + return error; + } + + core->xn[ops.dest_reg] = ops.op1 - ops.op2; + return 0; +} + +static int +cpu_do_mul(struct osmx_core *core) +{ + struct arithop ops; + int error; + + error = cpu_arithop(core, &ops); + if (error < 0) { + return error; + } + + core->xn[ops.dest_reg] = ops.op1 * ops.op2; + return 0; +} + +static int +cpu_do_div(struct osmx_core *core) +{ + struct arithop ops; + int error; + + error = cpu_arithop(core, &ops); + if (error < 0) { + return error; + } + + if (ops.op2 == 0) { + printf("** DIVIDE ERROR **\n"); + return -1; + } + + core->xn[ops.dest_reg] = ops.op1 / ops.op2; + return 0; +} + +int +cpu_run(struct osmx_core *core) +{ + uint8_t opcode; + int error; + + if (core == NULL) { + return -EINVAL; + } + + core->run = 1; + while (core->run) { + error = cpu_fetch(core, &opcode); + if (error < 0) { + printf("cpu: instruction fetch error\n"); + core->run = 0; + break; + } + + ++core->pc; + + /* Test opcode cases */ + switch (opcode) { + case OP_HLT: + printf("** HALTED **\n"); + core->run = false; + continue; + case OP_ADD: + if (cpu_do_add(core) < 0) { + core->run = false; + continue; + } + break; + case OP_SUB: + if (cpu_do_sub(core) < 0) { + core->run = false; + continue; + } + break; + case OP_MUL: + if (cpu_do_mul(core) < 0) { + core->run = false; + continue; + } + break; + case OP_DIV: + if (cpu_do_div(core) < 0) { + core->run = false; + continue; + } + break; + case OP_NOP: + break; + default: + printf("** INVALID OPCODE **\n"); + break; + } + + printf("--\n"); + cpu_dump(core); + } +} diff --git a/emux64/src/cpu/cpu_subr.c b/emux64/src/cpu/cpu_subr.c new file mode 100644 index 0000000..8833bdf --- /dev/null +++ b/emux64/src/cpu/cpu_subr.c @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2025 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdio.h> +#include <errno.h> +#include "cpu/cpu.h" + +void +cpu_dump(struct osmx_core *core) +{ + if (core == NULL) { + return; + } + + /* General purpose registers */ + for (int i = 0; i < N_GPREG; ++i) { + printf("X%d=0x%016llx ", i, core->xn[i]); + if ((i & 1) != 0) + printf("\n"); + } + + for (int i = 0; i < N_FLOATREG; ++i) { + printf("F%d=0x%016llx ", i, core->fn[i]); + if ((i & 1) != 0) + printf("\n"); + } + + /* Double precision registers */ + for (int i = 0; i < N_DUBREG; ++i) { + printf("D%d=0x%016llx ", i, core->dn[i]); + if ((i & 1) == 0) + printf("\n"); + } + + printf("PC=0x%016llx\n", core->pc); +} + +int +cpu_reset(struct osmx_core *core) +{ + if (core == NULL) { + return -EINVAL; + } + + core->pc = CPU_BUA_PBASE; + core->xn[0] = 0; + + /* Initialize float registers */ + for (int i = 0; i < N_FLOATREG; ++i) { + core->fn[i] = 0; + } + + /* Initialize double registers */ + for (int i = 0; i < N_DUBREG; ++i) { + core->dn[i] = 0; + } + + /* Initialize other gp regs */ + for (int i = 1; i < N_GPREG; ++i) { + core->xn[i] = 0xFFFFFFFFFFFFFFFF; + } + + return 0; +} diff --git a/emux64/src/include/cpu/cpu.h b/emux64/src/include/cpu/cpu.h new file mode 100644 index 0000000..482aae3 --- /dev/null +++ b/emux64/src/include/cpu/cpu.h @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2025 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Description: Virtual CPU definitions + * Author: Ian Marco Moffett + */ + +#ifndef CPU_CPU_H +#define CPU_CPU_H + +#include <stdint.h> +#include <stddef.h> +#include "memmap.h" + +/* Register type counts */ +#define N_GPREG 16 +#define N_FLOATREG 7 +#define N_DUBREG 7 + +/* OSMX64 Opcodes */ +#define OP_NOP 0x00 /* No-op */ +#define OP_ADD 0x01 /* 2-op ADD */ +#define OP_SUB 0x02 /* 2-op SUB */ +#define OP_MUL 0x03 /* 2-op MUL */ +#define OP_DIV 0x04 /* 2-op DIV */ +#define OP_HLT 0x0E /* Halt */ + +/* + * X<n> register encoding + * + * Range: 0x00 - 0xE + */ +#define REG_XN_BASE 0x00 +#define REG_XN_LIMIT (REG_XN_BASE + 0x0E) + +/* + * Represents a single unit of execution + * + * @xn: 64-bit X<n> registers + * @fn: IEEE 754 single-precision registers + * @dn: IEEE 754 double-precision registers + * @pc: Program counter + * @run: Processor running + */ +struct osmx_core { + uint64_t xn[N_GPREG]; + float fn[N_FLOATREG]; + double dn[N_DUBREG]; + uintptr_t pc; + uint8_t run : 1; +}; + +/* + * Represents a single (virtual) CPU package, + * can have many cores + * + * TODO: Dynamically allocate cores + */ +struct osmx_cpu { + struct osmx_core cores[1]; +}; + +/* + * Bring the CPU to an initial reset state + * + * @core: Core to bring to reset state + * + * Returns zero on success + */ +int cpu_reset(struct osmx_core *core); + +/* + * Dump the registers to the console for debugging + * purposes + * + * @core: Core to dump + */ +void cpu_dump(struct osmx_core *core); + +/* + * Initialize the registers to use for the + * CPU + * + * @core: Core to use + * + * Returns zero on success + */ +int cpu_run(struct osmx_core *core); + +#endif /* !CPU_CPU_H */ diff --git a/emux64/src/include/memmap.h b/emux64/src/include/memmap.h new file mode 100644 index 0000000..3060f5c --- /dev/null +++ b/emux64/src/include/memmap.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2025 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef MEMMAP_H +#define MEMMAP_H 1 + +/* Bring up area physical base */ +#define CPU_BUA_PBASE 0xFFF00000 + +#endif /* !MEMMAP_H */ diff --git a/emux64/src/include/rom.h b/emux64/src/include/rom.h new file mode 100644 index 0000000..0480440 --- /dev/null +++ b/emux64/src/include/rom.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2025 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ROM_H +#define ROM_H + +#include <stdint.h> +#include <stddef.h> + +/* + * Represents a firmware ROM file + * + * @buf: Buffer containing ROM data + * @length: Length of ROM + */ +struct osmx_rom { + uint8_t *buf; + size_t length; +}; + +extern struct osmx_rom g_firmware; + +/* + * Open a ROM file by path + * + * @path: Path to ROM file + * @res: Result of ROM descriptor + * + * Returns zero on success, otherwise a less than + * zero value on failure. + */ +int rom_open(const char *path, struct osmx_rom *res); + +/* + * Release resources associated with a ROM file + * + * @rom: ROM to release from host memory + */ +void rom_release(struct osmx_rom *rom); + +#endif /* ROM_H */ diff --git a/emux64/src/main.c b/emux64/src/main.c new file mode 100644 index 0000000..b8d39b4 --- /dev/null +++ b/emux64/src/main.c @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2025 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include "cpu/cpu.h" +#include "rom.h" + +static char *rom_file = NULL; +struct osmx_rom g_firmware; + +static void +help(void) +{ + printf( + "- OSMX64 emulator -\n" + "[-h] Show this help menu\n" + "[-r] <rom_file>\n" + ); +} + +static void +cleanup(void) +{ + if (rom_file != NULL) { + free(rom_file); + rom_file = NULL; + } + + rom_release(&g_firmware); +} + +static int +run(struct osmx_core *core) +{ + int error; + + if (rom_file == NULL) { + return -1; + } + + /* Open the firmware ROM */ + cpu_dump(core); + error = rom_open(rom_file, &g_firmware); + if (error < 0) { + return error; + } + + cpu_run(core); +} + +int +main(int argc, char **argv) +{ + struct osmx_core core; + int error; + int c; + + atexit(cleanup); + while ((c = getopt(argc, argv, "hr:")) != -1) { + switch (c) { + case 'h': + help(); + return 0; + case 'r': + rom_file = strdup(optarg); + break; + } + } + + if (rom_file == NULL) { + printf("** please select a ROM file\n"); + help(); + return -1; + } + + if ((error = cpu_reset(&core)) < 0) { + printf("error: failed to power up vcore\n"); + return error; + } + + return run(&core); +} diff --git a/emux64/src/rom.c b/emux64/src/rom.c new file mode 100644 index 0000000..24d447d --- /dev/null +++ b/emux64/src/rom.c @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2025 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdint.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include "rom.h" + +int +rom_open(const char *path, struct osmx_rom *res) +{ + int fd; + + if (path == NULL || res == NULL) { + return -EINVAL; + } + + fd = open(path, O_RDONLY); + if (fd < 0) { + perror("open"); + return fd; + } + + /* Get the ROM length */ + res->length = lseek(fd, 0, SEEK_END); + lseek(fd, 0, SEEK_SET); + + /* Allocate space for the ROM */ + res->buf = malloc(res->length); + if (res->buf == NULL) { + printf("error: out of host memory\n"); + close(fd); + return -ENOMEM; + } + + read(fd, res->buf, res->length); + close(fd); + return 0; +} + +void +rom_release(struct osmx_rom *rom) +{ + if (rom == NULL) { + return; + } + + if (rom->buf == NULL) { + return; + } + + free(rom->buf); + rom->buf = NULL; +} diff --git a/sv/soc/bus/dmactl.sv b/sv/soc/bus/dmactl.sv index c0851c1..27a13ec 100644 --- a/sv/soc/bus/dmactl.sv +++ b/sv/soc/bus/dmactl.sv @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Athena Systems LLC and Ian Marco Moffett + * Copyright (c) 2024-2025 Ian Marco Moffett and the Osmora Team. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -10,7 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holder nor the names of its + * 3. Neither the name of Hyra nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * @@ -36,8 +36,8 @@ module dmactl #( /* MMIO bases for DMA channels */ parameter C0_MMIO_BASE = 48'h1000140, parameter C1_MMIO_BASE = 48'h1000153, - parameter C2_MMIO_BASE = 48'h1000153, - parameter C3_MMIO_BASE = 48'h1000166, + parameter C2_MMIO_BASE = 48'h1000166, + parameter C3_MMIO_BASE = 48'h100016E, /* Channel control bits */ parameter CCTL_START = 0, diff --git a/sv/soc/irq/pimc.sv b/sv/soc/irq/pimc.sv index 15b82c9..21d5dde 100644 --- a/sv/soc/irq/pimc.sv +++ b/sv/soc/irq/pimc.sv @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Athena Systems LLC and Ian Marco Moffett + * Copyright (c) 2024-2025 Ian Marco Moffett and the Osmora Team. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -10,7 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holder nor the names of its + * 3. Neither the name of Hyra nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * diff --git a/tb/soc/irq/tb_pimc.cpp b/tb/soc/irq/tb_pimc.cpp index ec06a5d..7365649 100644 --- a/tb/soc/irq/tb_pimc.cpp +++ b/tb/soc/irq/tb_pimc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Athena Systems LLC and Ian Marco Moffett + * Copyright (c) 2024-2025 Ian Marco Moffett and the Osmora Team. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -10,7 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holder nor the names of its + * 3. Neither the name of Hyra nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * |
