initial commit
This commit is contained in:
		
				commit
				
					
						3850c27440
					
				
			
		
					 7 changed files with 343 additions and 0 deletions
				
			
		
							
								
								
									
										7
									
								
								.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,7 @@
 | 
			
		|||
target/
 | 
			
		||||
!.mvn/wrapper/maven-wrapper.jar
 | 
			
		||||
!**/src/main/**/target/
 | 
			
		||||
!**/src/test/**/target/
 | 
			
		||||
 | 
			
		||||
### IntelliJ IDEA ###
 | 
			
		||||
.idea/
 | 
			
		||||
							
								
								
									
										4
									
								
								README.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								README.txt
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,4 @@
 | 
			
		|||
This is just for me to understand how all this works, and to learn something new.
 | 
			
		||||
 | 
			
		||||
For example, I learned that endianness is not per bit but per byte. My whole life I've been in misinformation.
 | 
			
		||||
So little endian is not that first bit is the LSB, but it's MSB... and after 8 bits it becomes larger, which makes no point
 | 
			
		||||
							
								
								
									
										17
									
								
								pom.xml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								pom.xml
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,17 @@
 | 
			
		|||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
 | 
			
		||||
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 | 
			
		||||
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 | 
			
		||||
    <modelVersion>4.0.0</modelVersion>
 | 
			
		||||
 | 
			
		||||
    <groupId>eu.m724</groupId>
 | 
			
		||||
    <artifactId>risc</artifactId>
 | 
			
		||||
    <version>1.0-SNAPSHOT</version>
 | 
			
		||||
 | 
			
		||||
    <properties>
 | 
			
		||||
        <maven.compiler.source>21</maven.compiler.source>
 | 
			
		||||
        <maven.compiler.target>21</maven.compiler.target>
 | 
			
		||||
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 | 
			
		||||
    </properties>
 | 
			
		||||
 | 
			
		||||
</project>
 | 
			
		||||
							
								
								
									
										85
									
								
								src/main/java/eu/m724/AddressSpace.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								src/main/java/eu/m724/AddressSpace.java
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,85 @@
 | 
			
		|||
package eu.m724;
 | 
			
		||||
 | 
			
		||||
import java.util.Arrays;
 | 
			
		||||
import java.util.Base64;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Represents an address space
 | 
			
		||||
 *
 | 
			
		||||
 * Basically, there's ROM, then RAM, then IO
 | 
			
		||||
 */
 | 
			
		||||
public class AddressSpace {
 | 
			
		||||
    public final int romBase, romSize;
 | 
			
		||||
    public final int ramBase, ramSize;
 | 
			
		||||
    public boolean isRomInit;
 | 
			
		||||
 | 
			
		||||
    private final byte[] rom;
 | 
			
		||||
    private final byte[] ram;
 | 
			
		||||
 | 
			
