From a64b8780580bb4de557b7e574f2b2ee4058500d9 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Thu, 24 Oct 2024 11:38:13 +0200 Subject: [PATCH] comit --- .gitignore | 3 +- README.md | 2 +- include/address_space.h | 5 ++ programs/fib.elf | Bin 0 -> 4960 bytes programs/src/fib.c | 14 +++++ src/address_space.c | 23 +++++++++ src/instruction_executor.c | 102 +++++++++++++++++++++++++++++++------ 7 files changed, 131 insertions(+), 18 deletions(-) create mode 100755 programs/fib.elf create mode 100644 programs/src/fib.c diff --git a/.gitignore b/.gitignore index 1d597b3..5ba1d71 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .vscode/ build/ -programs/tests/ \ No newline at end of file +programs/tests/ +toolchain/ \ No newline at end of file diff --git a/README.md b/README.md index 0795c4a..46ecb6f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -RISC-V (rv32mi) emulator in C \ +RISC-V (rv32i + Zicsr) emulator in C \ This is just for me to understand how all this works, and to learn something new. \ So don't use it. diff --git a/include/address_space.h b/include/address_space.h index 3f7df9f..f8f7980 100644 --- a/include/address_space.h +++ b/include/address_space.h @@ -16,6 +16,9 @@ struct AddressSpace_s { uint8_t *ram; // The size of RAM. uint32_t ramSize; + + // The CSRs, size is always 4096 (12 bits) + uint32_t *csr; }; typedef struct AddressSpace_s AddressSpace; @@ -23,5 +26,7 @@ typedef struct AddressSpace_s AddressSpace; AddressSpace *create_address_space(const uint32_t romSize, const uint32_t ramSize); int read_address_space(const AddressSpace *addressSpace, const uint32_t address, const int n, void *dest); int write_address_space(const AddressSpace *addressSpace, const uint32_t address, const int n, void *src); +int read_csr(const AddressSpace *addressSpace, const uint16_t address, void *dest); +int write_csr(const AddressSpace *addressSpace, const uint16_t address, void *src); #endif \ No newline at end of file diff --git a/programs/fib.elf b/programs/fib.elf new file mode 100755 index 0000000000000000000000000000000000000000..c6eb92e9b99a0b2823a80d0705f96716f041fba6 GIT binary patch literal 4960 zcmeHL&1%$86h6t#GzfxeXHh{H(S(`mBDCYI#D&w&ScOt3)BQCwjbmW`NUo)>tc>CV zOdmk-5qtrK;v={gM7mWBxUsS4B+Zx!BI5cUIJxKNJ2%O9@9KNj+PbGG3S_3jcgV6j z7Vj^mojRDnUUpT)O0&s)u789z@)9~=edmkVqp)ZTSjdeP+cK97 zNCqSWk^#wpWI!??8ITM}1|$QL0m*=5;6E8CE6S-=SyV0ixmwl~Hr2nXmKnvYs>M^? zfbNGAm|#4D!;)1=YnB~h&jjmwgmqx7dK^!xFXFfQ53ro*C&gAJ!rJjEVJFpQJbksC z;2FlW-{+4f39kH7hl%-KW%PbUVZB3u&5e!Q=E@Cot?tyERcKtne+&GuyAR4DhMG|d z_HWhv+Ia2nKh0)JMv7yg&J8eBGBT}$8XA22rOzQ0Ao=6ya#}R7Z&Q9QQW!W*8c9CC zTgbOCCnNo13Gq7==jI<4@?If_M}EiYf_*UiWzKv3QOE7`@yH(vFR+30cC)eD;Oni; z2iu%uzTR&0)^; zM}vVk#2`5i#}y**J5Pic;#dEh(ODAbr1d0*To5;zk%mNe4V`eSl%Nr3m(nnKQjh#5 zI_XhK5g(*WWqK6V2t!6|{`B7=?i1EXlcH~-_hJbypyPfsdyO})Kg)jaM;9@VyNDO% H&L41Ri)4`H literal 0 HcmV?d00001 diff --git a/programs/src/fib.c b/programs/src/fib.c new file mode 100644 index 0000000..51ec695 --- /dev/null +++ b/programs/src/fib.c @@ -0,0 +1,14 @@ +unsigned int main() { + int n = 47; + + if (n <= 1) return n; + + unsigned int prev = 0, curr = 1, next; + for (int i = 2; i <= n; i++) { + next = prev + curr; + prev = curr; + curr = next; + } + + return curr; +} \ No newline at end of file diff --git a/src/address_space.c b/src/address_space.c index f0646e4..cc75af1 100644 --- a/src/address_space.c +++ b/src/address_space.c @@ -23,6 +23,7 @@ AddressSpace *create_address_space(const uint32_t romSize, const uint32_t ramSiz addressSpace->romLocked = false; addressSpace->ram = ram; addressSpace->ramSize = ramSize; + addressSpace->csr = calloc(4096, 1); return addressSpace; } @@ -82,5 +83,27 @@ int write_address_space(const AddressSpace *addressSpace, const uint32_t address return 1; } + return 0; +} + +int read_csr(const AddressSpace *addressSpace, const uint16_t address, void *dest) { + if (address >= 4096) { + fprintf(stderr, "Trying to read from CSR address 0x%X, which is higher than maximum 0xFFF\n", address); + return 1; + } + + memcpy(dest, addressSpace->csr + address, 4); + + return 0; +} + +int write_csr(const AddressSpace *addressSpace, const uint16_t address, void *dest) { + if (address >= 4096) { + fprintf(stderr, "Trying to write to CSR address 0x%X, which is higher than maximum 0xFFF\n", address); + return 1; + } + + memcpy(addressSpace->csr + address, dest, 4); + return 0; } \ No newline at end of file diff --git a/src/instruction_executor.c b/src/instruction_executor.c index 493a6b4..b47701d 100644 --- a/src/instruction_executor.c +++ b/src/instruction_executor.c @@ -238,11 +238,11 @@ int execute_instruction_on_cpu(CPU *cpu, uint32_t instruction) { // TODO conside imm |= ((instruction >> 20) & 0x1) << 11; // imm[11] imm |= ((instruction >> 21) & 0x3FF) << 1; // imm[10:1] - printf("JAL: Jumped to 0x%X + %d = 0x%X (inst %u), link x%u", cpu->programCounter, imm, cpu->programCounter, cpu->programCounter / 4, rd); - registers[rd] = cpu->programCounter + 4; cpu->programCounter += imm - 4; // program counter is incremented after this, and we have to execute the function we point to + printf("JAL: Jumped to 0x%X + %d = 0x%X (inst %u), link x%u", registers[rd], imm, cpu->programCounter, cpu->programCounter / 4, rd); + break; } case 0b0110011: { // OP for Integer Register-Register Operations (R type) @@ -279,25 +279,95 @@ int execute_instruction_on_cpu(CPU *cpu, uint32_t instruction) { // TODO conside } case 0b1110011: {// SYSTEM (I type) instructions are used to access system functionality that might require privileged access, here only ECALL and EBREAK uint8_t funct3 = instruction >> 12 & 0x7; - uint32_t rs1 = instruction >> 15 & 0x1F; - uint32_t func12 = instruction >> 20 & 0xFFF; + uint32_t rs1 = instruction >> 15 & 0x1F; // aka uimm. zero extends automatically + uint32_t func12 = instruction >> 20 & 0xFFF; // aka csr - if (funct3 != 0 || rd != 0 || rs1 != 0) { - fprintf(stderr, "For SYSTEM instructions, funct3, rd and rs1 must be 0, but are 0x%X, 0x%X and 0x%X. Zicsr is not supported.", funct3, rd, rs1); - return 2; + if (funct3 == 0) { + if (rd != 0 || rs1 != 0) { + fprintf(stderr, "For ECALL / EBREAK instructions, rd and rs1 must be 0, but are 0x%X and 0x%X.", rd, rs1); + return 2; + } + + if (func12 == 0) { // ECALL + printf("--- ECALL ---"); + // TODO do something + } else if (func12 == 1) { // EBREAK + printf("--- EBREAK---"); + // TODO do something + } else { + fprintf(stderr, "Invalid func12 for environment instructions: 0x%X", func12); + //return 2; + } + } else if (funct3 == 0b001) { // CSRRW Atomic Read/Write CSR + printf("CSRRW: (0x%X <-> x%u) -> x%u", func12, rs1, rd); + if (rd != 0) { + uint32_t csrValue; + read_csr(addressSpace, func12, &csrValue); + + write_csr(addressSpace, func12, registers + rs1); + registers[rd] = csrValue; + } else { + write_csr(addressSpace, func12, registers + rs1); + } + } else if (funct3 == 0b010) { // CSRRS Atomic Read and Set Bits in CSR + printf("CSRRS: (0x%X | x%u) -> x%u", func12, rs1, rd); + uint32_t csrValue; + read_csr(addressSpace, func12, &csrValue); + + if (rs1 != 0) { + uint32_t csrValueNew = csrValue | registers[rs1]; + write_csr(addressSpace, func12, &csrValueNew); + } + + registers[rd] = csrValue; + } else if (funct3 == 0b011) { // CSRRC Atomic Read and Clear Bits in CSR + printf("CSRRC: (0x%X & ~x%u) -> x%u", func12, rs1, rd); + uint32_t csrValue; + read_csr(addressSpace, func12, &csrValue); + + if (rs1 != 0) { + uint32_t csrValueNew = csrValue & ~registers[rs1]; + write_csr(addressSpace, func12, &csrValueNew); + } + + registers[rd] = csrValue; + } else if (funct3 == 0b101) { // CSRRWI Atomic Read/Write CSR Immediate + printf("CSRRWI: (0x%X <-> 0x%X) -> x%u", func12, rs1, rd); + // since we don't worry about order, we can simplify + if (rd != 0) { + read_csr(addressSpace, func12, registers + rd); + } + + write_csr(addressSpace, func12, &rs1); // rs1 is uimm + } else if (funct3 == 0b110) { // CSRRSI Atomic Read and Set Bits in CSR Immediate + printf("CSRRSI: (0x%X | 0x%X) -> x%u", func12, rs1, rd); + read_csr(addressSpace, func12, registers + rd); + + if (rs1 != 0) { + uint32_t csrValueNew = registers[rd] | rs1; + write_csr(addressSpace, func12, &csrValueNew); + } + } else if (funct3 == 0b111) { // CSRRCI Atomic Read and Clear Bits in CSR Immediate + printf("CSRRCI: (0x%X & 0x%X) -> x%u", func12, rs1, rd); + read_csr(addressSpace, func12, registers + rd); + + if (rs1 != 0) { + uint32_t csrValueNew = registers[rd] & ~rs1; + write_csr(addressSpace, func12, &csrValueNew); + } } - if (func12 == 0) { // ECALL - printf("--- ECALL ---"); - // TODO do something - } else if (func12 == 1) { // EBREAK - printf("--- EBREAK---"); - // TODO do something - } else { - fprintf(stderr, "Invalid SYSTEM func12: 0x%X", func12); - return 2; + break; + } + case 0b0001111: { // MISC-MEM + uint8_t funct3 = instruction >> 12 & 0x7; + uint8_t rs1 = instruction >> 15 & 0x1F; + + if (funct3 != 0) { + fprintf(stderr, "funct3 in MISC-MEM must be zero, but is 0x%X", funct3); } + // TODO break; } default: {