diff --git a/build.xml b/build.xml index 90a5adb..1cd8036 100644 --- a/build.xml +++ b/build.xml @@ -1,7 +1,6 @@ @@ -164,12 +163,13 @@ - - - - - - + + + + + + + diff --git a/ivy.xml b/ivy.xml index 553ee84..5004d1c 100644 --- a/ivy.xml +++ b/ivy.xml @@ -13,6 +13,9 @@ + + + diff --git a/src/il/co/codeguru/corewars_riscv/ConsoleMain.java b/src/il/co/codeguru/corewars_riscv/ConsoleMain.java index ac042ef..c87dd49 100644 --- a/src/il/co/codeguru/corewars_riscv/ConsoleMain.java +++ b/src/il/co/codeguru/corewars_riscv/ConsoleMain.java @@ -1,24 +1,30 @@ package il.co.codeguru.corewars_riscv; +import il.co.codeguru.corewars_riscv.features.Feature; +import il.co.codeguru.corewars_riscv.features.FeatureSet; import il.co.codeguru.corewars_riscv.gui.PlayersPanel; -import il.co.codeguru.corewars_riscv.utils.Logger; import il.co.codeguru.corewars_riscv.war.Competition; import il.co.codeguru.corewars_riscv.war.WarriorGroup; import il.co.codeguru.corewars_riscv.war.WarriorRepository; import java.io.*; import java.nio.file.Files; -import java.util.ArrayList; -import java.util.List; -import java.util.Properties; +import java.util.*; public class ConsoleMain { public static void main(String[] args) { if (args.length < 1) { - System.out.println("Usage: " + System.getProperty("sun.java.command").split(" ")[0] + " path-to-warriors"); + System.out.println("Usage: " + System.getProperty("sun.java.command").split(" ")[0] + " path-to-warriors" + "[--list-features]"); System.exit(0); } - Logger.outputToStdout(); + + if(Arrays.asList(args).contains("--list-features")) { + for(Map.Entry feature : FeatureSet.getAllFeatures().getRegisterdFeatures()) { + System.out.println(feature.getKey()); + } + System.exit(0); + } + Properties config = loadConfig("config.properties"); List binaries = loadBinaryFiles(args[0]); @@ -40,9 +46,6 @@ public static void main(String[] args) { System.out.println(group.getName() + ":" + group.getGroupScore()); } - System.out.println("Working Directory = " + - System.getProperty("user.dir")); - outputRepoToFile( competition.getWarriorRepository(), config.getProperty("OUTPUT_FILE") @@ -61,11 +64,16 @@ public static Competition setupCompetition(List binaries, Pro ); if(!ok) throw new RuntimeException("Failed to load warriors"); + FeatureSet features = FeatureSet.getAllFeatures(); + features.getRegisterdFeatures().stream() + .filter(e -> config.getProperty(e.getKey(), "false").equals("true")) + .forEach(e -> e.getValue().enable()); + competition.runCompetition( 100, competition.getWarriorRepository().getNumberOfGroups(), false, - config.getProperty("NEW_MEMORY", "false").equals("true") + features.getEnabledFeatures() ); return competition; } @@ -84,7 +92,7 @@ public static List loadBinaryFiles(String path) { File folder = new File(path); File[] teamDirList = folder.listFiles(); if (teamDirList == null) { - System.out.println(path + " is not a valid path or doesn't exist"); + System.err.println(path + " is not a valid path or doesn't exist"); System.exit(1); } List ans = new ArrayList<>(teamDirList.length); @@ -141,7 +149,7 @@ public static Properties loadConfig(String filename) try { is = new FileInputStream(filename); } catch (FileNotFoundException ex) { - System.out.println("WARNING: Config not found!"); + System.err.println("WARNING: Config not found!"); return config; } try { diff --git a/src/il/co/codeguru/corewars_riscv/cpu/riscv/CpuRiscV.java b/src/il/co/codeguru/corewars_riscv/cpu/riscv/CpuRiscV.java index 565d9d0..d6e3e0c 100644 --- a/src/il/co/codeguru/corewars_riscv/cpu/riscv/CpuRiscV.java +++ b/src/il/co/codeguru/corewars_riscv/cpu/riscv/CpuRiscV.java @@ -1,19 +1,26 @@ package il.co.codeguru.corewars_riscv.cpu.riscv; import il.co.codeguru.corewars_riscv.cpu.exceptions.CpuException; -import il.co.codeguru.corewars_riscv.cpu.riscv.instruction_formats.InstructionFormatBase; import il.co.codeguru.corewars_riscv.cpu.riscv.rv32c.InstructionDecoderRv32c; import il.co.codeguru.corewars_riscv.cpu.riscv.rv32c.instruction_formats.CInstructionFormatBase; +import il.co.codeguru.corewars_riscv.cpu.riscv.rv32i.InstructionDecoder32I; +import il.co.codeguru.corewars_riscv.cpu.riscv.rv32i.InstructionRunner32I; +import il.co.codeguru.corewars_riscv.cpu.riscv.rv32i.instruction_formats.InstructionFormatBase; +import il.co.codeguru.corewars_riscv.features.Syscall; import il.co.codeguru.corewars_riscv.memory.Memory; import il.co.codeguru.corewars_riscv.memory.MemoryException; +import java.util.HashMap; +import java.util.Map; + public class CpuRiscV { private CpuStateRiscV state; private Memory Memory; - private InstructionDecoder decoder; + private InstructionDecoder32I decoder; private InstructionDecoderRv32c cDecoder; - private InstructionRunner runner; + private InstructionRunner32I runner; + private Map syscalls = new HashMap<>(); public CpuStateRiscV getState() { return state; @@ -27,9 +34,9 @@ public CpuRiscV(CpuStateRiscV state, Memory Memory) { this.state = state; this.Memory = Memory; - this.decoder = new InstructionDecoder(); + this.decoder = new InstructionDecoder32I(); this.cDecoder = new InstructionDecoderRv32c(); - this.runner = new InstructionRunner(this); + this.runner = new InstructionRunner32I(this); } public void nextOpcode() throws CpuException, MemoryException @@ -49,9 +56,9 @@ public void nextOpcode() throws CpuException, MemoryException private boolean tryRv32cSet() throws CpuException, MemoryException { - short rawComppressedCode = Memory.loadHalfWord(state.getPc()); - CInstructionFormatBase commpressedInstruction = new CInstructionFormatBase(rawComppressedCode); - Instruction i = cDecoder.decode(commpressedInstruction); + short rawCompressedCode = Memory.loadHalfWord(state.getPc()); + CInstructionFormatBase compressedInstruction = new CInstructionFormatBase(rawCompressedCode); + Instruction i = cDecoder.decode(compressedInstruction); if(i!=null) { i.execute(runner); @@ -60,4 +67,12 @@ private boolean tryRv32cSet() throws CpuException, MemoryException return i!=null; } + public void registerSyscall(int id, Syscall syscall) { + this.syscalls.put(id, syscall); + } + + public void callSyscall(int id) { + this.syscalls.get(id).call(this); + } + } diff --git a/src/il/co/codeguru/corewars_riscv/cpu/riscv/Instruction.java b/src/il/co/codeguru/corewars_riscv/cpu/riscv/Instruction.java index 84f209f..d4651c7 100644 --- a/src/il/co/codeguru/corewars_riscv/cpu/riscv/Instruction.java +++ b/src/il/co/codeguru/corewars_riscv/cpu/riscv/Instruction.java @@ -1,7 +1,8 @@ package il.co.codeguru.corewars_riscv.cpu.riscv; import il.co.codeguru.corewars_riscv.cpu.exceptions.CpuException; -import il.co.codeguru.corewars_riscv.cpu.riscv.instruction_formats.InstructionFormatBase; +import il.co.codeguru.corewars_riscv.cpu.riscv.rv32i.instruction_formats.InstructionFormatBase; +import il.co.codeguru.corewars_riscv.cpu.riscv.rv32i.InstructionRunner32I; import il.co.codeguru.corewars_riscv.memory.MemoryException; public class Instruction { @@ -28,14 +29,14 @@ public InstructionFormatBase getFormat() { return instructionFormat; } - public void execute(InstructionRunner runner) throws CpuException, MemoryException + public void execute(InstructionRunner32I runner) throws CpuException, MemoryException { action.apply(instructionFormat, runner); } @FunctionalInterface public interface Action{ - void apply(InstructionFormatBase i, InstructionRunner runner) throws CpuException, MemoryException; + void apply(InstructionFormatBase i, InstructionRunner32I runner) throws CpuException, MemoryException; } public static class InstructionInfo { diff --git a/src/il/co/codeguru/corewars_riscv/cpu/riscv/InstructionDecoder.java b/src/il/co/codeguru/corewars_riscv/cpu/riscv/InstructionDecoder.java index dde1909..937c076 100644 --- a/src/il/co/codeguru/corewars_riscv/cpu/riscv/InstructionDecoder.java +++ b/src/il/co/codeguru/corewars_riscv/cpu/riscv/InstructionDecoder.java @@ -1,200 +1,5 @@ package il.co.codeguru.corewars_riscv.cpu.riscv; -import il.co.codeguru.corewars_riscv.cpu.exceptions.InvalidOpcodeException; -import il.co.codeguru.corewars_riscv.cpu.riscv.instruction_formats.*; - -public class InstructionDecoder { - public Instruction decode(InstructionFormatBase i) throws InvalidOpcodeException - { - switch(i.getOpcode()) - { - case RV32I.OpcodeTypes.LOAD: - return loadOpcode(i); - case RV32I.OpcodeTypes.OP_IMM: - return immOpcode(i); - case RV32I.OpcodeTypes.AUIPC: - return new Instruction(RV32I.Opcodes.Auipc, new InstructionFormatU(i), - (InstructionFormatBase format, InstructionRunner runner) -> runner.auipc(new InstructionFormatU(format))); - case RV32I.OpcodeTypes.STORE: - return storeOpcode(i); - case RV32I.OpcodeTypes.OP: - return registerOpcode(i); - case RV32I.OpcodeTypes.LUI: - return new Instruction(RV32I.Opcodes.Lui, new InstructionFormatU(i), - (InstructionFormatBase format, InstructionRunner runner) -> runner.lui(new InstructionFormatU(format))); - case RV32I.OpcodeTypes.BRANCH: - return branchOpcode(i); - case RV32I.OpcodeTypes.JALR: - return new Instruction(RV32I.Opcodes.Jalr, new InstructionFormatI(i), - (InstructionFormatBase format, InstructionRunner runner) -> runner.jalr(new InstructionFormatI(format))); - case RV32I.OpcodeTypes.JAL: - return new Instruction(RV32I.Opcodes.Jal, new InstructionFormatUJ(i), - (InstructionFormatBase format, InstructionRunner runner) -> runner.jal(new InstructionFormatUJ(format))); - default: - throw new InvalidOpcodeException(); - } - } - - private Instruction branchOpcode(InstructionFormatBase i) throws InvalidOpcodeException { - InstructionFormatSB sb = new InstructionFormatSB(i); - switch(sb.getFunct3()) - { - case 0: - return new Instruction(RV32I.Opcodes.Beq, sb, - (InstructionFormatBase format, InstructionRunner runner) -> runner.beq(new InstructionFormatSB(format))); - case 1: - return new Instruction(RV32I.Opcodes.Bne, sb, - (InstructionFormatBase format, InstructionRunner runner) -> runner.bne(new InstructionFormatSB(format))); - case 4: - return new Instruction(RV32I.Opcodes.Blt, sb, - (InstructionFormatBase format, InstructionRunner runner) -> runner.blt(new InstructionFormatSB(format))); - case 5: - return new Instruction(RV32I.Opcodes.Bge, sb, - (InstructionFormatBase format, InstructionRunner runner) -> runner.bge(new InstructionFormatSB(format))); - case 6: - return new Instruction(RV32I.Opcodes.Bltu, sb, - (InstructionFormatBase format, InstructionRunner runner) -> runner.bltu(new InstructionFormatSB(format))); - case 7: - return new Instruction(RV32I.Opcodes.Bgeu, sb, - (InstructionFormatBase format, InstructionRunner runner) -> runner.bgeu(new InstructionFormatSB(format))); - default: - throw new InvalidOpcodeException(); - } - } - - private Instruction registerOpcode(InstructionFormatBase i) throws InvalidOpcodeException { - InstructionFormatR ir = new InstructionFormatR(i); - switch(ir.getFunct3()) - { - case 0: - switch (ir.getFunct7()) - { - case 0: - return new Instruction(RV32I.Opcodes.Add, ir, - (InstructionFormatBase format, InstructionRunner runner) -> runner.add(new InstructionFormatR(format))); - case 32: - return new Instruction(RV32I.Opcodes.Sub, ir, - (InstructionFormatBase format, InstructionRunner runner) -> runner.sub(new InstructionFormatR(format))); - default: - throw new InvalidOpcodeException(); - } - case 1: - return new Instruction(RV32I.Opcodes.Sll, ir, - (InstructionFormatBase format, InstructionRunner runner) -> runner.sll(new InstructionFormatR(format))); - case 2: - return new Instruction(RV32I.Opcodes.Slt, ir, - (InstructionFormatBase format, InstructionRunner runner) -> runner.slt(new InstructionFormatR(format))); - case 3: - return new Instruction(RV32I.Opcodes.Sltu, ir, - (InstructionFormatBase format, InstructionRunner runner) -> runner.sltu(new InstructionFormatR(format))); - case 4: - return new Instruction(RV32I.Opcodes.Xor, ir, - (InstructionFormatBase format, InstructionRunner runner) -> runner.xor(new InstructionFormatR(format))); - case 5: - switch(ir.getFunct7()) - { - case 0: - return new Instruction(RV32I.Opcodes.Srl, ir, - (InstructionFormatBase format, InstructionRunner runner) -> runner.srl(new InstructionFormatR(format))); - case 32: - return new Instruction(RV32I.Opcodes.Sra, ir, - (InstructionFormatBase format, InstructionRunner runner) -> runner.sra(new InstructionFormatR(format))); - default: - throw new InvalidOpcodeException(); - } - case 6: - return new Instruction(RV32I.Opcodes.Or, ir, - (InstructionFormatBase format, InstructionRunner runner) -> runner.or(new InstructionFormatR(format))); - case 7: - return new Instruction(RV32I.Opcodes.And, ir, - (InstructionFormatBase format, InstructionRunner runner) -> runner.and(new InstructionFormatR(format))); - default: - throw new InvalidOpcodeException(); - } - } - - private Instruction storeOpcode(InstructionFormatBase i) throws InvalidOpcodeException { - InstructionFormatS is = new InstructionFormatS(i); - switch(is.getFunct3()) - { - case 0: - return new Instruction(RV32I.Opcodes.Sb, is, - (InstructionFormatBase format, InstructionRunner runner) -> runner.sb(new InstructionFormatS(format))); - case 1: - return new Instruction(RV32I.Opcodes.Sh, is, - (InstructionFormatBase format, InstructionRunner runner) -> runner.sh(new InstructionFormatS(format))); - case 2: - return new Instruction(RV32I.Opcodes.Sw, is, - (InstructionFormatBase format, InstructionRunner runner) -> runner.sw(new InstructionFormatS(format))); - default: - throw new InvalidOpcodeException(); - } - } - - private Instruction immOpcode(InstructionFormatBase i) throws InvalidOpcodeException { - InstructionFormatI ii = new InstructionFormatI(i); - switch (ii.getFunct3()) - { - case 0x0: - return new Instruction(RV32I.Opcodes.Addi, ii, - (InstructionFormatBase format, InstructionRunner runner) -> runner.addi(new InstructionFormatI(format))); - case 0x1: - return new Instruction(RV32I.Opcodes.Slli, ii, - (InstructionFormatBase format, InstructionRunner runner) -> runner.slli(new InstructionFormatI(format))); - case 0x2: - return new Instruction(RV32I.Opcodes.Slti, ii, - (InstructionFormatBase format, InstructionRunner runner) -> runner.slti(new InstructionFormatI(format))); - case 0x3: - return new Instruction(RV32I.Opcodes.Sltiu, ii, - (InstructionFormatBase format, InstructionRunner runner) -> runner.sltiu(new InstructionFormatI(format))); - case 0x4: - return new Instruction(RV32I.Opcodes.Xori, ii, - (InstructionFormatBase format, InstructionRunner runner) -> runner.xori(new InstructionFormatI(format))); - case 0x5: - int imm = ii.getImmediate() >> 5; - switch(imm) - { - case 0: - return new Instruction(RV32I.Opcodes.Srli, ii, - (InstructionFormatBase format, InstructionRunner runner) -> runner.srli(new InstructionFormatI(format))); - case 32: - return new Instruction(RV32I.Opcodes.Srai, ii, - (InstructionFormatBase format, InstructionRunner runner) -> runner.srai(new InstructionFormatI(format))); - default: - throw new InvalidOpcodeException(); - } - case 0x6: - return new Instruction(RV32I.Opcodes.Ori, ii, - (InstructionFormatBase format, InstructionRunner runner) -> runner.ori(new InstructionFormatI(format))); - case 0x7: - return new Instruction(RV32I.Opcodes.Andi, ii, - (InstructionFormatBase format, InstructionRunner runner) -> runner.andi(new InstructionFormatI(format))); - default: - throw new InvalidOpcodeException(); - } - } - - private Instruction loadOpcode(InstructionFormatBase i) throws InvalidOpcodeException { - InstructionFormatI ii = new InstructionFormatI(i); - switch(ii.getFunct3()) - { - case 0x0: - return new Instruction(RV32I.Opcodes.Lb, ii, - (InstructionFormatBase format, InstructionRunner runner) -> runner.lb(new InstructionFormatI(format))); - case 0x1: - return new Instruction(RV32I.Opcodes.Lh, ii, - (InstructionFormatBase format, InstructionRunner runner) -> runner.lh(new InstructionFormatI(format))); - case 0x2: - return new Instruction(RV32I.Opcodes.Lw, ii, - (InstructionFormatBase format, InstructionRunner runner) -> runner.lw(new InstructionFormatI(format))); - case 0x4: - return new Instruction(RV32I.Opcodes.Lbu, ii, - (InstructionFormatBase format, InstructionRunner runner) -> runner.lbu(new InstructionFormatI(format))); - case 0x5: - return new Instruction(RV32I.Opcodes.Lhu, ii, - (InstructionFormatBase format, InstructionRunner runner) -> runner.lhu(new InstructionFormatI(format))); - default: - throw new InvalidOpcodeException(); - } - } +public interface InstructionDecoder { + Instruction decode(InstructionFormat format_input); } diff --git a/src/il/co/codeguru/corewars_riscv/cpu/riscv/InstructionFormat.java b/src/il/co/codeguru/corewars_riscv/cpu/riscv/InstructionFormat.java new file mode 100644 index 0000000..87552d9 --- /dev/null +++ b/src/il/co/codeguru/corewars_riscv/cpu/riscv/InstructionFormat.java @@ -0,0 +1,5 @@ +package il.co.codeguru.corewars_riscv.cpu.riscv; + +public interface InstructionFormat { + String format(Instruction.InstructionInfo info); +} diff --git a/src/il/co/codeguru/corewars_riscv/cpu/riscv/rv32c/InstructionDecoderRv32c.java b/src/il/co/codeguru/corewars_riscv/cpu/riscv/rv32c/InstructionDecoderRv32c.java index c8915c9..83069d0 100644 --- a/src/il/co/codeguru/corewars_riscv/cpu/riscv/rv32c/InstructionDecoderRv32c.java +++ b/src/il/co/codeguru/corewars_riscv/cpu/riscv/rv32c/InstructionDecoderRv32c.java @@ -1,14 +1,17 @@ package il.co.codeguru.corewars_riscv.cpu.riscv.rv32c; import il.co.codeguru.corewars_riscv.cpu.riscv.Instruction; -import il.co.codeguru.corewars_riscv.cpu.riscv.InstructionRunner; -import il.co.codeguru.corewars_riscv.cpu.riscv.RV32I; -import il.co.codeguru.corewars_riscv.cpu.riscv.instruction_formats.*; +import il.co.codeguru.corewars_riscv.cpu.riscv.InstructionDecoder; +import il.co.codeguru.corewars_riscv.cpu.riscv.InstructionFormat; +import il.co.codeguru.corewars_riscv.cpu.riscv.rv32i.InstructionRunner32I; +import il.co.codeguru.corewars_riscv.cpu.riscv.rv32i.RV32I; +import il.co.codeguru.corewars_riscv.cpu.riscv.rv32i.instruction_formats.*; import il.co.codeguru.corewars_riscv.cpu.riscv.rv32c.instruction_formats.*; -public class InstructionDecoderRv32c { +public class InstructionDecoderRv32c implements InstructionDecoder { - public Instruction decode(CInstructionFormatBase i) { + public Instruction decode(InstructionFormat formatInput) { + CInstructionFormatBase i = (CInstructionFormatBase) formatInput; CInstructionFormatCI ci = new CInstructionFormatCI(i); CInstructionFormatCS cs = new CInstructionFormatCS(i); CInstructionFormatCB cb = new CInstructionFormatCB(i); @@ -33,7 +36,7 @@ public Instruction decode(CInstructionFormatBase i) { int bit54 = (ciw.getImmediate() >> 6) & 3; int nzuimm = (bit2 | (bit3 << 1) | (bit54 << 2) | (bit96 << 4)) << 2; return new Instruction(RV32C.Opcodes.CADDI4SPN, RV32I.instructionI(RV32I.Opcodes.Addi, ciw.getRd(), 2, nzuimm), - (InstructionFormatBase format, InstructionRunner runner) -> runner.addi(new InstructionFormatI(format))); + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.addi(new InstructionFormatI(format))); case 2: /* * C.LW loads a 32-bit value from memory into register rd. It computes @@ -43,7 +46,7 @@ public Instruction decode(CInstructionFormatBase i) { */ CInstructionFormatCL cl = new CInstructionFormatCL(i); return new Instruction(RV32C.Opcodes.CLW, RV32I.instructionI(RV32I.Opcodes.Lw, cl.getRd(), cl.getRs1(), cl.getImmediate()), - (InstructionFormatBase format, InstructionRunner runner) -> runner.lw(new InstructionFormatI(format))); + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.lw(new InstructionFormatI(format))); case 6: /* * C.SW stores a 32-bit value in register rs2 to memory. It computes an @@ -52,7 +55,7 @@ public Instruction decode(CInstructionFormatBase i) { * It expands to sw rs2, offset[6:2](rs1). */ return new Instruction(RV32C.Opcodes.CSW, RV32I.instructionS(RV32I.Opcodes.Sw, cs.getRs1(), cs.getRs2(), cs.getImmediate()), - (InstructionFormatBase format, InstructionRunner runner) -> runner.sw(new InstructionFormatS(format))); + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.sw(new InstructionFormatS(format))); } case RV32C.OpcodeTypes.C1: @@ -67,7 +70,7 @@ public Instruction decode(CInstructionFormatBase i) { * C.ADDI is only valid when rd != x0. */ return new Instruction(RV32C.Opcodes.CADDI, RV32I.instructionI(RV32I.Opcodes.Addi, ci.getRs1(), ci.getRs1(), ci.getImmediate()), - (InstructionFormatBase format, InstructionRunner runner) -> runner.addi(new InstructionFormatI(format))); + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.addi(new InstructionFormatI(format))); } case 1: @@ -77,7 +80,7 @@ public Instruction decode(CInstructionFormatBase i) { * (pc+2) to the link register, x1. C.JAL expands to "jal x1, offset[11:1]". */ return new Instruction(RV32C.Opcodes.CJAL, RV32I.instructionUJ(RV32I.Opcodes.Jal, 1, cj.getImmediate()), - (InstructionFormatBase format, InstructionRunner runner) -> runner.jal(new InstructionFormatUJ(format), 2)); + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.jal(new InstructionFormatUJ(format), 2)); case 2: /* * C.LI loads the sign-extended 6-bit immediate, imm, into @@ -85,7 +88,7 @@ public Instruction decode(CInstructionFormatBase i) { * C.LI expands into "addi rd, x0, imm[5:0]". */ return new Instruction(RV32C.Opcodes.CLI, RV32I.instructionI(RV32I.Opcodes.Addi, ci.getRs1(), 0, ci.getImmediate()), - (InstructionFormatBase format, InstructionRunner runner) -> runner.addi(new InstructionFormatI(format))); + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.addi(new InstructionFormatI(format))); case 3: if (ci.getRs1() == 2) { /* @@ -105,7 +108,7 @@ public Instruction decode(CInstructionFormatBase i) { int nzimm = (bit4 | (bit5 << 1) | (bit6 << 2) | (bits78 << 3) | (bit9 << 5)) << 4; return new Instruction(RV32C.Opcodes.CADDI16SP, RV32I.instructionI(RV32I.Opcodes.Addi, 2, 2, nzimm), - (InstructionFormatBase format, InstructionRunner runner) -> runner.addi(new InstructionFormatI(format))); + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.addi(new InstructionFormatI(format))); } else if (ci.getRs1() != 0) { /* * C.LUI loads the non-zero 6-bit immediate field into bits 17--12 of the @@ -116,7 +119,7 @@ public Instruction decode(CInstructionFormatBase i) { * C.LUI expands into "lui rd, nzimm[17:12]". */ return new Instruction(RV32C.Opcodes.CLUI, RV32I.instructionU(RV32I.Opcodes.Lui, ci.getRs1(), ci.getImmediate()), - (InstructionFormatBase format, InstructionRunner runner) -> runner.lui(new InstructionFormatU(format))); + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.lui(new InstructionFormatU(format))); } case 4: @@ -136,7 +139,7 @@ public Instruction decode(CInstructionFormatBase i) { * "srli rd, rd, 64". */ return new Instruction(RV32C.Opcodes.CSRLI, RV32I.instructionI(RV32I.Opcodes.Srli, cb.getRs1(), cb.getRs1(), cb.getImmediate()), - (InstructionFormatBase format, InstructionRunner runner) -> runner.srli(new InstructionFormatI(format))); + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.srli(new InstructionFormatI(format))); case 1: /* * C.SRAI is defined analogously to C.SRLI, but instead performs an arithmetic @@ -144,7 +147,7 @@ public Instruction decode(CInstructionFormatBase i) { * C.SRAI expands to "srai rd, rd, shamt[5:0]". */ return new Instruction(RV32C.Opcodes.CSRAI, RV32I.instructionI(RV32I.Opcodes.Srai, cb.getRs1(), cb.getRs1(), cb.getImmediate()), - (InstructionFormatBase format, InstructionRunner runner) -> runner.srai(new InstructionFormatI(format))); + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.srai(new InstructionFormatI(format))); case 2: /* * C.ANDI is a CB-format instruction that computes the bitwise AND of @@ -153,7 +156,7 @@ public Instruction decode(CInstructionFormatBase i) { * C.ANDI expands to "andi rd, rd, imm[5:0]". */ return new Instruction(RV32C.Opcodes.CANDI, RV32I.instructionI(RV32I.Opcodes.Andi, cb.getRs1(), cb.getRs1(), cb.getImmediate()), - (InstructionFormatBase format, InstructionRunner runner) -> runner.andi(new InstructionFormatI(format))); + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.andi(new InstructionFormatI(format))); } } else if (((cs.getFunct6() >> 2) & 1) == 0) { switch (cs.getFunct2()) { @@ -164,7 +167,7 @@ public Instruction decode(CInstructionFormatBase i) { * C.SUB expands into "sub rd, rd, rs2". */ return new Instruction(RV32C.Opcodes.CSUB, RV32I.instructionR(RV32I.Opcodes.Sub, cs.getRs1(), cs.getRs1(), cs.getRs2()), - (InstructionFormatBase format, InstructionRunner runner) -> runner.sub(new InstructionFormatR(format))); + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.sub(new InstructionFormatR(format))); case 1: /* * C.XOR computes the bitwise XOR of the values in registers rd @@ -172,7 +175,7 @@ public Instruction decode(CInstructionFormatBase i) { * C.XOR expands into "xor rd, rd, rs2". */ return new Instruction(RV32C.Opcodes.CXOR, RV32I.instructionR(RV32I.Opcodes.Xor, cs.getRs1(), cs.getRs1(), cs.getRs2()), - (InstructionFormatBase format, InstructionRunner runner) -> runner.xor(new InstructionFormatR(format))); + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.xor(new InstructionFormatR(format))); case 2: /* * C.OR computes the bitwise OR of the values in registers rd @@ -180,7 +183,7 @@ public Instruction decode(CInstructionFormatBase i) { * C.OR expands into "or rd, rd, rs2". */ return new Instruction(RV32C.Opcodes.COR, RV32I.instructionR(RV32I.Opcodes.Or, cs.getRs1(), cs.getRs1(), cs.getRs2()), - (InstructionFormatBase format, InstructionRunner runner) -> runner.or(new InstructionFormatR(format))); + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.or(new InstructionFormatR(format))); case 3: /* * C.AND computes the bitwise AND of the values in registers rd @@ -188,7 +191,7 @@ public Instruction decode(CInstructionFormatBase i) { * C.AND expands into "and rd, rd, rs2". */ return new Instruction(RV32C.Opcodes.CAND, RV32I.instructionR(RV32I.Opcodes.And, cs.getRs1(), cs.getRs1(), cs.getRs2()), - (InstructionFormatBase format, InstructionRunner runner) -> runner.and(new InstructionFormatR(format))); + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.and(new InstructionFormatR(format))); } } @@ -199,7 +202,7 @@ public Instruction decode(CInstructionFormatBase i) { * a +-2 KiB range. C.J expands to "jal x0, offset[11:1]". */ return new Instruction(RV32C.Opcodes.CJ, RV32I.instructionUJ(RV32I.Opcodes.Jal, 0, cj.getImmediate()), - (InstructionFormatBase format, InstructionRunner runner) -> runner.jal(new InstructionFormatUJ(format), 2)); + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.jal(new InstructionFormatUJ(format), 2)); case 6: /* * C.BEQZ performs conditional control transfers. The offset is sign-extended @@ -208,14 +211,14 @@ public Instruction decode(CInstructionFormatBase i) { * value in register rs1 is zero. It expands to "beq rs1, x0,offset[8:1]". */ return new Instruction(RV32C.Opcodes.CBEQZ, RV32I.instructionSB(RV32I.Opcodes.Beq, cb.getRs1(), 0, cb.getBranchImmediate()), - (InstructionFormatBase format, InstructionRunner runner) -> runner.beq(new InstructionFormatSB(format), 2)); + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.beq(new InstructionFormatSB(format), 2)); case 7: /* * C.BNEZ is defined analogously to C.BEQZ, but it takes the branch if rs1 contains * a nonzero value. It expands to "bne rs1, x0, offset[8:1]". */ return new Instruction(RV32C.Opcodes.CBNEZ, RV32I.instructionSB(RV32I.Opcodes.Bne, cb.getRs1(), 0, cb.getBranchImmediate()), - (InstructionFormatBase format, InstructionRunner runner) -> runner.bne(new InstructionFormatSB(format), 2)); + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.bne(new InstructionFormatSB(format), 2)); } case RV32C.OpcodeTypes.C2: @@ -232,7 +235,7 @@ public Instruction decode(CInstructionFormatBase i) { * "slli rd, rd, 64". */ return new Instruction(RV32C.Opcodes.CSLLI, RV32I.instructionI(RV32I.Opcodes.Slli, ci.getRs1(), ci.getRs1(), ci.getImmediate()), - (InstructionFormatBase format, InstructionRunner runner) -> runner.slli(new InstructionFormatI(format))); + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.slli(new InstructionFormatI(format))); case 2: /* * C.LWSP loads a 32-bit value from memory into register rd. It computes @@ -245,7 +248,7 @@ public Instruction decode(CInstructionFormatBase i) { int bit5 = (ci.getUnsignedImmediate() >> 5) & 1; int uimm = (bit42 | (bit5 << 3) | (bit76 << 4)) << 2; return new Instruction(RV32C.Opcodes.CLWSP, RV32I.instructionI(RV32I.Opcodes.Lw, ci.getRs1(), 2, uimm), - (InstructionFormatBase format, InstructionRunner runner) -> runner.lw(new InstructionFormatI(format))); + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.lw(new InstructionFormatI(format))); case 4: CInstructionFormatCR cr = new CInstructionFormatCR(i); if ((cr.getFunct4() & 1) == 1) { @@ -256,7 +259,7 @@ public Instruction decode(CInstructionFormatBase i) { * result to register rd. C.ADD expands into "add rd, rd, rs2". */ return new Instruction(RV32C.Opcodes.CADD, RV32I.instructionR(RV32I.Opcodes.Add, cr.getRs1(), cr.getRs1(), cr.getRs2()), - (InstructionFormatBase format, InstructionRunner runner) -> runner.add(new InstructionFormatR(format))); + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.add(new InstructionFormatR(format))); } else if (cr.getRs1() != 0 && cr.getRs2() == 0) { /* * C.JALR (jump and link register) performs the same operation as C.JR, @@ -265,7 +268,7 @@ public Instruction decode(CInstructionFormatBase i) { * "jalr x1, 0(rs1)". */ return new Instruction(RV32C.Opcodes.CJALR, RV32I.instructionI(RV32I.Opcodes.Jalr, 1, cr.getRs1(), 0), - (InstructionFormatBase format, InstructionRunner runner) -> runner.jalr(new InstructionFormatI(format), 2)); + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.jalr(new InstructionFormatI(format), 2)); } } else { if (cr.getRs1() != 0 && cr.getRs2() != 0) { @@ -274,14 +277,14 @@ public Instruction decode(CInstructionFormatBase i) { * expands into "add rd, x0, rs2". */ return new Instruction(RV32C.Opcodes.CMV, RV32I.instructionR(RV32I.Opcodes.Add, cr.getRs1(), 0, cr.getRs2()), - (InstructionFormatBase format, InstructionRunner runner) -> runner.add(new InstructionFormatR(format))); + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.add(new InstructionFormatR(format))); } else if (cr.getRs1() != 0 && cr.getRs2() == 0) { /* * C.JR (jump register) performs an unconditional control transfer to * the address in register rs1. C.JR expands to "jalr x0, 0(rs1)". */ return new Instruction(RV32C.Opcodes.CJR, RV32I.instructionI(RV32I.Opcodes.Jalr, 0, cr.getRs1(), 0), - (InstructionFormatBase format, InstructionRunner runner) -> runner.jalr(new InstructionFormatI(format), 2)); + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.jalr(new InstructionFormatI(format), 2)); } } @@ -295,7 +298,7 @@ public Instruction decode(CInstructionFormatBase i) { CInstructionFormatCSS css = new CInstructionFormatCSS(i); return new Instruction(RV32C.Opcodes.CSWSP, RV32I.instructionS(RV32I.Opcodes.Sw, 2, css.getRs2(), css.getWord()), - (InstructionFormatBase format, InstructionRunner runner) -> runner.sw(new InstructionFormatS(format))); + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.sw(new InstructionFormatS(format))); } } diff --git a/src/il/co/codeguru/corewars_riscv/cpu/riscv/rv32c/instruction_formats/CInstructionFormatBase.java b/src/il/co/codeguru/corewars_riscv/cpu/riscv/rv32c/instruction_formats/CInstructionFormatBase.java index c8bd0d4..3a8e3c2 100644 --- a/src/il/co/codeguru/corewars_riscv/cpu/riscv/rv32c/instruction_formats/CInstructionFormatBase.java +++ b/src/il/co/codeguru/corewars_riscv/cpu/riscv/rv32c/instruction_formats/CInstructionFormatBase.java @@ -1,13 +1,15 @@ package il.co.codeguru.corewars_riscv.cpu.riscv.rv32c.instruction_formats; import il.co.codeguru.corewars_riscv.cpu.riscv.Instruction; +import il.co.codeguru.corewars_riscv.cpu.riscv.InstructionFormat; -public class CInstructionFormatBase { +public class CInstructionFormatBase implements InstructionFormat { final protected short raw; - public CInstructionFormatBase(short raw) { - this.raw = raw; + public CInstructionFormatBase(Integer raw) { + this.raw = raw.shortValue(); } + public CInstructionFormatBase(Short raw) {this.raw = raw;} protected static int mask(int len) { diff --git a/src/il/co/codeguru/corewars_riscv/cpu/riscv/rv32i/InstructionDecoder32I.java b/src/il/co/codeguru/corewars_riscv/cpu/riscv/rv32i/InstructionDecoder32I.java new file mode 100644 index 0000000..bddf5fc --- /dev/null +++ b/src/il/co/codeguru/corewars_riscv/cpu/riscv/rv32i/InstructionDecoder32I.java @@ -0,0 +1,218 @@ +package il.co.codeguru.corewars_riscv.cpu.riscv.rv32i; + +import il.co.codeguru.corewars_riscv.cpu.exceptions.InvalidOpcodeException; +import il.co.codeguru.corewars_riscv.cpu.riscv.Instruction; +import il.co.codeguru.corewars_riscv.cpu.riscv.InstructionFormat; +import il.co.codeguru.corewars_riscv.cpu.riscv.rv32i.instruction_formats.*; + +public class InstructionDecoder32I { + public Instruction decode(InstructionFormat format_input) throws InvalidOpcodeException + { + InstructionFormatBase i = (InstructionFormatBase) format_input; + switch(i.getOpcode()) + { + case RV32I.OpcodeTypes.LOAD: + return loadOpcode(i); + case RV32I.OpcodeTypes.OP_IMM: + return immOpcode(i); + case RV32I.OpcodeTypes.AUIPC: + return new Instruction(RV32I.Opcodes.Auipc, new InstructionFormatU(i), + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.auipc(new InstructionFormatU(format))); + case RV32I.OpcodeTypes.STORE: + return storeOpcode(i); + case RV32I.OpcodeTypes.OP: + return registerOpcode(i); + case RV32I.OpcodeTypes.LUI: + return new Instruction(RV32I.Opcodes.Lui, new InstructionFormatU(i), + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.lui(new InstructionFormatU(format))); + case RV32I.OpcodeTypes.BRANCH: + return branchOpcode(i); + case RV32I.OpcodeTypes.SYS: + return sysOpcode(i); + case RV32I.OpcodeTypes.JALR: + return new Instruction(RV32I.Opcodes.Jalr, new InstructionFormatI(i), + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.jalr(new InstructionFormatI(format))); + case RV32I.OpcodeTypes.JAL: + return new Instruction(RV32I.Opcodes.Jal, new InstructionFormatUJ(i), + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.jal(new InstructionFormatUJ(format))); + default: + throw new InvalidOpcodeException(); + } + } + + private Instruction sysOpcode(InstructionFormatBase i) throws InvalidOpcodeException { + InstructionFormatI ii = new InstructionFormatI(i); + switch(ii.getFunct3()) { + case 0: + if(ii.getImmediate() == 0) { + return new Instruction(RV32I.Opcodes.Ecall, ii, + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.ecall(new InstructionFormatI(format))); + } + default: + throw new InvalidOpcodeException(); + } + } + + private Instruction branchOpcode(InstructionFormatBase i) throws InvalidOpcodeException { + InstructionFormatSB sb = new InstructionFormatSB(i); + switch(sb.getFunct3()) + { + case 0: + return new Instruction(RV32I.Opcodes.Beq, sb, + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.beq(new InstructionFormatSB(format))); + case 1: + return new Instruction(RV32I.Opcodes.Bne, sb, + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.bne(new InstructionFormatSB(format))); + case 4: + return new Instruction(RV32I.Opcodes.Blt, sb, + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.blt(new InstructionFormatSB(format))); + case 5: + return new Instruction(RV32I.Opcodes.Bge, sb, + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.bge(new InstructionFormatSB(format))); + case 6: + return new Instruction(RV32I.Opcodes.Bltu, sb, + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.bltu(new InstructionFormatSB(format))); + case 7: + return new Instruction(RV32I.Opcodes.Bgeu, sb, + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.bgeu(new InstructionFormatSB(format))); + default: + throw new InvalidOpcodeException(); + } + } + + private Instruction registerOpcode(InstructionFormatBase i) throws InvalidOpcodeException { + InstructionFormatR ir = new InstructionFormatR(i); + switch(ir.getFunct3()) + { + case 0: + switch (ir.getFunct7()) + { + case 0: + return new Instruction(RV32I.Opcodes.Add, ir, + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.add(new InstructionFormatR(format))); + case 32: + return new Instruction(RV32I.Opcodes.Sub, ir, + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.sub(new InstructionFormatR(format))); + default: + throw new InvalidOpcodeException(); + } + case 1: + return new Instruction(RV32I.Opcodes.Sll, ir, + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.sll(new InstructionFormatR(format))); + case 2: + return new Instruction(RV32I.Opcodes.Slt, ir, + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.slt(new InstructionFormatR(format))); + case 3: + return new Instruction(RV32I.Opcodes.Sltu, ir, + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.sltu(new InstructionFormatR(format))); + case 4: + return new Instruction(RV32I.Opcodes.Xor, ir, + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.xor(new InstructionFormatR(format))); + case 5: + switch(ir.getFunct7()) + { + case 0: + return new Instruction(RV32I.Opcodes.Srl, ir, + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.srl(new InstructionFormatR(format))); + case 32: + return new Instruction(RV32I.Opcodes.Sra, ir, + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.sra(new InstructionFormatR(format))); + default: + throw new InvalidOpcodeException(); + } + case 6: + return new Instruction(RV32I.Opcodes.Or, ir, + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.or(new InstructionFormatR(format))); + case 7: + return new Instruction(RV32I.Opcodes.And, ir, + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.and(new InstructionFormatR(format))); + default: + throw new InvalidOpcodeException(); + } + } + + private Instruction storeOpcode(InstructionFormatBase i) throws InvalidOpcodeException { + InstructionFormatS is = new InstructionFormatS(i); + switch(is.getFunct3()) + { + case 0: + return new Instruction(RV32I.Opcodes.Sb, is, + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.sb(new InstructionFormatS(format))); + case 1: + return new Instruction(RV32I.Opcodes.Sh, is, + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.sh(new InstructionFormatS(format))); + case 2: + return new Instruction(RV32I.Opcodes.Sw, is, + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.sw(new InstructionFormatS(format))); + default: + throw new InvalidOpcodeException(); + } + } + + private Instruction immOpcode(InstructionFormatBase i) throws InvalidOpcodeException { + InstructionFormatI ii = new InstructionFormatI(i); + switch (ii.getFunct3()) + { + case 0x0: + return new Instruction(RV32I.Opcodes.Addi, ii, + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.addi(new InstructionFormatI(format))); + case 0x1: + return new Instruction(RV32I.Opcodes.Slli, ii, + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.slli(new InstructionFormatI(format))); + case 0x2: + return new Instruction(RV32I.Opcodes.Slti, ii, + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.slti(new InstructionFormatI(format))); + case 0x3: + return new Instruction(RV32I.Opcodes.Sltiu, ii, + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.sltiu(new InstructionFormatI(format))); + case 0x4: + return new Instruction(RV32I.Opcodes.Xori, ii, + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.xori(new InstructionFormatI(format))); + case 0x5: + int imm = ii.getImmediate() >> 5; + switch(imm) + { + case 0: + return new Instruction(RV32I.Opcodes.Srli, ii, + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.srli(new InstructionFormatI(format))); + case 32: + return new Instruction(RV32I.Opcodes.Srai, ii, + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.srai(new InstructionFormatI(format))); + default: + throw new InvalidOpcodeException(); + } + case 0x6: + return new Instruction(RV32I.Opcodes.Ori, ii, + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.ori(new InstructionFormatI(format))); + case 0x7: + return new Instruction(RV32I.Opcodes.Andi, ii, + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.andi(new InstructionFormatI(format))); + default: + throw new InvalidOpcodeException(); + } + } + + private Instruction loadOpcode(InstructionFormatBase i) throws InvalidOpcodeException { + InstructionFormatI ii = new InstructionFormatI(i); + switch(ii.getFunct3()) + { + case 0x0: + return new Instruction(RV32I.Opcodes.Lb, ii, + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.lb(new InstructionFormatI(format))); + case 0x1: + return new Instruction(RV32I.Opcodes.Lh, ii, + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.lh(new InstructionFormatI(format))); + case 0x2: + return new Instruction(RV32I.Opcodes.Lw, ii, + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.lw(new InstructionFormatI(format))); + case 0x4: + return new Instruction(RV32I.Opcodes.Lbu, ii, + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.lbu(new InstructionFormatI(format))); + case 0x5: + return new Instruction(RV32I.Opcodes.Lhu, ii, + (InstructionFormatBase format, InstructionRunner32I runner) -> runner.lhu(new InstructionFormatI(format))); + default: + throw new InvalidOpcodeException(); + } + } +} diff --git a/src/il/co/codeguru/corewars_riscv/cpu/riscv/InstructionRunner.java b/src/il/co/codeguru/corewars_riscv/cpu/riscv/rv32i/InstructionRunner32I.java similarity index 96% rename from src/il/co/codeguru/corewars_riscv/cpu/riscv/InstructionRunner.java rename to src/il/co/codeguru/corewars_riscv/cpu/riscv/rv32i/InstructionRunner32I.java index 6e0ef7e..0f90483 100644 --- a/src/il/co/codeguru/corewars_riscv/cpu/riscv/InstructionRunner.java +++ b/src/il/co/codeguru/corewars_riscv/cpu/riscv/rv32i/InstructionRunner32I.java @@ -1,17 +1,22 @@ -package il.co.codeguru.corewars_riscv.cpu.riscv; +package il.co.codeguru.corewars_riscv.cpu.riscv.rv32i; -import il.co.codeguru.corewars_riscv.cpu.riscv.instruction_formats.*; +import il.co.codeguru.corewars_riscv.cpu.riscv.CpuRiscV; +import il.co.codeguru.corewars_riscv.cpu.riscv.CpuStateRiscV; +import il.co.codeguru.corewars_riscv.cpu.riscv.rv32i.instruction_formats.*; import il.co.codeguru.corewars_riscv.memory.Memory; import il.co.codeguru.corewars_riscv.memory.MemoryException; +import il.co.codeguru.corewars_riscv.utils.Logger; -public class InstructionRunner { +public class InstructionRunner32I { + private CpuRiscV cpu; private CpuStateRiscV state; private Memory memory; - public InstructionRunner(CpuRiscV cpu) { + public InstructionRunner32I(CpuRiscV cpu) { this.state = cpu.getState(); this.memory = cpu.getMemory(); + this.cpu = cpu; } /** @@ -313,6 +318,10 @@ void bgeu(InstructionFormatSB i) { } + void ecall(InstructionFormatI i) { + cpu.callSyscall(state.getReg(8)); + } + private void jump(CpuStateRiscV state, int immediate, int instructionSize) { state.setPc(state.getPc() + immediate - instructionSize); } diff --git a/src/il/co/codeguru/corewars_riscv/cpu/riscv/RV32I.java b/src/il/co/codeguru/corewars_riscv/cpu/riscv/rv32i/RV32I.java similarity index 94% rename from src/il/co/codeguru/corewars_riscv/cpu/riscv/RV32I.java rename to src/il/co/codeguru/corewars_riscv/cpu/riscv/rv32i/RV32I.java index 4e29b6a..5573625 100644 --- a/src/il/co/codeguru/corewars_riscv/cpu/riscv/RV32I.java +++ b/src/il/co/codeguru/corewars_riscv/cpu/riscv/rv32i/RV32I.java @@ -1,6 +1,7 @@ -package il.co.codeguru.corewars_riscv.cpu.riscv; +package il.co.codeguru.corewars_riscv.cpu.riscv.rv32i; -import il.co.codeguru.corewars_riscv.cpu.riscv.instruction_formats.*; +import il.co.codeguru.corewars_riscv.cpu.riscv.Instruction; +import il.co.codeguru.corewars_riscv.cpu.riscv.rv32i.instruction_formats.*; public final class RV32I { private RV32I(){} @@ -22,6 +23,7 @@ public final class OpcodeTypes { public static final int LUI = 0x37; public static final int JALR = 0x67; public static final int JAL = 0x6f; + public static final int SYS = 0x73; } public static final class Opcodes{ @@ -73,6 +75,9 @@ public static final class Opcodes{ public static Instruction.InstructionInfo Auipc= new Instruction.InstructionInfo("Auipc",OpcodeTypes.AUIPC); public static Instruction.InstructionInfo Jal = new Instruction.InstructionInfo("Jal",OpcodeTypes.JAL); public static Instruction.InstructionInfo Jalr = new Instruction.InstructionInfo("Jalr",OpcodeTypes.JALR); + + //System + public static Instruction.InstructionInfo Ecall= new Instruction.InstructionInfo("Ecall",OpcodeTypes.SYS, 0); } } diff --git a/src/il/co/codeguru/corewars_riscv/cpu/riscv/instruction_formats/InstructionFormatBase.java b/src/il/co/codeguru/corewars_riscv/cpu/riscv/rv32i/instruction_formats/InstructionFormatBase.java similarity index 68% rename from src/il/co/codeguru/corewars_riscv/cpu/riscv/instruction_formats/InstructionFormatBase.java rename to src/il/co/codeguru/corewars_riscv/cpu/riscv/rv32i/instruction_formats/InstructionFormatBase.java index 6721de5..6eb5a40 100644 --- a/src/il/co/codeguru/corewars_riscv/cpu/riscv/instruction_formats/InstructionFormatBase.java +++ b/src/il/co/codeguru/corewars_riscv/cpu/riscv/rv32i/instruction_formats/InstructionFormatBase.java @@ -1,11 +1,12 @@ -package il.co.codeguru.corewars_riscv.cpu.riscv.instruction_formats; +package il.co.codeguru.corewars_riscv.cpu.riscv.rv32i.instruction_formats; import il.co.codeguru.corewars_riscv.cpu.riscv.Instruction; +import il.co.codeguru.corewars_riscv.cpu.riscv.InstructionFormat; -public class InstructionFormatBase { +public class InstructionFormatBase implements InstructionFormat { final protected int raw; - public InstructionFormatBase(int raw) { + public InstructionFormatBase(Integer raw) { this.raw = raw; } diff --git a/src/il/co/codeguru/corewars_riscv/cpu/riscv/instruction_formats/InstructionFormatI.java b/src/il/co/codeguru/corewars_riscv/cpu/riscv/rv32i/instruction_formats/InstructionFormatI.java similarity index 93% rename from src/il/co/codeguru/corewars_riscv/cpu/riscv/instruction_formats/InstructionFormatI.java rename to src/il/co/codeguru/corewars_riscv/cpu/riscv/rv32i/instruction_formats/InstructionFormatI.java index 5696721..84307da 100644 --- a/src/il/co/codeguru/corewars_riscv/cpu/riscv/instruction_formats/InstructionFormatI.java +++ b/src/il/co/codeguru/corewars_riscv/cpu/riscv/rv32i/instruction_formats/InstructionFormatI.java @@ -1,4 +1,4 @@ -package il.co.codeguru.corewars_riscv.cpu.riscv.instruction_formats; +package il.co.codeguru.corewars_riscv.cpu.riscv.rv32i.instruction_formats; import il.co.codeguru.corewars_riscv.cpu.riscv.Instruction; diff --git a/src/il/co/codeguru/corewars_riscv/cpu/riscv/instruction_formats/InstructionFormatR.java b/src/il/co/codeguru/corewars_riscv/cpu/riscv/rv32i/instruction_formats/InstructionFormatR.java similarity index 94% rename from src/il/co/codeguru/corewars_riscv/cpu/riscv/instruction_formats/InstructionFormatR.java rename to src/il/co/codeguru/corewars_riscv/cpu/riscv/rv32i/instruction_formats/InstructionFormatR.java index 2882be3..49b0fdb 100644 --- a/src/il/co/codeguru/corewars_riscv/cpu/riscv/instruction_formats/InstructionFormatR.java +++ b/src/il/co/codeguru/corewars_riscv/cpu/riscv/rv32i/instruction_formats/InstructionFormatR.java @@ -1,4 +1,4 @@ -package il.co.codeguru.corewars_riscv.cpu.riscv.instruction_formats; +package il.co.codeguru.corewars_riscv.cpu.riscv.rv32i.instruction_formats; import il.co.codeguru.corewars_riscv.cpu.riscv.Instruction; diff --git a/src/il/co/codeguru/corewars_riscv/cpu/riscv/instruction_formats/InstructionFormatS.java b/src/il/co/codeguru/corewars_riscv/cpu/riscv/rv32i/instruction_formats/InstructionFormatS.java similarity index 95% rename from src/il/co/codeguru/corewars_riscv/cpu/riscv/instruction_formats/InstructionFormatS.java rename to src/il/co/codeguru/corewars_riscv/cpu/riscv/rv32i/instruction_formats/InstructionFormatS.java index 274fe12..9e327a8 100644 --- a/src/il/co/codeguru/corewars_riscv/cpu/riscv/instruction_formats/InstructionFormatS.java +++ b/src/il/co/codeguru/corewars_riscv/cpu/riscv/rv32i/instruction_formats/InstructionFormatS.java @@ -1,4 +1,4 @@ -package il.co.codeguru.corewars_riscv.cpu.riscv.instruction_formats; +package il.co.codeguru.corewars_riscv.cpu.riscv.rv32i.instruction_formats; import il.co.codeguru.corewars_riscv.cpu.riscv.Instruction; diff --git a/src/il/co/codeguru/corewars_riscv/cpu/riscv/instruction_formats/InstructionFormatSB.java b/src/il/co/codeguru/corewars_riscv/cpu/riscv/rv32i/instruction_formats/InstructionFormatSB.java similarity index 95% rename from src/il/co/codeguru/corewars_riscv/cpu/riscv/instruction_formats/InstructionFormatSB.java rename to src/il/co/codeguru/corewars_riscv/cpu/riscv/rv32i/instruction_formats/InstructionFormatSB.java index 13f6295..482832f 100644 --- a/src/il/co/codeguru/corewars_riscv/cpu/riscv/instruction_formats/InstructionFormatSB.java +++ b/src/il/co/codeguru/corewars_riscv/cpu/riscv/rv32i/instruction_formats/InstructionFormatSB.java @@ -1,4 +1,4 @@ -package il.co.codeguru.corewars_riscv.cpu.riscv.instruction_formats; +package il.co.codeguru.corewars_riscv.cpu.riscv.rv32i.instruction_formats; import il.co.codeguru.corewars_riscv.cpu.riscv.Instruction; diff --git a/src/il/co/codeguru/corewars_riscv/cpu/riscv/instruction_formats/InstructionFormatU.java b/src/il/co/codeguru/corewars_riscv/cpu/riscv/rv32i/instruction_formats/InstructionFormatU.java similarity index 91% rename from src/il/co/codeguru/corewars_riscv/cpu/riscv/instruction_formats/InstructionFormatU.java rename to src/il/co/codeguru/corewars_riscv/cpu/riscv/rv32i/instruction_formats/InstructionFormatU.java index dc28ee0..2a3872c 100644 --- a/src/il/co/codeguru/corewars_riscv/cpu/riscv/instruction_formats/InstructionFormatU.java +++ b/src/il/co/codeguru/corewars_riscv/cpu/riscv/rv32i/instruction_formats/InstructionFormatU.java @@ -1,4 +1,4 @@ -package il.co.codeguru.corewars_riscv.cpu.riscv.instruction_formats; +package il.co.codeguru.corewars_riscv.cpu.riscv.rv32i.instruction_formats; import il.co.codeguru.corewars_riscv.cpu.riscv.Instruction; diff --git a/src/il/co/codeguru/corewars_riscv/cpu/riscv/instruction_formats/InstructionFormatUJ.java b/src/il/co/codeguru/corewars_riscv/cpu/riscv/rv32i/instruction_formats/InstructionFormatUJ.java similarity index 94% rename from src/il/co/codeguru/corewars_riscv/cpu/riscv/instruction_formats/InstructionFormatUJ.java rename to src/il/co/codeguru/corewars_riscv/cpu/riscv/rv32i/instruction_formats/InstructionFormatUJ.java index d3a1be8..3960f17 100644 --- a/src/il/co/codeguru/corewars_riscv/cpu/riscv/instruction_formats/InstructionFormatUJ.java +++ b/src/il/co/codeguru/corewars_riscv/cpu/riscv/rv32i/instruction_formats/InstructionFormatUJ.java @@ -1,4 +1,4 @@ -package il.co.codeguru.corewars_riscv.cpu.riscv.instruction_formats; +package il.co.codeguru.corewars_riscv.cpu.riscv.rv32i.instruction_formats; import il.co.codeguru.corewars_riscv.cpu.riscv.Instruction; diff --git a/src/il/co/codeguru/corewars_riscv/features/Feature.java b/src/il/co/codeguru/corewars_riscv/features/Feature.java new file mode 100644 index 0000000..618dc30 --- /dev/null +++ b/src/il/co/codeguru/corewars_riscv/features/Feature.java @@ -0,0 +1,18 @@ +package il.co.codeguru.corewars_riscv.features; + +import il.co.codeguru.corewars_riscv.war.Warrior; + +public abstract class Feature { + private boolean enabled; + + public boolean isEnabled() { + return enabled; + } + + public void enable() { + enabled = true; + } + + abstract public void initWarriorGroup(Warrior... warriors); + + } diff --git a/src/il/co/codeguru/corewars_riscv/features/FeatureSet.java b/src/il/co/codeguru/corewars_riscv/features/FeatureSet.java new file mode 100644 index 0000000..d72d1f8 --- /dev/null +++ b/src/il/co/codeguru/corewars_riscv/features/FeatureSet.java @@ -0,0 +1,37 @@ +package il.co.codeguru.corewars_riscv.features; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +public class FeatureSet { + + private Map featureMap; + + public FeatureSet() { + featureMap = new HashMap<>(); + } + + public void register(String name, Feature feature) { + featureMap.put(name, feature); + } + + public Set> getRegisterdFeatures() { + return featureMap.entrySet(); + } + + public void enableFeature(String name) { + featureMap.get(name).enable(); + } + + public Feature[] getEnabledFeatures() { + return featureMap.values().stream().filter((Feature::isEnabled)).toArray(Feature[]::new); + } + + public static FeatureSet getAllFeatures() { + FeatureSet ans = new FeatureSet(); + ans.register("new-memory", new NewMemory()); + ans.register("push-pop-all", new PushPopAll()); + return ans; + } +} diff --git a/src/il/co/codeguru/corewars_riscv/features/NewMemory.java b/src/il/co/codeguru/corewars_riscv/features/NewMemory.java new file mode 100644 index 0000000..5ad4f80 --- /dev/null +++ b/src/il/co/codeguru/corewars_riscv/features/NewMemory.java @@ -0,0 +1,34 @@ +package il.co.codeguru.corewars_riscv.features; + +import il.co.codeguru.corewars_riscv.memory.Memory; +import il.co.codeguru.corewars_riscv.memory.MemoryBus; +import il.co.codeguru.corewars_riscv.memory.MemoryRegion; +import il.co.codeguru.corewars_riscv.memory.RawMemory; +import il.co.codeguru.corewars_riscv.war.Warrior; + +import java.util.HashMap; +import java.util.Map; + +public class NewMemory extends Feature { + + public static final MemoryRegion SharedMemory = new MemoryRegion(0x40000, 0x40399); + public static final MemoryRegion StackMemory = new MemoryRegion(0x20000, 0x20799); + + @Override + public void initWarriorGroup(Warrior... warriors) { + Map teamMap = new HashMap<>(); + for (Warrior warrior : warriors) { + if (warrior != null) { + if (!teamMap.containsKey(warrior.getTeamId())) { + teamMap.put(warrior.getTeamId(), new RawMemory(SharedMemory.getSize())); + } + MemoryBus bus = warrior.getBus(); + bus.addRegion(SharedMemory, teamMap.get(warrior.getTeamId())); + bus.addRegion(StackMemory, new RawMemory(StackMemory.getSize())); + + warrior.getCpuState().setReg(2, StackMemory.m_start); + warrior.getCpuState().setReg(3, SharedMemory.m_start); + } + } + } +} diff --git a/src/il/co/codeguru/corewars_riscv/features/PushPopAll.java b/src/il/co/codeguru/corewars_riscv/features/PushPopAll.java new file mode 100644 index 0000000..d5e6a9b --- /dev/null +++ b/src/il/co/codeguru/corewars_riscv/features/PushPopAll.java @@ -0,0 +1,55 @@ +package il.co.codeguru.corewars_riscv.features; + +import il.co.codeguru.corewars_riscv.cpu.riscv.CpuRiscV; +import il.co.codeguru.corewars_riscv.cpu.riscv.CpuStateRiscV; +import il.co.codeguru.corewars_riscv.memory.Memory; +import il.co.codeguru.corewars_riscv.war.Warrior; + +public class PushPopAll extends Feature { + + @Override + public void initWarriorGroup(Warrior... warriors) { + for (Warrior warrior : warriors) { + if (warrior != null) { + warrior.getCpu().registerSyscall(3, new PushAll()); + warrior.getCpu().registerSyscall(4, new PopAll()); + } + } + } + + // TODO: This is not really appropiate as a syscall, more as a command. + // In the future, there is a need to make this a RISC-V command under the CG extension. + + private class PushAll extends Syscall { + + int remainingUses = 1; + + @Override + public void call(CpuRiscV cpuRiscV) { + if (remainingUses == 0) { + return; + } + + Memory memory = cpuRiscV.getMemory(); + CpuStateRiscV state = cpuRiscV.getState(); + for (int i = 3; i < 32; i++) { + memory.storeWord(state.getReg(2), state.getReg(i)); + state.setReg(2, state.getReg(2) + 4); + } + + remainingUses--; + } + } + + private class PopAll extends Syscall { + @Override + public void call(CpuRiscV cpuRiscV) { + Memory memory = cpuRiscV.getMemory(); + CpuStateRiscV state = cpuRiscV.getState(); + for (int i = 3; i < 32; i++) { + state.setReg(i, memory.loadWord(state.getReg(2))); + state.setReg(2, state.getReg(2) + 4); + } + } + } +} diff --git a/src/il/co/codeguru/corewars_riscv/features/Syscall.java b/src/il/co/codeguru/corewars_riscv/features/Syscall.java new file mode 100644 index 0000000..54a9777 --- /dev/null +++ b/src/il/co/codeguru/corewars_riscv/features/Syscall.java @@ -0,0 +1,7 @@ +package il.co.codeguru.corewars_riscv.features; + +import il.co.codeguru.corewars_riscv.cpu.riscv.CpuRiscV; + +public abstract class Syscall { + public abstract void call(CpuRiscV cpuRiscV); +} diff --git a/src/il/co/codeguru/corewars_riscv/gui/CompetitionWindow.java b/src/il/co/codeguru/corewars_riscv/gui/CompetitionWindow.java index 86f9385..2b9e449 100644 --- a/src/il/co/codeguru/corewars_riscv/gui/CompetitionWindow.java +++ b/src/il/co/codeguru/corewars_riscv/gui/CompetitionWindow.java @@ -2,6 +2,7 @@ import elemental2.dom.DomGlobal; import elemental2.dom.HTMLElement; +import il.co.codeguru.corewars_riscv.features.FeatureSet; import il.co.codeguru.corewars_riscv.gui.code_editor.CodeEditor; import il.co.codeguru.corewars_riscv.utils.Logger; import il.co.codeguru.corewars_riscv.war.*; @@ -67,7 +68,7 @@ public CompetitionWindow() warCounterDisplay = new JLabel(""); buttonPanel.add(warCounterDisplay); buttonPanel.add(Box.createHorizontalStrut(30)); - + controlArea.add(buttonPanel); // ------------- controlArea.add(new JSeparator(JSeparator.HORIZONTAL)); @@ -75,7 +76,6 @@ public CompetitionWindow() JPanel controlPanel = new JPanel(); controlPanel.setLayout(new FlowLayout()); controlPanel.add(new JLabel("Survivor groups per session:")); - controlPanel.add(new JLabel("Sessions per groups combination:")); battlesPerGroupField = new JTextField("battlesPerGroupField", "100", 4); seed = new JTextField("seed", null, 4); @@ -84,7 +84,6 @@ public CompetitionWindow() controlPanel.add(seed); controlArea.add(controlPanel); - // ------------ getContentPane().add(controlArea, BorderLayout.SOUTH); @@ -97,7 +96,7 @@ public CompetitionWindow() setPlatform("riscv"); stepnum = (HTMLElement) DomGlobal.document.getElementById("stepnum"); - + exportMethods(); competition.competitionEventCaster.doneAdding(); @@ -223,7 +222,7 @@ public boolean runWar(boolean isInDebug) } try { - competition.runCompetition(battlesPerGroup, numOfGroups, isInDebug, SettingsPanel.useNewMemory()); + competition.runCompetition(battlesPerGroup, numOfGroups, isInDebug, SettingsPanel.getEnabledOptions().getEnabledFeatures()); startRunAnimation(); // when runWar() returns we want the War object to be already constructured and ready if (this.isInDebug) { // add breakpointchecked only if we're in debugger War war = competition.getCurrentWar(); diff --git a/src/il/co/codeguru/corewars_riscv/gui/CpuFrame.java b/src/il/co/codeguru/corewars_riscv/gui/CpuFrame.java index 132a82d..91b7345 100644 --- a/src/il/co/codeguru/corewars_riscv/gui/CpuFrame.java +++ b/src/il/co/codeguru/corewars_riscv/gui/CpuFrame.java @@ -3,6 +3,7 @@ import elemental2.dom.DomGlobal; import elemental2.dom.HTMLElement; import il.co.codeguru.corewars_riscv.cpu.riscv.CpuStateRiscV; +import il.co.codeguru.corewars_riscv.features.NewMemory; import il.co.codeguru.corewars_riscv.memory.Memory; import il.co.codeguru.corewars_riscv.gui.widgets.Console; import il.co.codeguru.corewars_riscv.jsadd.Format; @@ -330,8 +331,8 @@ private void initMemRegions(boolean force) Warrior warrior = currentWar.getWarriorByLabel(m_currentWarriorLabel); - stackView.initMemRegion(warrior.stackRegion, currentWar.getMemory(), force); - sharedMemView.initMemRegion(warrior.sharedRegion, currentWar.getMemory(), force); + stackView.initMemRegion(NewMemory.StackMemory, warrior.getBus(), force); + sharedMemView.initMemRegion(NewMemory.SharedMemory, warrior.getBus(), force); m_stateAccess.Memory = currentWar.getMemory(); } diff --git a/src/il/co/codeguru/corewars_riscv/gui/MemRegionView.java b/src/il/co/codeguru/corewars_riscv/gui/MemRegionView.java index c2a0a95..2e8f070 100644 --- a/src/il/co/codeguru/corewars_riscv/gui/MemRegionView.java +++ b/src/il/co/codeguru/corewars_riscv/gui/MemRegionView.java @@ -10,8 +10,11 @@ import il.co.codeguru.corewars_riscv.jsadd.Format; import il.co.codeguru.corewars_riscv.memory.MemoryEventListener; import il.co.codeguru.corewars_riscv.memory.MemoryRegion; +import il.co.codeguru.corewars_riscv.utils.Logger; import il.co.codeguru.corewars_riscv.utils.Unsigned; +import static il.co.codeguru.corewars_riscv.jsadd.Format.hex; + public class MemRegionView implements MemoryEventListener { private HTMLElement m_htmlList; diff --git a/src/il/co/codeguru/corewars_riscv/gui/SettingsPanel.java b/src/il/co/codeguru/corewars_riscv/gui/SettingsPanel.java index 4e4b9d1..0a1c75c 100644 --- a/src/il/co/codeguru/corewars_riscv/gui/SettingsPanel.java +++ b/src/il/co/codeguru/corewars_riscv/gui/SettingsPanel.java @@ -1,13 +1,39 @@ package il.co.codeguru.corewars_riscv.gui; +import il.co.codeguru.corewars_riscv.features.Feature; +import il.co.codeguru.corewars_riscv.features.FeatureSet; + +import java.util.Map; + public class SettingsPanel { public static boolean useNewMemory() { - return getCheckboxValue("#new-memory"); + return false; + } + + public static void addAllOptions() { + FeatureSet features = FeatureSet.getAllFeatures(); + for(Map.Entry feature : features.getRegisterdFeatures()) { + addOption(feature.getKey()); + } } - private static native boolean getCheckboxValue(String selector) /*-{ - return $wnd.$(selector).prop("checked"); + public static FeatureSet getEnabledOptions() { + FeatureSet features = FeatureSet.getAllFeatures(); + for(Map.Entry feature : features.getRegisterdFeatures()) { + if(isEnabled(feature.getKey())) { + feature.getValue().enable(); + } + } + return features; + } + + private static native boolean isEnabled(String option) /*-{ + return $wnd.settings_menu.isEnabled(option); + }-*/; + + private static native void addOption(String option) /*-{ + $wnd.settings_menu.addOption(option); }-*/; } diff --git a/src/il/co/codeguru/corewars_riscv/memory/CyclicRawMemory.java b/src/il/co/codeguru/corewars_riscv/memory/CyclicRawMemory.java new file mode 100644 index 0000000..6b85948 --- /dev/null +++ b/src/il/co/codeguru/corewars_riscv/memory/CyclicRawMemory.java @@ -0,0 +1,18 @@ +package il.co.codeguru.corewars_riscv.memory; + +public class CyclicRawMemory extends RawMemory { + + public CyclicRawMemory(int size) { + super(size); + } + + @Override + public void storeByte(int index, byte value) throws MemoryException { + super.storeByte(index & 0xFFFF, value); + } + + @Override + public byte loadByte(int index) throws MemoryException { + return super.loadByte(index & 0xFFFF); + } +} diff --git a/src/il/co/codeguru/corewars_riscv/memory/MemoryBus.java b/src/il/co/codeguru/corewars_riscv/memory/MemoryBus.java new file mode 100644 index 0000000..3369ece --- /dev/null +++ b/src/il/co/codeguru/corewars_riscv/memory/MemoryBus.java @@ -0,0 +1,47 @@ +package il.co.codeguru.corewars_riscv.memory; +import il.co.codeguru.corewars_riscv.utils.Logger; +import il.co.codeguru.corewars_riscv.utils.Pair; + +import java.util.ArrayList; +import java.util.List; + +import static il.co.codeguru.corewars_riscv.jsadd.Format.hex; + +public class MemoryBus extends Memory { + private List> regions = new ArrayList<>(); + + private Pair findRegion(int index) { + for (Pair region : regions) { + if (region.getKey().isInRegion(index)) { + return region; + } + } + //If there is only arena, return it and make it cyclic + if(regions.size() == 1) { + return regions.get(0); + } + return null; + } + + public void addRegion(MemoryRegion region, Memory memory) { + regions.add(new Pair<>(region, memory)); + } + + @Override + public void storeByte(int index, byte value) throws MemoryException { + Pair region = findRegion(index); + if(region == null) { + throw new MemoryException("Write at forbidden location - at " + hex(index)); + } + region.getValue().storeByte(region.getKey().normalize(index), value); + } + + @Override + public byte loadByte(int index) throws MemoryException { + Pair region = findRegion(index); + if(region == null) { + throw new MemoryException("Read at forbidden location - at " + hex(index)); + } + return region.getValue().loadByte(region.getKey().normalize(index)); + } +} diff --git a/src/il/co/codeguru/corewars_riscv/memory/MemoryRegion.java b/src/il/co/codeguru/corewars_riscv/memory/MemoryRegion.java index a571328..3ea2b79 100644 --- a/src/il/co/codeguru/corewars_riscv/memory/MemoryRegion.java +++ b/src/il/co/codeguru/corewars_riscv/memory/MemoryRegion.java @@ -2,6 +2,9 @@ public class MemoryRegion { + public int m_start; + public int m_end; // inclusive at end + public MemoryRegion() { m_start = -1; m_end = -1; @@ -16,10 +19,15 @@ public boolean isInRegion(int asked) { return ((asked >= m_start) && (asked <= m_end)); } + public int normalize(int index) { + return index - m_start; + } + public boolean equals(MemoryRegion a) { return m_start == a.m_start && m_end == a.m_end; } - public int m_start; - public int m_end; // inclusive at end + public int getSize() { + return m_end - m_start + 1; + } } \ No newline at end of file diff --git a/src/il/co/codeguru/corewars_riscv/memory/RawMemory.java b/src/il/co/codeguru/corewars_riscv/memory/RawMemory.java index 6a78569..3b51ce3 100644 --- a/src/il/co/codeguru/corewars_riscv/memory/RawMemory.java +++ b/src/il/co/codeguru/corewars_riscv/memory/RawMemory.java @@ -8,7 +8,7 @@ public byte[] getByteArray() return data; } - private byte[] data; + protected byte[] data; public RawMemory(int size) { diff --git a/src/il/co/codeguru/corewars_riscv/utils/Pair.java b/src/il/co/codeguru/corewars_riscv/utils/Pair.java new file mode 100644 index 0000000..a413831 --- /dev/null +++ b/src/il/co/codeguru/corewars_riscv/utils/Pair.java @@ -0,0 +1,13 @@ +package il.co.codeguru.corewars_riscv.utils; + +public class Pair { + private final K key; + private final V value; + public Pair(K key, V value) { + this.key = key; + this.value = value; + } + + public K getKey() {return this.key; } + public V getValue() {return this.value; } +} diff --git a/src/il/co/codeguru/corewars_riscv/utils/disassembler/DisassemblerRiscV.java b/src/il/co/codeguru/corewars_riscv/utils/disassembler/DisassemblerRiscV.java index 9f03c0d..05a0b39 100644 --- a/src/il/co/codeguru/corewars_riscv/utils/disassembler/DisassemblerRiscV.java +++ b/src/il/co/codeguru/corewars_riscv/utils/disassembler/DisassemblerRiscV.java @@ -2,17 +2,16 @@ import il.co.codeguru.corewars_riscv.cpu.exceptions.InvalidOpcodeException; import il.co.codeguru.corewars_riscv.cpu.riscv.Instruction; -import il.co.codeguru.corewars_riscv.cpu.riscv.InstructionDecoder; +import il.co.codeguru.corewars_riscv.cpu.riscv.rv32i.InstructionDecoder32I; import il.co.codeguru.corewars_riscv.memory.Memory; import il.co.codeguru.corewars_riscv.memory.RawMemory; -import il.co.codeguru.corewars_riscv.cpu.riscv.instruction_formats.InstructionFormatBase; +import il.co.codeguru.corewars_riscv.cpu.riscv.rv32i.instruction_formats.InstructionFormatBase; import il.co.codeguru.corewars_riscv.cpu.riscv.rv32c.InstructionDecoderRv32c; import il.co.codeguru.corewars_riscv.cpu.riscv.rv32c.instruction_formats.CInstructionFormatBase; -import il.co.codeguru.corewars_riscv.utils.Logger; public class DisassemblerRiscV implements IDisassembler { - private InstructionDecoder decoder; + private InstructionDecoder32I decoder; private InstructionDecoderRv32c cDecoder; private Memory Memory; @@ -25,7 +24,7 @@ public DisassemblerRiscV(byte[] memory, int index, int endIndex) { this.index = index; this.endIndex = endIndex; - this.decoder = new InstructionDecoder(); + this.decoder = new InstructionDecoder32I(); this.cDecoder= new InstructionDecoderRv32c(); } diff --git a/src/il/co/codeguru/corewars_riscv/war/Competition.java b/src/il/co/codeguru/corewars_riscv/war/Competition.java index 1cf3696..3cced13 100644 --- a/src/il/co/codeguru/corewars_riscv/war/Competition.java +++ b/src/il/co/codeguru/corewars_riscv/war/Competition.java @@ -1,5 +1,6 @@ package il.co.codeguru.corewars_riscv.war; +import il.co.codeguru.corewars_riscv.features.Feature; import il.co.codeguru.corewars_riscv.gui.widgets.EventMulticasterCompetition; import il.co.codeguru.corewars_riscv.gui.widgets.EventMulticasterMemory; import il.co.codeguru.corewars_riscv.memory.MemoryEventListener; @@ -40,7 +41,7 @@ public static class CompState { public boolean abort = false; int waitedFrames = 0; // how many frames we just waited for negative speed long startTime = 0; - boolean useNewMemory; + Feature[] features; } public CompState compState; @@ -142,7 +143,7 @@ else if (needMore == -1) { - public void runCompetition(int warsPerCombination, int warriorsPerGroup, boolean isInDebugger, boolean useNewMemory) { + public void runCompetition(int warsPerCombination, int warriorsPerGroup, boolean isInDebugger, Feature[] features) { this.warsPerCombination = warsPerCombination; Logger.log("Running competition"); competitionIterator = new CompetitionIterator(warriorRepository.getNumberOfGroups(), warriorsPerGroup, seed); @@ -156,7 +157,7 @@ public void runCompetition(int warsPerCombination, int warriorsPerGroup, boolean currentWar = null; compState.isInDebugger = isInDebugger; compState.startTime = System.currentTimeMillis(); - compState.useNewMemory = useNewMemory; + compState.features = features; if (isInDebugger) switchToDebug(); @@ -204,7 +205,7 @@ private int runRound() private void startWar(WarriorGroup[] warriorGroups) throws Exception { - currentWar = new War(memoryEventListener, competitionEventListener, compState.isInDebugger, compState.useNewMemory); + currentWar = new War(memoryEventListener, competitionEventListener, compState.isInDebugger, compState.features); currentWar.setSeed(this.seed); competitionEventListener.onWarPreStartClear(); currentWar.loadWarriorGroups(warriorGroups); diff --git a/src/il/co/codeguru/corewars_riscv/war/War.java b/src/il/co/codeguru/corewars_riscv/war/War.java index ae8b75a..a72c2cb 100644 --- a/src/il/co/codeguru/corewars_riscv/war/War.java +++ b/src/il/co/codeguru/corewars_riscv/war/War.java @@ -1,11 +1,12 @@ package il.co.codeguru.corewars_riscv.war; import il.co.codeguru.corewars_riscv.cpu.exceptions.CpuException; +import il.co.codeguru.corewars_riscv.features.Feature; +import il.co.codeguru.corewars_riscv.memory.CyclicRawMemory; import il.co.codeguru.corewars_riscv.memory.RawMemory; import il.co.codeguru.corewars_riscv.gui.IBreakpointCheck; import il.co.codeguru.corewars_riscv.memory.MemoryEventListener; import il.co.codeguru.corewars_riscv.memory.MemoryException; -import il.co.codeguru.corewars_riscv.utils.Logger; import il.co.codeguru.corewars_riscv.utils.Unsigned; import java.util.ArrayList; @@ -22,16 +23,10 @@ * @author DL */ public class War { - /** Arena's code segment */ - public final static short ARENA_SEGMENT = 0; /** Arena's size in bytes (= size of a single segment) */ public final static int ARENA_SIZE = PARAGRAPHS_IN_SEGMENT * PARAGRAPH_SIZE; - /** Warrior's private stack size */ - public final static short STACK_SIZE = 2*1024; - /** Group-shared private memory size */ - public final static short GROUP_SHARED_MEMORY_SIZE = 1024; /** Arena is filled with this byte */ private final static byte ARENA_BYTE = (byte)0x00; /** Maximum number of warriors in a fight */ @@ -41,17 +36,14 @@ public class War { /** Minimum initial space (in bytes) between loaded warriors */ private final static int MIN_GAP = 1024; + private final Feature[] features; + /** Warriors in the fight */ private Warrior[] m_warriors; /** Number of loaded warriors */ private int m_numWarriors; /** Number of warriors still alive */ private int m_numWarriorsAlive; - /** - * Addresses equal or larger than this are still unused. - * An address can be 'used' either by the Arena, or by the private stacks. - */ - private int m_nextFreeAddress; /** The 'physical' memory core */ private RawMemory m_core; @@ -64,7 +56,6 @@ public class War { private IBreakpointCheck m_breakpointCheck = null; private int m_uiWarriorIndex = -1; // break in breakpoints only of this warrior (he's the one selected in the PlayersPanel) private boolean m_hasEnded = false; // this war has ended but the object remains alive for post-mortem examination - private boolean useNewMemory; public void setUiWarrior(Warrior warrior) { if (warrior != null) @@ -86,15 +77,18 @@ public void setEnded() { * Constructor. * Fills the Arena with its initial data. */ - public War(MemoryEventListener memoryListener, CompetitionEventListener warListener, boolean startPaused, boolean useNewMemory) { - isPaused = startPaused; //startPaused; // startPause just causes control to return after startWar, we don't want to pause the first round + public War(MemoryEventListener memoryListener, CompetitionEventListener warListener, boolean startPaused, Feature[] features) { + isPaused = startPaused; // startPause just causes control to return after startWar, we don't want to pause the first round m_warListener = warListener; m_warriors = new Warrior[MAX_WARRIORS]; m_numWarriors = 0; m_numWarriorsAlive = 0; - m_core = new RawMemory(MEMORY_SIZE); - m_nextFreeAddress = ARENA_SIZE; - this.useNewMemory = useNewMemory; + m_core = new CyclicRawMemory(MEMORY_SIZE); + /** + * Addresses equal or larger than this are still unused. + * An address can be 'used' either by the Arena, or by the private stacks. + */ + this.features = features; // initialize arena for (int offset = 0; offset < ARENA_SIZE; ++offset) { @@ -236,22 +230,27 @@ private int calculateWarriorSpeed(int energy) { */ public void loadWarriorGroups(WarriorGroup[] warriorGroups) throws Exception { m_currentWarrior = 0; + int currentTeamId = 0; ArrayList groupsLeftToLoad = new ArrayList<>(Arrays.asList(warriorGroups)); while (groupsLeftToLoad.size() > 0) { int randomInt = rand.nextInt(groupsLeftToLoad.size()); - loadWarriorGroup(groupsLeftToLoad.get(randomInt)); + loadWarriorGroup(groupsLeftToLoad.get(randomInt), currentTeamId); + currentTeamId++; groupsLeftToLoad.remove(randomInt); } + + for(Feature feature : this.features) { + feature.initWarriorGroup(this.m_warriors); + } + m_currentWarrior = -1; } - private void loadWarriorGroup(WarriorGroup warriorGroup) throws Exception { + private void loadWarriorGroup(WarriorGroup warriorGroup, int teamId) throws Exception { List warriors = warriorGroup.getWarriors(); - int groupSharedMemory = allocateCoreMemory(GROUP_SHARED_MEMORY_SIZE); - for (WarriorData warrior : warriors) { String warriorName = warrior.getName(); byte[] warriorData = warrior.getCode(); @@ -262,18 +261,15 @@ private void loadWarriorGroup(WarriorGroup warriorGroup) throws Exception { else loadOffset = (short) warrior.m_debugFixedLoadAddress; - int stackMemory = allocateCoreMemory(STACK_SIZE); - Warrior w = new Warrior( warriorName, warrior.getLabel(), warriorData.length, + teamId, m_core, loadOffset, - stackMemory, - groupSharedMemory, - m_numWarriors, - useNewMemory); + m_numWarriors + ); m_warriors[m_numWarriors++] = w; // load warrior to arena @@ -294,25 +290,6 @@ private void loadWarriorGroup(WarriorGroup warriorGroup) throws Exception { } - /** - * Virtually allocates core memory of a given size, by advancing the - * next-free-memory pointer (m_nextFreeAddress). - * - * @param size Required memory size, must be a multiple of - * RawMemory.PARAGRAPH_SIZE - * @return Pointer to the beginning of the allocated memory block. - */ - private int allocateCoreMemory(short size) { - if ((size % PARAGRAPH_SIZE) != 0) { - throw new IllegalArgumentException(); - } - int allocatedMemory = m_nextFreeAddress; - - m_nextFreeAddress += size; - - return allocatedMemory; - } - /** * Returns a suitable random address to which a warrior with a given code * size can be loaded. @@ -323,9 +300,8 @@ private int allocateCoreMemory(short size) { * * @param warriorSize Code size of the loaded warrior. * @return offset within the Arena to which the warrior can be loaded. - * @throws Exception if no suitable address could be found. */ - private short getLoadOffset(int warriorSize) throws Exception { + private short getLoadOffset(int warriorSize) { int loadAddress = 0; boolean found = false; int numTries = 0; diff --git a/src/il/co/codeguru/corewars_riscv/war/Warrior.java b/src/il/co/codeguru/corewars_riscv/war/Warrior.java index 62afa72..e88dfe3 100644 --- a/src/il/co/codeguru/corewars_riscv/war/Warrior.java +++ b/src/il/co/codeguru/corewars_riscv/war/Warrior.java @@ -4,70 +4,81 @@ import il.co.codeguru.corewars_riscv.cpu.riscv.CpuRiscV; import il.co.codeguru.corewars_riscv.cpu.riscv.CpuStateRiscV; import il.co.codeguru.corewars_riscv.memory.Memory; +import il.co.codeguru.corewars_riscv.memory.MemoryBus; import il.co.codeguru.corewars_riscv.memory.MemoryException; import il.co.codeguru.corewars_riscv.memory.MemoryRegion; -import il.co.codeguru.corewars_riscv.memory.RestrictedMemory; -import static il.co.codeguru.corewars_riscv.war.War.*; +import static il.co.codeguru.corewars_riscv.war.War.ARENA_SIZE; /** * A single CoreWars warrior. - * + * * @author DL */ -public class Warrior -{ - public MemoryRegion stackRegion; - public MemoryRegion sharedRegion; - public final MemoryRegion arenaRegion = new MemoryRegion(0, ARENA_SIZE -1); +public class Warrior { + public final MemoryRegion arenaRegion = new MemoryRegion(0, ARENA_SIZE - 1); + public final int m_myIndex; // in the War m_warriors array. used for identifying breakpoints + private final MemoryBus bus = new MemoryBus(); + /** + * Warrior's name + */ + private final String m_name; + private final String m_label; + /** + * Warrior's initial code size + */ + private final int m_codeSize; + /** + * Warrior's initial load address + */ + private final int m_loadAddress; + private int teamId; + /** + * Current state of registers & flags + */ + private CpuStateRiscV m_state; + /** + * CPU instance + */ + private CpuRiscV m_cpu; + /** + * Whether or not the warrior is still alive + */ + private boolean m_isAlive; /** * Constructor. - * - * @param name Warrior's name. - * @param codeSize Warrior's code size. - * @param core Real mode memory used as core. - * @param loadAddress Warrior's load address in the core (initial CS:IP). - * @param initialStack Warrior's private stack in the core (initial SS:SP). - * @param groupSharedMemory Warrior group's shared memroy address (initial ES). + * + * @param name Warrior's name. + * @param codeSize Warrior's code size. + * @param teamId Warrior's team id + * @param core Real mode memory used as core. + * @param loadAddress Warrior's load address in the core (initial CS:IP). */ public Warrior( String name, String label, int codeSize, + int teamId, Memory core, int loadAddress, - int initialStack, - int groupSharedMemory, - int myIndex, - boolean useNewMemory) - { + int myIndex) { m_label = label; // this comes from Code label m_name = name; m_codeSize = codeSize; m_loadAddress = loadAddress; + this.teamId = teamId; m_myIndex = myIndex; m_state = new CpuStateRiscV(); - initializeCpuState(loadAddress, initialStack, groupSharedMemory, useNewMemory); - - stackRegion = new MemoryRegion(initialStack, initialStack + STACK_SIZE - 1); - sharedRegion = new MemoryRegion(groupSharedMemory, groupSharedMemory + GROUP_SHARED_MEMORY_SIZE - 1); + initializeCpuState(loadAddress); - RestrictedMemory memory = new RestrictedMemory(core, new MemoryRegion[]{ - sharedRegion, stackRegion, arenaRegion - }, useNewMemory); + bus.addRegion(arenaRegion, core); - m_cpu = new CpuRiscV(m_state, memory); + m_cpu = new CpuRiscV(m_state, bus); - m_isAlive = true; - } - - // Quick and dirty hack for creating a seam for unit testing - public void setCpu(CpuRiscV cpu) - { - m_cpu = cpu; + m_isAlive = true; } /** @@ -82,7 +93,7 @@ public boolean isAlive() { */ public void kill() { m_isAlive = false; - } + } /** * @return the warrior's name. @@ -90,6 +101,7 @@ public void kill() { public String getName() { return m_name; } + public String getLabel() { return m_label; } @@ -98,8 +110,9 @@ public String getLabel() { * @return the warrior's load offset. */ public short getLoadOffset() { - return (short)(m_loadAddress); + return (short) (m_loadAddress); } + public int getLoadOffsetInt() { return m_loadAddress & 0xFFFF; } @@ -118,68 +131,56 @@ public int getCodeSize() { public short getEnergy() { return 0; } - public void setEnergy(short value) { } + + public void setEnergy(short value) { + } /** * Performs the warrior's next turn (= next InstructionInfo). - * @throws CpuException on any CPU error. - * @throws MemoryException on any RawMemory error. + * + * @throws CpuException on any CPU error. + * @throws MemoryException on any RawMemory error. */ public void nextOpcode() throws CpuException, MemoryException { m_cpu.nextOpcode(); - if(m_cpu.getState().getPc() >= ARENA_SIZE || m_cpu.getState().getPc() < 0) - { + if (m_cpu.getState().getPc() >= ARENA_SIZE || m_cpu.getState().getPc() < 0) { throw new MemoryException("Warrior " + m_name + " tried to execute instructions outside of the arena"); } } /** * Initializes the CpuRiscV registers & flags: + *

+ * x1 and PC - To the warriors load address in the memory * - * x1 and PC - To the warriors load address in the memory - * x2 - The stack - * x3 - The shared memory between the players in the team - * - * @param loadAddress Warrior's load address in the core. - * @param initialStack Warrior's private stack. - * @param groupSharedMemory The warrior's group shared memory. + * @param loadAddress Warrior's load address in the core. */ - private void initializeCpuState( - int loadAddress, - int initialStack, - int groupSharedMemory, - boolean useNewMemory) { - + private void initializeCpuState(int loadAddress) { int loadIndex = (loadAddress) & 0xFFFF; // initialize registers m_state.setPc(loadIndex); m_state.setReg(1, loadIndex); - if(useNewMemory) { - m_state.setReg(2, initialStack + STACK_SIZE - 1); - m_state.setReg(3, groupSharedMemory); - } + } + public CpuStateRiscV getCpuState() { + return m_state; + } + public MemoryBus getBus() { + return bus; } - - public CpuStateRiscV getCpuState(){ - return m_state; + + public int getTeamId() { + return teamId; } - /** Warrior's name */ - private final String m_name; - private final String m_label; - /** Warrior's initial code size */ - private final int m_codeSize; - /** Warrior's initial load address */ - private final int m_loadAddress; - /** Current state of registers & flags */ - private CpuStateRiscV m_state; - /** CPU instance */ - private CpuRiscV m_cpu; - /** Whether or not the warrior is still alive */ - private boolean m_isAlive; + public CpuRiscV getCpu() { + return m_cpu; + } - public final int m_myIndex; // in the War m_warriors array. used for identifying breakpoints + // Quick and dirty hack for creating a seam for unit testing + public void setCpu(CpuRiscV cpu) { + m_cpu = cpu; + } } \ No newline at end of file diff --git a/test/il/co/codeguru/corewars_riscv/cpu/riscv/InstructionDecoderTest.java b/test/il/co/codeguru/corewars_riscv/cpu/riscv/InstructionDecoder32ITest.java similarity index 74% rename from test/il/co/codeguru/corewars_riscv/cpu/riscv/InstructionDecoderTest.java rename to test/il/co/codeguru/corewars_riscv/cpu/riscv/InstructionDecoder32ITest.java index 8a66c88..3ec02e0 100644 --- a/test/il/co/codeguru/corewars_riscv/cpu/riscv/InstructionDecoderTest.java +++ b/test/il/co/codeguru/corewars_riscv/cpu/riscv/InstructionDecoder32ITest.java @@ -2,23 +2,23 @@ import il.co.codeguru.corewars_riscv.cpu.exceptions.CpuException; import il.co.codeguru.corewars_riscv.cpu.exceptions.InvalidOpcodeException; -import il.co.codeguru.corewars_riscv.cpu.riscv.instruction_formats.InstructionFormatBase; +import il.co.codeguru.corewars_riscv.cpu.riscv.rv32i.instruction_formats.InstructionFormatBase; +import il.co.codeguru.corewars_riscv.cpu.riscv.rv32i.InstructionDecoder32I; import il.co.codeguru.corewars_riscv.memory.MemoryException; import il.co.codeguru.corewars_riscv.utils.Logger; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import static junit.framework.TestCase.fail; -public class InstructionDecoderTest { +public class InstructionDecoder32ITest { - private InstructionDecoder decoder; + private InstructionDecoder32I decoder; @Before public void setUp() { - decoder = new InstructionDecoder(); + decoder = new InstructionDecoder32I(); Logger.setTestingMode(); } diff --git a/test/il/co/codeguru/corewars_riscv/cpu/riscv/InstructionFormatTest.java b/test/il/co/codeguru/corewars_riscv/cpu/riscv/InstructionFormatTest.java index 5c124c2..1473d7f 100644 --- a/test/il/co/codeguru/corewars_riscv/cpu/riscv/InstructionFormatTest.java +++ b/test/il/co/codeguru/corewars_riscv/cpu/riscv/InstructionFormatTest.java @@ -1,6 +1,7 @@ package il.co.codeguru.corewars_riscv.cpu.riscv; -import il.co.codeguru.corewars_riscv.cpu.riscv.instruction_formats.*; +import il.co.codeguru.corewars_riscv.cpu.riscv.rv32i.RV32I; +import il.co.codeguru.corewars_riscv.cpu.riscv.rv32i.instruction_formats.*; import il.co.codeguru.corewars_riscv.utils.Logger; import org.junit.Before; import org.junit.Test; @@ -22,7 +23,7 @@ public void testZeroOpcode() { @Test public void testOpCodeIs7LSB() { - InstructionFormatBase a = new InstructionFormatBase((short) 0xFFFFFFFF); + InstructionFormatBase a = new InstructionFormatBase(0xFFFFFFFF); assertEquals(0x7F, a.getOpcode()); } diff --git a/test/il/co/codeguru/corewars_riscv/cpu/riscv/instruction_tests/ImmediateTest.java b/test/il/co/codeguru/corewars_riscv/cpu/riscv/instruction_tests/ImmediateTest.java index 0e2ad1d..6f79311 100644 --- a/test/il/co/codeguru/corewars_riscv/cpu/riscv/instruction_tests/ImmediateTest.java +++ b/test/il/co/codeguru/corewars_riscv/cpu/riscv/instruction_tests/ImmediateTest.java @@ -5,8 +5,8 @@ import il.co.codeguru.corewars_riscv.cpu.riscv.CpuStateRiscV; import il.co.codeguru.corewars_riscv.memory.Memory; import il.co.codeguru.corewars_riscv.memory.RawMemory; -import il.co.codeguru.corewars_riscv.cpu.riscv.RV32I; -import il.co.codeguru.corewars_riscv.cpu.riscv.instruction_formats.InstructionFormatBase; +import il.co.codeguru.corewars_riscv.cpu.riscv.rv32i.RV32I; +import il.co.codeguru.corewars_riscv.cpu.riscv.rv32i.instruction_formats.InstructionFormatBase; import il.co.codeguru.corewars_riscv.memory.MemoryException; import il.co.codeguru.corewars_riscv.utils.Logger; import junitparams.JUnitParamsRunner; diff --git a/test/il/co/codeguru/corewars_riscv/cpu/riscv/instruction_tests/JumpTest.java b/test/il/co/codeguru/corewars_riscv/cpu/riscv/instruction_tests/JumpTest.java index 264043f..6bdef8d 100644 --- a/test/il/co/codeguru/corewars_riscv/cpu/riscv/instruction_tests/JumpTest.java +++ b/test/il/co/codeguru/corewars_riscv/cpu/riscv/instruction_tests/JumpTest.java @@ -6,8 +6,8 @@ import il.co.codeguru.corewars_riscv.cpu.riscv.CpuStateRiscV; import il.co.codeguru.corewars_riscv.memory.Memory; import il.co.codeguru.corewars_riscv.memory.RawMemory; -import il.co.codeguru.corewars_riscv.cpu.riscv.RV32I; -import il.co.codeguru.corewars_riscv.cpu.riscv.instruction_formats.InstructionFormatBase; +import il.co.codeguru.corewars_riscv.cpu.riscv.rv32i.RV32I; +import il.co.codeguru.corewars_riscv.cpu.riscv.rv32i.instruction_formats.InstructionFormatBase; import il.co.codeguru.corewars_riscv.memory.MemoryException; import il.co.codeguru.corewars_riscv.utils.Logger; import junitparams.JUnitParamsRunner; diff --git a/test/il/co/codeguru/corewars_riscv/cpu/riscv/instruction_tests/LoadTest.java b/test/il/co/codeguru/corewars_riscv/cpu/riscv/instruction_tests/LoadTest.java index 6725d6a..d472976 100644 --- a/test/il/co/codeguru/corewars_riscv/cpu/riscv/instruction_tests/LoadTest.java +++ b/test/il/co/codeguru/corewars_riscv/cpu/riscv/instruction_tests/LoadTest.java @@ -5,8 +5,8 @@ import il.co.codeguru.corewars_riscv.cpu.riscv.CpuStateRiscV; import il.co.codeguru.corewars_riscv.memory.Memory; import il.co.codeguru.corewars_riscv.memory.RawMemory; -import il.co.codeguru.corewars_riscv.cpu.riscv.RV32I; -import il.co.codeguru.corewars_riscv.cpu.riscv.instruction_formats.InstructionFormatBase; +import il.co.codeguru.corewars_riscv.cpu.riscv.rv32i.RV32I; +import il.co.codeguru.corewars_riscv.cpu.riscv.rv32i.instruction_formats.InstructionFormatBase; import il.co.codeguru.corewars_riscv.memory.MemoryException; import il.co.codeguru.corewars_riscv.utils.Logger; import junitparams.JUnitParamsRunner; diff --git a/test/il/co/codeguru/corewars_riscv/cpu/riscv/instruction_tests/RegisterTest.java b/test/il/co/codeguru/corewars_riscv/cpu/riscv/instruction_tests/RegisterTest.java index 15f9909..70cf47e 100644 --- a/test/il/co/codeguru/corewars_riscv/cpu/riscv/instruction_tests/RegisterTest.java +++ b/test/il/co/codeguru/corewars_riscv/cpu/riscv/instruction_tests/RegisterTest.java @@ -5,8 +5,8 @@ import il.co.codeguru.corewars_riscv.cpu.riscv.CpuStateRiscV; import il.co.codeguru.corewars_riscv.memory.Memory; import il.co.codeguru.corewars_riscv.memory.RawMemory; -import il.co.codeguru.corewars_riscv.cpu.riscv.RV32I; -import il.co.codeguru.corewars_riscv.cpu.riscv.instruction_formats.InstructionFormatBase; +import il.co.codeguru.corewars_riscv.cpu.riscv.rv32i.RV32I; +import il.co.codeguru.corewars_riscv.cpu.riscv.rv32i.instruction_formats.InstructionFormatBase; import il.co.codeguru.corewars_riscv.memory.MemoryException; import il.co.codeguru.corewars_riscv.utils.Logger; import junitparams.JUnitParamsRunner; diff --git a/test/il/co/codeguru/corewars_riscv/cpu/riscv/instruction_tests/StoreTest.java b/test/il/co/codeguru/corewars_riscv/cpu/riscv/instruction_tests/StoreTest.java index 4f41d99..d64e108 100644 --- a/test/il/co/codeguru/corewars_riscv/cpu/riscv/instruction_tests/StoreTest.java +++ b/test/il/co/codeguru/corewars_riscv/cpu/riscv/instruction_tests/StoreTest.java @@ -5,8 +5,8 @@ import il.co.codeguru.corewars_riscv.cpu.riscv.CpuStateRiscV; import il.co.codeguru.corewars_riscv.memory.Memory; import il.co.codeguru.corewars_riscv.memory.RawMemory; -import il.co.codeguru.corewars_riscv.cpu.riscv.RV32I; -import il.co.codeguru.corewars_riscv.cpu.riscv.instruction_formats.InstructionFormatBase; +import il.co.codeguru.corewars_riscv.cpu.riscv.rv32i.RV32I; +import il.co.codeguru.corewars_riscv.cpu.riscv.rv32i.instruction_formats.InstructionFormatBase; import il.co.codeguru.corewars_riscv.memory.MemoryException; import il.co.codeguru.corewars_riscv.utils.Logger; import junitparams.JUnitParamsRunner; diff --git a/test/il/co/codeguru/corewars_riscv/cpu/riscv/instruction_tests/UTest.java b/test/il/co/codeguru/corewars_riscv/cpu/riscv/instruction_tests/UTest.java index af834aa..dddd309 100644 --- a/test/il/co/codeguru/corewars_riscv/cpu/riscv/instruction_tests/UTest.java +++ b/test/il/co/codeguru/corewars_riscv/cpu/riscv/instruction_tests/UTest.java @@ -5,8 +5,8 @@ import il.co.codeguru.corewars_riscv.cpu.riscv.CpuStateRiscV; import il.co.codeguru.corewars_riscv.memory.Memory; import il.co.codeguru.corewars_riscv.memory.RawMemory; -import il.co.codeguru.corewars_riscv.cpu.riscv.RV32I; -import il.co.codeguru.corewars_riscv.cpu.riscv.instruction_formats.InstructionFormatBase; +import il.co.codeguru.corewars_riscv.cpu.riscv.rv32i.RV32I; +import il.co.codeguru.corewars_riscv.cpu.riscv.rv32i.instruction_formats.InstructionFormatBase; import il.co.codeguru.corewars_riscv.memory.MemoryException; import il.co.codeguru.corewars_riscv.utils.Logger; import junitparams.JUnitParamsRunner; diff --git a/test/il/co/codeguru/corewars_riscv/features/FeatureSetTest.java b/test/il/co/codeguru/corewars_riscv/features/FeatureSetTest.java new file mode 100644 index 0000000..59455ac --- /dev/null +++ b/test/il/co/codeguru/corewars_riscv/features/FeatureSetTest.java @@ -0,0 +1,27 @@ +package il.co.codeguru.corewars_riscv.features; + +import il.co.codeguru.corewars_riscv.war.Warrior; +import org.junit.Assert; +import org.junit.Test; + +public class FeatureSetTest { + + class EmptyFeature extends Feature { + + @Override + public void initWarriorGroup(Warrior... warriors) { + + } + } + + @Test + public void enableSingleTest() { + FeatureSet set = new FeatureSet(); + Feature f = new EmptyFeature(); + set.register("new-feature", f); + + set.enableFeature("new-feature"); + + Assert.assertArrayEquals(set.getEnabledFeatures(), new Feature[]{f}); + } +} diff --git a/test/il/co/codeguru/corewars_riscv/utils/DisassemblerRiscVTest.java b/test/il/co/codeguru/corewars_riscv/utils/DisassemblerRiscVTest.java index f28653f..64e114a 100644 --- a/test/il/co/codeguru/corewars_riscv/utils/DisassemblerRiscVTest.java +++ b/test/il/co/codeguru/corewars_riscv/utils/DisassemblerRiscVTest.java @@ -1,7 +1,7 @@ package il.co.codeguru.corewars_riscv.utils; -import il.co.codeguru.corewars_riscv.cpu.riscv.RV32I; -import il.co.codeguru.corewars_riscv.cpu.riscv.instruction_formats.InstructionFormatBase; +import il.co.codeguru.corewars_riscv.cpu.riscv.rv32i.RV32I; +import il.co.codeguru.corewars_riscv.cpu.riscv.rv32i.instruction_formats.InstructionFormatBase; import il.co.codeguru.corewars_riscv.cpu.riscv.rv32c.RV32C; import il.co.codeguru.corewars_riscv.cpu.riscv.rv32c.instruction_formats.CInstructionFormatBase; import il.co.codeguru.corewars_riscv.utils.disassembler.DisassemblerRiscV;