		||||
    public AddressSpace(int romSize, int ramSize) {
 | 
			
		||||
        this.romBase = 0;
 | 
			
		||||
        this.ramBase = romSize;
 | 
			
		||||
 | 
			
		||||
        this.romSize = romSize;
 | 
			
		||||
        this.ramSize = ramSize;
 | 
			
		||||
 | 
			
		||||
        this.rom = new byte[romSize];
 | 
			
		||||
        this.ram = new byte[ramSize];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void initRom(byte[] program) { // TODO test method
 | 
			
		||||
        if (isRomInit) throw new RuntimeException("ROM already initialized");
 | 
			
		||||
        isRomInit = true;
 | 
			
		||||
 | 
			
		||||
        for (int i=0; i<program.length; i++) {
 | 
			
		||||
            rom[i] = program[i];
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * read {@code n} bytes from ROM<br>
 | 
			
		||||
     *
 | 
			
		||||
     * @param address address of first byte
 | 
			
		||||
     * @param n number of bytes, max 8
 | 
			
		||||
     * @return the unsigned bytes
 | 
			
		||||
     */
 | 
			
		||||
    long readRom(int address, int n) {
 | 
			
		||||
        long v = 0;
 | 
			
		||||
 | 
			
		||||
        for (int i=0; i<n; i++) {
 | 
			
		||||
            v |= (long) (rom[address + i] & 0xFF) << (8 * i);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return v;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * read {@code n} bytes from RAM
 | 
			
		||||
     *
 | 
			
		||||
     * @param address address of first byte
 | 
			
		||||
     * @param n number of bytes, max 8
 | 
			
		||||
     * @return the unsigned bytes
 | 
			
		||||
     */
 | 
			
		||||
    long readRam(int address, int n) {
 | 
			
		||||
        long v = 0;
 | 
			
		||||
 | 
			
		||||
        for (int i=0; i<n; i++) {
 | 
			
		||||
            v |= (long) (ram[address + i] & 0xFF) << (8 * i);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return v;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Write {@code} value to RAM
 | 
			
		||||
     *
 | 
			
		||||
     * @param address the address of first byte
 | 
			
		||||
     * @param n number of bytes of value, max 8
 | 
			
		||||
     * @param value the value
 | 
			
		||||
     */
 | 
			
		||||
    void writeRam(int address, int n, long value) {
 | 
			
		||||
        for (int i=0; i<n; i++) {
 | 
			
		||||
            ram[address + i] = (byte) (value >> (8 * i) & 0xFF);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										202
									
								
								src/main/java/eu/m724/CPU.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										202
									
								
								src/main/java/eu/m724/CPU.java
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,202 @@
 | 
			
		|||
package eu.m724;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Represents a rv32i CPU
 | 
			
		||||
 */
 | 
			
		||||
public class CPU {
 | 
			
		||||
    private final int xsize = 32;
 | 
			
		||||
    private final int[] register = new int[32];
 | 
			
		||||
 | 
			
		||||
    private AddressSpace addressSpace;
 | 
			
		||||
    private int programCounter;
 | 
			
		||||
 | 
			
		||||
    public void init(AddressSpace addressSpace) {
 | 
			
		||||
        this.addressSpace = addressSpace; // TODO should addressspace really be linked
 | 
			
		||||
 | 
			
		||||
        register[2] = addressSpace.romSize + addressSpace.ramSize;
 | 
			
		||||
        programCounter = addressSpace.romBase;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public int getNextInstruction() {
 | 
			
		||||
        if (programCounter > addressSpace.romSize - 1)
 | 
			
		||||
            throw new NullPointerException();
 | 
			
		||||
 | 
			
		||||
        int inst = (int) addressSpace.readRom(programCounter, 4);
 | 
			
		||||
        programCounter += 4;
 | 
			
		||||
        return inst;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public boolean executeNextInstruction() {
 | 
			
		||||
        try {
 | 
			
		||||
            executeInstruction(getNextInstruction());
 | 
			
		||||
        } catch (NullPointerException e) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void executeInstruction(int instruction) {
 | 
			
		||||
        register[0] = 0x0; // so it's not signed
 | 
			
		||||
        int opcode = instruction & 0x7F;
 | 
			
		||||
        int rd = instruction >> 7 & 0x1F;
 | 
			
		||||
 | 
			
		||||
        if (opcode != 0) {
 | 
			
		||||
            System.out.println();
 | 
			
		||||
            System.out.println("Instruction: " + Integer.toBinaryString(instruction));
 | 
			
		||||
            System.out.println("Opcode: " + Integer.toBinaryString(opcode));
 | 
			
		||||
            System.out.println("Destination register: " + Integer.toBinaryString(rd));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (opcode == 0b0010011) { // OP-IMM for Integer Register-Immediate Instructions (I type)
 | 
			
		||||
            int funct3 = instruction >> 12 & 0x7;
 | 
			
		||||
            int rs1 = instruction >> 15 & 0x1F;
 | 
			
		||||
            int imm = instruction >> 20 & 0xFFF;
 | 
			
		||||
 | 
			
		||||
            if (funct3 == 0b000) { // ADDI
 | 
			
		||||
                System.out.printf("ADDI: %d #%d + %d imm = #%d\n", register[rs1], rs1, imm, rd);
 | 
			
		||||
 | 
			
		||||
                register[rd] = register[rs1] + imm;
 | 
			
		||||
            } else if (funct3 == 0b010) { // SLTI
 | 
			
		||||
                System.out.println("SLTI");
 | 
			
		||||
            } else if (funct3 == 0b011) { // SLTIU
 | 
			
		||||
                System.out.println("SLTIU");
 | 
			
		||||
            } else if (funct3 == 0b100) { // XORI
 | 
			
		||||
                System.out.println("XORI");
 | 
			
		||||
            } else if (funct3 == 0b110) { // ORI
 | 
			
		||||
                System.out.println("ORI");
 | 
			
		||||
            } else if (funct3 == 0b111) { // ANDI
 | 
			
		||||
                System.out.println("ANDI");
 | 
			
		||||
            } else if (funct3 == 0b001) { // SLLI
 | 
			
		||||
                System.out.println("SLLI");
 | 
			
		||||
            } else if (funct3 == 0b101) { // SRLI / SRAI
 | 
			
		||||
                int funct7 = instruction >> 25 & 0x7F;
 | 
			
		||||
 | 
			
		||||
                if (funct7 == 0b0000000) { // SRLI
 | 
			
		||||
                    System.out.println("SRLI");
 | 
			
		||||
                } else if (funct7 == 0b0100000) { // SRAI
 | 
			
		||||
                    System.out.println("SRAI");
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        } else if (opcode == 0b0110111) { // LUI load upper immediate (U type)
 | 
			
		||||
 | 
			
		||||
        } else if (opcode == 0b0010111) { // AUIPC (add upper immediate to pc) (U type)
 | 
			
		||||
 | 
			
		||||
        } else if (opcode == 0b0110011) { // OP for Integer Register-Register Operations (R type)
 | 
			
		||||
            int funct3 = instruction >> 12 & 0x7;
 | 
			
		||||
 | 
			
		||||
            if (funct3 == 0b000) { // ADD / SUB
 | 
			
		||||
                int funct7 = instruction >> 25 & 0x7F;
 | 
			
		||||
 | 
			
		||||
                if (funct7 == 0b0000000) { // ADD
 | 
			
		||||
                    int rs1 = instruction >> 15 & 0x1F;
 | 
			
		||||
                    int rs2 = instruction >> 20 & 0x1F;
 | 
			
		||||
 | 
			
		||||
                    int sum = register[rs1] + register[rs2] & 0xFF; // to overflow
 | 
			
		||||
 | 
			
		||||
                    System.out.printf("ADD: %d #%d + %d #%d = %d #%d\n", register[rs1], rs1, register[rs2], rs2, sum, rd);
 | 
			
		||||
 | 
			
		||||
                    register[rd] = sum;
 | 
			
		||||
                } else if (funct7 == 0b0100000) { // SUB
 | 
			
		||||
                    System.out.println("SUB");
 | 
			
		||||
                }
 | 
			
		||||
            } else if (funct3 == 0b001) { // SLL
 | 
			
		||||
 | 
			
		||||
            } else if (funct3 == 0b010) { // SLT
 | 
			
		||||
 | 
			
		||||
            } else if (funct3 == 0b011) { // SLTU
 | 
			
		||||
 | 
			
		||||
            } else if (funct3 == 0b100) { // XOR
 | 
			
		||||
 | 
			
		||||
            } else if (funct3 == 0b101) { // SRL / SRA
 | 
			
		||||
                int funct7 = instruction >> 25 & 0x7F;
 | 
			
		||||
 | 
			
		||||
                if (funct7 == 0b0000000) { // SRL
 | 
			
		||||
 | 
			
		||||
                } else if (funct7 == 0b0100000) { // SRA
 | 
			
		||||
 | 
			
		||||
                }
 | 
			
		||||
            } else if (funct3 == 0b110) { // OR
 | 
			
		||||
 | 
			
		||||
            } else if (funct3 == 0b111) { // AND
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
        } else if (opcode == 0b1101111) { // JAL for unconditional jump (J type)
 | 
			
		||||
 | 
			
		||||
        } else if (opcode == 0b1100111) { // JALR for unconditional jump and link register (I type)
 | 
			
		||||
 | 
			
		||||
        } else if (opcode == 0b1100011) { // BRANCH instruction (B type)
 | 
			
		||||
            int funct3 = instruction >> 12 & 0x1F;
 | 
			
		||||
 | 
			
		||||
            if (funct3 == 0b000) { // BEQ
 | 
			
		||||
 | 
			
		||||
            } else if (funct3 == 0b001) { // BNE
 | 
			
		||||
 | 
			
		||||
            } else if (funct3 == 0b100) { // BLT
 | 
			
		||||
 | 
			
		||||
            } else if (funct3 == 0b101) { // BGE
 | 
			
		||||
 | 
			
		||||
            } else if (funct3 == 0b110) { // BLTU
 | 
			
		||||
 | 
			
		||||
            } else if (funct3 == 0b111) { // BGEU
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
        } else if (opcode == 0b0000011) { // LOAD instruction (I type)
 | 
			
		||||
            int funct3 = instruction >> 12 & 0x1F;
 | 
			
		||||
 | 
			
		||||
            if (funct3 == 0b000) { // LB
 | 
			
		||||
 | 
			
		||||
            } else if (funct3 == 0b001) { // LH
 | 
			
		||||
 | 
			
		||||
            } else if (funct3 == 0b010) { // LW
 | 
			
		||||
 | 
			
		||||
            } else if (funct3 == 0b100) { // LBU
 | 
			
		||||
 | 
			
		||||
            } else if (funct3 == 0b101) { // LHU
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
        } else if (opcode == 0b0100011) { // STORE instruction (S type)
 | 
			
		||||
            int funct3 = instruction >> 12 & 0x1F;
 | 
			
		||||
 | 
			
		||||
            if (funct3 == 0b000) { // SB
 | 
			
		||||
 | 
			
		||||
            } else if (funct3 == 0b001) { // SH
 | 
			
		||||
 | 
			
		||||
            } else if (funct3 == 0b010) { // SW
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
        } else if (opcode == 0b0001111) { // MISC-MEM for Memory Ordering Instructions (I type)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        } else if (opcode == 0b1110011) { // SYSTEM instructions (I type)
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Set a register to a value
 | 
			
		||||
     *
 | 
			
		||||
     * @param index the index of the register
 | 
			
		||||
     * @param value the value
 | 
			
		||||
     */
 | 
			
		||||
    public void setRegister(int index, int value) {
 | 
			
		||||
        register[index] = value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get a register's value
 | 
			
		||||
     *
 | 
			
		||||
     * @param index the index of the register
 | 
			
		||||
     */
 | 
			
		||||
    public int getRegister(int index) {
 | 
			
		||||
        return register[index];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void dumpRegisters() { // TODO debug function
 | 
			
		||||
        System.out.print("Dump of registers");
 | 
			
		||||
        for (int i=0; i<register.length; i++) {
 | 
			
		||||
            if (i % 8 == 0) System.out.println();
 | 
			
		||||
            System.out.printf("#%d: %d (0x%s) | ", i, register[i], Integer.toHexString(register[i]));
 | 
			
		||||
        }
 | 
			
		||||
        System.out.println();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										19
									
								
								src/main/java/eu/m724/Main.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/main/java/eu/m724/Main.java
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,19 @@
 | 
			
		|||
package eu.m724;
 | 
			
		||||
 | 
			
		||||
import java.util.Base64;
 | 
			
		||||
 | 
			
		||||
public class Main {
 | 
			
		||||
    public static void main(String[] args) {
 | 
			
		||||
        AddressSpace addressSpace = new AddressSpace(1024, 1024); // 1 KiB
 | 
			
		||||
        byte[] program = Base64.getDecoder().decode("kw5QABMPUAKzD98B");
 | 
			
		||||
        addressSpace.initRom(program);
 | 
			
		||||
 | 
			
		||||
        CPU cpu = new CPU();
 | 
			
		||||
        cpu.init(addressSpace);
 | 
			
		||||
 | 
			
		||||
        while (cpu.executeNextInstruction()) { }
 | 
			
		||||
 | 
			
		||||
        System.out.println("\nEnd of program");
 | 
			
		||||
        cpu.dumpRegisters();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										9
									
								
								src/main/java/eu/m724/Memory.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/main/java/eu/m724/Memory.java
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,9 @@
 | 
			
		|||
package eu.m724;
 | 
			
		||||
 | 
			
		||||
public class Memory {
 | 
			
		||||
    private byte[] memory;
 | 
			
		||||
 | 
			
		||||
    public Memory(int sizeBytes) {
 | 
			
		||||
        memory = new byte[sizeBytes];
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue