diff --git a/.gitignore b/.gitignore index 093805de..4df50ddf 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,10 @@ out .classpath .project examples/riscv + +# RARS build +build/ +rars.jar + +# macOS +.DS_Store diff --git a/examples/atomic_increment.s b/examples/atomic_increment.s new file mode 100644 index 00000000..01757c14 --- /dev/null +++ b/examples/atomic_increment.s @@ -0,0 +1,15 @@ +.globl main +.data +num: + .word 0x12345678 + +.text +main: + la t0, num +retry: + lr.w t1, (t0) + # increment by 1 + addi t1, t1, 1 + sc.w t2, t1, (t0) + # if save fails; retry operations again + bne zero, t2, retry diff --git a/src/Settings.properties b/src/Settings.properties index 8c02d809..78d1e9e5 100644 --- a/src/Settings.properties +++ b/src/Settings.properties @@ -30,4 +30,4 @@ DataSegmentHighlightBackground = 0x0099ccff DataSegmentHighlightForeground = 0 RegisterHighlightBackground = 0x0099cc55 RegisterHighlightForeground = 0 - +PerHartExecution = false diff --git a/src/images/Shared.png b/src/images/Shared.png new file mode 100644 index 00000000..320a5b1b Binary files /dev/null and b/src/images/Shared.png differ diff --git a/src/rars/Globals.java b/src/rars/Globals.java index 1696930d..ef8f1bbe 100644 --- a/src/rars/Globals.java +++ b/src/rars/Globals.java @@ -2,10 +2,12 @@ import rars.assembler.SymbolTable; import rars.riscv.hardware.Memory; +import rars.riscv.hardware.ReservationTables; import rars.riscv.InstructionSet; import rars.riscv.SyscallNumberOverride; import rars.util.PropertiesFile; import rars.venus.VenusUI; +import rars.venus.GeneralVenusUI; import java.util.ArrayList; import java.util.Enumeration; @@ -60,6 +62,8 @@ public class Globals { * the program currently being worked with. Used by GUI only, not command line. **/ public static RISCVprogram program; + + public static ArrayList gPrograms; /** * Symbol table for file currently being assembled. **/ @@ -68,6 +72,10 @@ public class Globals { * Simulated memory component. **/ public static Memory memory; + /** + * Simulated reservation tables component. + **/ + public static ReservationTables reservationTables; /** * Lock variable used at head of synchronized block to guard memory and registers **/ @@ -140,6 +148,34 @@ public class Globals { public static boolean runSpeedPanelExists = false; + private static int harts = 1; + + private static ArrayList hartWindows = new ArrayList<>(); + + public static void setHartWindows() { + for (int i = 1; i < Globals.getHarts(); i++) { + hartWindows.add(new GeneralVenusUI(i - 1)); + } + } + + public static ArrayList getHartWindows(){ + return hartWindows; + } + + public static int getHarts() { + return harts; + } + + public static void setHarts(int i) { + if ((harts == 1 && i < 0) || (harts == 7 && i > 0)) { + return; + } if (i > 0) { + reservationTables = new ReservationTables(++harts); + } else { + reservationTables = new ReservationTables(--harts); + } + } + private static String getCopyrightYears() { return "2003-2019"; } @@ -166,7 +202,8 @@ public static Settings getSettings() { public static void initialize(boolean gui) { if (!initialized) { - memory = Memory.getInstance(); //clients can use Memory.getInstance instead of Globals.memory + memory = Memory.getInstance(); //clients can use Memory.getInstance instead of Globals.memory + reservationTables = new ReservationTables(harts); symbolTable = new SymbolTable("global"); settings = new Settings(gui); instructionSet = new InstructionSet(); diff --git a/src/rars/Launch.java b/src/rars/Launch.java index d0e43311..70f71d10 100644 --- a/src/rars/Launch.java +++ b/src/rars/Launch.java @@ -78,6 +78,7 @@ public class Launch { * segments are .text and .data. Current supported dump formats
* are Binary, HexText, BinaryText.
* h -- display help. Use by itself and with no filename
+ * harts -- the amount of harts to use for running RARS with
* hex -- display memory or register contents in hexadecimal (default)
* ic -- display count of basic instructions 'executed'"); * mc -- set memory configuration. Option has 1 argument, e.g.
@@ -384,6 +385,10 @@ private boolean parseCommandArgs(String[] args) { countInstructions = true; continue; } + if (args[i].toLowerCase().equals("harts")) { + Globals.setHarts(Integer.valueOf(args[++i])); + continue; + } if (new File(args[i]).exists()) { // is it a file name? filenameList.add(args[i]); @@ -713,6 +718,7 @@ private void displayHelp() { out.println(" = " + segments+", or a range like 0x400000-0x10000000"); out.println(" = " + formats); out.println(" h -- display this help. Use by itself with no filename."); + out.println(" harts -- the amount of harts to use for running RARS with"); out.println(" hex -- display memory or register contents in hexadecimal (default)"); out.println(" ic -- display count of basic instructions 'executed'"); out.println(" mc -- set memory configuration. Argument is"); @@ -749,5 +755,3 @@ private void displayHelp() { } } - - diff --git a/src/rars/ProgramStatement.java b/src/rars/ProgramStatement.java index cce4d6f2..c3470d56 100644 --- a/src/rars/ProgramStatement.java +++ b/src/rars/ProgramStatement.java @@ -65,6 +65,7 @@ public class ProgramStatement implements Comparable { private int textAddress; private int sourceLine; private int binaryStatement; + private int currrentHart; private boolean altered; private static final String invalidOperator = ""; @@ -517,6 +518,15 @@ public void setSource(String src) { source = src; } + /** + * Set the current hart for this program statement. + * + * @param hart the new current hart + */ + public void setCurrentHart(int hart) { + currrentHart = hart; + } + /** * Produces RISCVprogram object representing the source file containing this statement. @@ -645,6 +655,15 @@ public int[] getOperands() { return operands; } + /** + * Produces current hart that will simulate this statement. + * + * @return curent hart. + */ + public int getCurrentHart() { + return currrentHart; + } + /** * Produces operand value from given array position (first operand is position 0). * @@ -873,5 +892,4 @@ private class ListElement { } } } - } diff --git a/src/rars/RISCVprogram.java b/src/rars/RISCVprogram.java index d9a9e6a8..7578b6a5 100644 --- a/src/rars/RISCVprogram.java +++ b/src/rars/RISCVprogram.java @@ -366,6 +366,10 @@ public void startSimulation(int maxSteps, int[] breakPoints) { sim.startSimulation(RegisterFile.getProgramCounter(), maxSteps, breakPoints); } + public void startSimulation(int maxSteps, int[] breakPoints, int hart) { + Simulator sim = Simulator.getInstance(hart); + sim.startSimulation(RegisterFile.getProgramCounter(hart), maxSteps, breakPoints, hart); + } /** * Instantiates a new {@link MacroPool} and sends reference of this * {@link RISCVprogram} to it diff --git a/src/rars/Settings.java b/src/rars/Settings.java index 70f86ef6..42aadc0d 100644 --- a/src/rars/Settings.java +++ b/src/rars/Settings.java @@ -153,7 +153,11 @@ public enum Bool { /** * Flag to determine whether a program uses rv64i instead of rv32i */ - RV64_ENABLED("rv64Enabled", false);; + RV64_ENABLED("rv64Enabled", false), + /** + * Flag to determine if the step buttons should run for all harts or just indivdual hart + */ + PER_HART_EXECUTION("PerHartExecution", false);; // TODO: add option for turning off user trap handling and interrupts private String name; @@ -1320,4 +1324,4 @@ private int[] getTextSegmentColumnOrder(String stringOfColumnIndexes) { return list; } -} \ No newline at end of file +} diff --git a/src/rars/api/Program.java b/src/rars/api/Program.java index f0b0f0db..26897876 100644 --- a/src/rars/api/Program.java +++ b/src/rars/api/Program.java @@ -130,6 +130,7 @@ private ErrorList assemble(ArrayList programs) throws AssemblyExce */ public void setup(ArrayList args, String STDIN){ RegisterFile.resetRegisters(); + Globals.reservationTables.reset(); FloatingPointRegisterFile.resetRegisters(); ControlAndStatusRegisterFile.resetRegisters(); InterruptController.reset(); diff --git a/src/rars/riscv/BasicInstructionFormat.java b/src/rars/riscv/BasicInstructionFormat.java index c607e051..fce2261f 100644 --- a/src/rars/riscv/BasicInstructionFormat.java +++ b/src/rars/riscv/BasicInstructionFormat.java @@ -41,5 +41,5 @@ public enum BasicInstructionFormat { S_FORMAT, // 2 src registers + small immediate B_FORMAT, // 2 src registers + small immediate shifted left U_FORMAT, // 1 dst register + large immediate - J_FORMAT // 1 dst register + large immediate for jumping + J_FORMAT, // 1 dst register + large immediate for jumping } diff --git a/src/rars/riscv/InstructionSet.java b/src/rars/riscv/InstructionSet.java index b186eb2f..a2fcf31f 100644 --- a/src/rars/riscv/InstructionSet.java +++ b/src/rars/riscv/InstructionSet.java @@ -310,6 +310,10 @@ public static void processBranch(int displacement) { // Decrement needed because PC has already been incremented RegisterFile.setProgramCounter(RegisterFile.getProgramCounter() + displacement - Instruction.INSTRUCTION_LENGTH); } + public static void processBranch(int displacement, int hart) { + // Decrement needed because PC has already been incremented + RegisterFile.setProgramCounter(RegisterFile.getProgramCounter(hart) + displacement - Instruction.INSTRUCTION_LENGTH, hart); + } /* * Method to process a jump. DO NOT USE WITH BRANCH INSTRUCTIONS! @@ -322,7 +326,9 @@ public static void processBranch(int displacement) { public static void processJump(int targetAddress) { RegisterFile.setProgramCounter(targetAddress); } - + public static void processJump(int targetAddress, int hart) { + RegisterFile.setProgramCounter(targetAddress, hart); + } /* * Method to process storing of a return address in the given * register. This is used only by the "and link" @@ -333,7 +339,9 @@ public static void processJump(int targetAddress) { public static void processReturnAddress(int register) { RegisterFile.updateRegister(register, RegisterFile.getProgramCounter()); } - + public static void processReturnAddress(int register, int hart){ + RegisterFile.updateRegister(register, RegisterFile.getProgramCounter(hart), hart); + } private static class MatchMap implements Comparable { private int mask; private int maskLength; // number of 1 bits in mask @@ -368,4 +376,3 @@ public BasicInstruction find(int instr) { } } } - diff --git a/src/rars/riscv/hardware/ControlAndStatusRegisterFile.java b/src/rars/riscv/hardware/ControlAndStatusRegisterFile.java index bf1d88dc..c7d6378f 100644 --- a/src/rars/riscv/hardware/ControlAndStatusRegisterFile.java +++ b/src/rars/riscv/hardware/ControlAndStatusRegisterFile.java @@ -2,6 +2,7 @@ import rars.Globals; +import java.util.ArrayList; import java.util.Observer; /* @@ -70,16 +71,48 @@ public class ControlAndStatusRegisterFile { null, // cycleh null, // timeh null, // instreth + null, // mhartid }; tmp[1] = new LinkedRegister("fflags", 0x001, tmp[3], 0x1F); tmp[2] = new LinkedRegister("frm", 0x002, tmp[3], 0xE0); tmp[14] = new LinkedRegister("cycleh", 0xC80,tmp[11], 0xFFFFFFFF_00000000L); tmp[15] = new LinkedRegister("timeh", 0xC81, tmp[12],0xFFFFFFFF_00000000L); - tmp[16] = new LinkedRegister("instreth",0xC82, tmp[13],0xFFFFFFFF_00000000L); + tmp[16] = new LinkedRegister("instreth", 0xC82, tmp[13], 0xFFFFFFFF_00000000L); + tmp[17] = new ReadOnlyRegister("mhartid", 0xF10, 0); instance = new RegisterBlock('_', tmp); // prefix not used } + public static ArrayList gInstance = new ArrayList<>(); + + public static void changeHarts(int sign) { + if (sign > 0) { + Register[] tmp = new Register[] { new MaskedRegister("ustatus", 0x000, 0, ~0x11), null, // fflags + null, // frm + new MaskedRegister("fcsr", 0x003, 0, ~0xFF), new Register("uie", 0x004, 0), + new Register("utvec", 0x005, 0), new Register("uscratch", 0x040, 0), + new Register("uepc", 0x041, 0), new Register("ucause", 0x042, 0), + new Register("utval", 0x043, 0), new Register("uip", 0x044, 0), + new ReadOnlyRegister("cycle", 0xC00, 0), new ReadOnlyRegister("time", 0xC01, 0), + new ReadOnlyRegister("instret", 0xC02, 0), null, // cycleh + null, // timeh + null, // instreth + null, // mhartid + }; + tmp[1] = new LinkedRegister("fflags", 0x001, tmp[3], 0x1F); + tmp[2] = new LinkedRegister("frm", 0x002, tmp[3], 0xE0); + tmp[14] = new LinkedRegister("cycleh", 0xC80, tmp[11], 0xFFFFFFFF_00000000L); + tmp[15] = new LinkedRegister("timeh", 0xC81, tmp[12], 0xFFFFFFFF_00000000L); + tmp[16] = new LinkedRegister("instreth", 0xC82, tmp[13], 0xFFFFFFFF_00000000L); + tmp[17] = new ReadOnlyRegister("mhartid", 0xF10, Globals.getHarts() - 1); + RegisterBlock temp = new RegisterBlock('_', tmp); + gInstance.add(temp); + } + if (sign < 0) { + gInstance.remove(gInstance.size() - 1); + } + } + /** * This method updates the register value * @@ -103,6 +136,22 @@ public static boolean updateRegister(int num, long val) { return false; } + public static boolean updateRegister(int num, long val, int hart) { + if (gInstance.get(hart).getRegister(num) instanceof ReadOnlyRegister) { + return true; + } + if (num >= 0xC80 && num <= 0xC82) { + return true; + } + if ((Globals.getSettings().getBackSteppingEnabled())) { + Globals.program.getBackStepper().addControlAndStatusRestore(num, + gInstance.get(hart).updateRegister(num, val)); + } else { + gInstance.get(hart).updateRegister(num, val); + } + return false; + } + /** * This method updates the register value * @@ -114,6 +163,10 @@ public static void updateRegister(String name, long val) { updateRegister(instance.getRegister(name).getNumber(), val); } + public static void updateRegister(String name, long val, int hart) { + updateRegister(gInstance.get(hart).getRegister(name).getNumber(), val, hart); + } + /** * This method updates the register value silently and bypasses read only * @@ -129,6 +182,15 @@ public static void updateRegisterBackdoor(int num, long val) { } } + public static void updateRegisterBackdoor(int num, long val, int hart) { + if ((Globals.getSettings().getBackSteppingEnabled())) { + Globals.program.getBackStepper().addControlAndStatusBackdoor(num, + gInstance.get(hart).getRegister(num).setValueBackdoor(val)); + } else { + gInstance.get(hart).getRegister(num).setValueBackdoor(val); + } + } + /** * This method updates the register value silently and bypasses read only * @@ -140,6 +202,11 @@ public static void updateRegisterBackdoor(String name, long val) { updateRegisterBackdoor(instance.getRegister(name).getNumber(), val); } + public static void updateRegisterBackdoor(String name, long val, int hart) { + System.out.printf("Getting secondary hart %d out of %d total secondary harts\n", hart, gInstance.size()); + updateRegisterBackdoor(gInstance.get(hart).getRegister(name).getNumber(), val, hart); + } + /** * ORs a register with a value * @@ -150,6 +217,10 @@ public static boolean orRegister(int num, long val) { return updateRegister(num, instance.getValue(num) | val); } + public static boolean orRegister(int num, long val, int hart) { + return updateRegister(num, gInstance.get(hart).getValue(num) | val, hart); + } + /** * ORs a register with a value * @@ -160,6 +231,10 @@ public static void orRegister(String name, long val) { updateRegister(name, instance.getValue(name) | val); } + public static void orRegister(String name, long val, int hart) { + updateRegister(name, gInstance.get(hart).getValue(name) | val, hart); + } + /** * Clears bits from a register according to a value * @@ -170,6 +245,10 @@ public static boolean clearRegister(int num, long val) { return updateRegister(num, instance.getValue(num) & ~val); } + public static boolean clearRegister(int num, long val, int hart) { + return updateRegister(num, gInstance.get(hart).getValue(num) & ~val, hart); + } + /** * Clears bits from a register according to a value * @@ -180,6 +259,10 @@ public static void clearRegister(String name, long val) { updateRegister(name, instance.getValue(name) & ~val); } + public static void clearRegister(String name, long val, int hart) { + updateRegister(name, gInstance.get(hart).getValue(name) & ~val, hart); + } + /** * Returns the value of the register * @@ -188,7 +271,11 @@ public static void clearRegister(String name, long val) { **/ public static int getValue(int num) { - return (int)instance.getValue(num); + return (int) instance.getValue(num); + } + + public static int getValue(int num, int hart) { + return (int) gInstance.get(hart).getValue(num); } /** @@ -201,6 +288,11 @@ public static int getValue(int num) { public static long getValueLong(int num) { return instance.getValue(num); } + + public static long getValueLong(int num, int hart) { + return gInstance.get(hart).getValue(num); + } + /** * Returns the value of the register * @@ -209,7 +301,11 @@ public static long getValueLong(int num) { **/ public static int getValue(String name) { - return (int)instance.getValue(name); + return (int) instance.getValue(name); + } + + public static int getValue(String name, int hart) { + return (int) gInstance.get(hart).getValue(name); } /** @@ -223,6 +319,10 @@ public static long getValueNoNotify(String name) { return instance.getRegister(name).getValueNoNotify(); } + public static long getValueNoNotify(String name, int hart) { + return gInstance.get(hart).getRegister(name).getValueNoNotify(); + } + /** * For returning the set of registers. * @@ -233,6 +333,10 @@ public static Register[] getRegisters() { return instance.getRegisters(); } + public static Register[] getRegisters(int hart) { + return gInstance.get(hart).getRegisters(); + } + /** * ControlAndStatusRegisterFile implements a wide range of register numbers that don't math the position in the underlying array diff --git a/src/rars/riscv/hardware/FloatingPointRegisterFile.java b/src/rars/riscv/hardware/FloatingPointRegisterFile.java index 949bcc0c..f3972b28 100644 --- a/src/rars/riscv/hardware/FloatingPointRegisterFile.java +++ b/src/rars/riscv/hardware/FloatingPointRegisterFile.java @@ -2,6 +2,7 @@ import rars.Globals; +import java.util.ArrayList; import java.util.Observer; /* @@ -64,6 +65,26 @@ public class FloatingPointRegisterFile { new Register("ft8", 28, 0), new Register("ft9", 29, 0), new Register("ft10", 30, 0), new Register("ft11", 31, 0) }); + private static final ArrayList gInstance = new ArrayList<>(); + + public static void increaseHarts() { + gInstance.add(new RegisterBlock('f', + new Register[] { new Register("ft0", 0, 0), new Register("ft1", 1, 0), new Register("ft2", 2, 0), + new Register("ft3", 3, 0), new Register("ft4", 4, 0), new Register("ft5", 5, 0), + new Register("ft6", 6, 0), new Register("ft7", 7, 0), new Register("fs0", 8, 0), + new Register("fs1", 9, 0), new Register("fa0", 10, 0), new Register("fa1", 11, 0), + new Register("fa2", 12, 0), new Register("fa3", 13, 0), new Register("fa4", 14, 0), + new Register("fa5", 15, 0), new Register("fa6", 16, 0), new Register("fa7", 17, 0), + new Register("fs2", 18, 0), new Register("fs3", 19, 0), new Register("fs4", 20, 0), + new Register("fs5", 21, 0), new Register("fs6", 22, 0), new Register("fs7", 23, 0), + new Register("fs8", 24, 0), new Register("fs9", 25, 0), new Register("fs10", 26, 0), + new Register("fs11", 27, 0), new Register("ft8", 28, 0), new Register("ft9", 29, 0), + new Register("ft10", 30, 0), new Register("ft11", 31, 0) })); + } + + public static void decreaseHarts() { + gInstance.remove(gInstance.size() - 1); + } /** * Sets the value of the FPU register given to the value given. @@ -71,22 +92,28 @@ public class FloatingPointRegisterFile { * @param reg Register to set the value of. * @param val The desired float value for the register. **/ - public static void setRegisterToFloat(int reg, float val) { updateRegister(reg, Float.floatToRawIntBits(val)); } + public static void setRegisterToFloat(int reg, float val, int hart) { + updateRegister(reg, Float.floatToRawIntBits(val), hart); + } + /** * Gets the float value stored in the given FPU register. * * @param name Register to get the value of. * @return The float value stored by that register. **/ - public static float getFloatFromRegister(String name) { return Float.intBitsToFloat(getValue(name)); } + public static float getFloatFromRegister(String name, int hart) { + return Float.intBitsToFloat(getValue(name)); + } + /** * This method updates the FPU register value who's number is num. Note the * registers themselves hold an int value. There are helper methods available @@ -95,7 +122,6 @@ public static float getFloatFromRegister(String name) { * @param num FPU register to set the value of. * @param val The desired int value for the register. **/ - public static void updateRegister(int num, int val) { long lval = val | 0xFFFFFFFF_00000000L; // NAN box if used as float if ((Globals.getSettings().getBackSteppingEnabled())) { @@ -105,6 +131,16 @@ public static void updateRegister(int num, int val) { } } + public static void updateRegister(int num, int val, int hart) { + long lval = val | 0xFFFFFFFF_00000000L; // NAN box if used as float + if ((Globals.getSettings().getBackSteppingEnabled())) { + // TODO: enable multithreaded backstepping + Globals.program.getBackStepper().addFloatingPointRestore(num, instance.updateRegister(num, lval)); + } else { + gInstance.get(hart).updateRegister(num, lval); + } + } + public static void updateRegisterLong(int num, long val) { if ((Globals.getSettings().getBackSteppingEnabled())) { Globals.program.getBackStepper().addFloatingPointRestore(num, instance.updateRegister(num, val)); @@ -112,6 +148,16 @@ public static void updateRegisterLong(int num, long val) { instance.updateRegister(num, val); } } + + public static void updateRegisterLong(int num, long val, int hart) { + if ((Globals.getSettings().getBackSteppingEnabled())) { + // TODO: enable multithreaded backstepping + Globals.program.getBackStepper().addFloatingPointRestore(num, instance.updateRegister(num, val)); + } else { + gInstance.get(hart).updateRegister(num, val); + } + } + /** * Gets the raw int value actually stored in a Register. If you need a * float, use Float.intBitsToFloat() to get the equivent float. @@ -119,20 +165,32 @@ public static void updateRegisterLong(int num, long val) { * @param num The FPU register number. * @return The int value of the given register. **/ - public static int getValue(int num) { long lval = instance.getValue(num); - if((lval & 0xFFFFFFFF_00000000L) == 0xFFFFFFFF_00000000L){ - return (int)lval; // If NaN-Boxed return value + if ((lval & 0xFFFFFFFF_00000000L) == 0xFFFFFFFF_00000000L) { + return (int) lval; // If NaN-Boxed return value }else{ return 0x7FC00000; // Otherwise NaN } } + public static int getValue(int num, int hart) { + long lval = gInstance.get(hart).getValue(num); + if ((lval & 0xFFFFFFFF_00000000L) == 0xFFFFFFFF_00000000L) { + return (int) lval; // If NaN-Boxed return value + } else { + return 0x7FC00000; // Otherwise NaN + } + } + public static long getValueLong(int num) { return instance.getValue(num); } + public static long getValueLong(int num, int hart) { + return gInstance.get(hart).getValue(num); + } + /** * Gets the raw int value actually stored in a Register. If you need a * float, use Float.intBitsToFloat() to get the equivent float. @@ -140,12 +198,20 @@ public static long getValueLong(int num) { * @param name The FPU register name. * @return The int value of the given register. **/ - public static int getValue(String name) { long lval = instance.getValue(name); - if((lval & 0xFFFFFFFF_00000000L) == 0xFFFFFFFF_00000000L){ - return (int)lval; - }else{ + if ((lval & 0xFFFFFFFF_00000000L) == 0xFFFFFFFF_00000000L) { + return (int) lval; + } else { + return 0x7FC00000; + } + } + + public static int getValue(String name, int hart) { + long lval = gInstance.get(hart).getValue(name); + if ((lval & 0xFFFFFFFF_00000000L) == 0xFFFFFFFF_00000000L) { + return (int) lval; + } else { return 0x7FC00000; } } @@ -155,29 +221,36 @@ public static int getValue(String name) { * * @return The set of registers. **/ - public static Register[] getRegisters() { return instance.getRegisters(); } + public static Register[] getRegisters(int hart) { + return gInstance.get(hart).getRegisters(); + } + /** * Get register object corresponding to given name. If no match, return null. * * @param name The FPU register name, must be "f0" through "f31". * @return The register object,or null if not found. **/ - public static Register getRegister(String name) { return instance.getRegister(name); } + public static Register getRegister(String name, int hart) { + return gInstance.get(hart).getRegister(name); + } + /** * Method to reinitialize the values of the registers. **/ - public static void resetRegisters() { instance.resetRegisters(); + for (RegisterBlock i : gInstance) + i.resetRegisters(); } diff --git a/src/rars/riscv/hardware/Register.java b/src/rars/riscv/hardware/Register.java index d50667b1..03eede5b 100644 --- a/src/rars/riscv/hardware/Register.java +++ b/src/rars/riscv/hardware/Register.java @@ -41,6 +41,7 @@ public class Register extends Observable { private String name; private int number; private long resetValue; + private int hart; // volatile should be enough to allow safe multi-threaded access // w/o the use of synchronized methods. getValue and setValue // are the only methods here used by the register collection @@ -60,8 +61,15 @@ public Register(String n, int num, long val) { number = num; value = val; resetValue = val; + hart = -1; + } + public Register(String n, int num, long val, int hart) { + name = n; + number = num; + value = val; + resetValue = val; + this.hart = hart; } - /** * Returns the name of the Register. * @@ -132,6 +140,10 @@ public synchronized long setValue(long val) { return old; } + public int getHart(){ + return hart; + } + /** * Sets the value of the register to the val passed to it. This should only * be used to update registers not related to the current instruction. @@ -171,7 +183,10 @@ public synchronized void changeResetValue(long reset) { private void notifyAnyObservers(int type) { if (this.countObservers() > 0) {// && Globals.program != null) && Globals.program.inSteppedExecution()) { this.setChanged(); - this.notifyObservers(new RegisterAccessNotice(type, this.name)); + if(this.hart == -1) + this.notifyObservers(new RegisterAccessNotice(type, this.name)); + else + this.notifyObservers(new RegisterAccessNotice(type, this.name, hart)); } } diff --git a/src/rars/riscv/hardware/RegisterAccessNotice.java b/src/rars/riscv/hardware/RegisterAccessNotice.java index ced06218..d20aea9e 100644 --- a/src/rars/riscv/hardware/RegisterAccessNotice.java +++ b/src/rars/riscv/hardware/RegisterAccessNotice.java @@ -38,23 +38,30 @@ a copy of this software and associated documentation files (the public class RegisterAccessNotice extends AccessNotice { private String registerName; - + private int hart; /** * Constructor will be called only within this package, so assume * register number is in valid range. */ + RegisterAccessNotice(int type, String registerName, int hart) { + super(type); + this.registerName = registerName; + this.hart = hart; + } RegisterAccessNotice(int type, String registerName) { super(type); this.registerName = registerName; + hart = -1; } - /** * Fetch the register number of register accessed. */ public String getRegisterName() { return registerName; } - + public int getHart(){ + return hart; + } /** * String representation indicates access type and which register */ diff --git a/src/rars/riscv/hardware/RegisterFile.java b/src/rars/riscv/hardware/RegisterFile.java index ac5ece2c..ca5aad81 100644 --- a/src/rars/riscv/hardware/RegisterFile.java +++ b/src/rars/riscv/hardware/RegisterFile.java @@ -5,6 +5,7 @@ import rars.assembler.SymbolTable; import rars.riscv.Instruction; +import java.util.ArrayList; import java.util.Observer; /* @@ -46,7 +47,7 @@ public class RegisterFile { public static final int GLOBAL_POINTER_REGISTER = 3; public static final int STACK_POINTER_REGISTER = 2; - private static final RegisterBlock instance = new RegisterBlock('x', new Register[]{ + public static final RegisterBlock instance = new RegisterBlock('x', new Register[]{ new Register("zero", 0, 0), new Register("ra", 1, 0), new Register("sp", STACK_POINTER_REGISTER, Memory.stackPointer), new Register("gp", GLOBAL_POINTER_REGISTER, Memory.globalPointer), @@ -65,9 +66,78 @@ public class RegisterFile { new Register("t3", 28, 0), new Register("t4", 29, 0), new Register("t5", 30, 0), new Register("t6", 31, 0) }); - + public static ArrayList gInstance; private static Register programCounter = new Register("pc", -1, Memory.textBaseAddress); + private static ArrayList gProgramCounter = new ArrayList<>(); + + public static void initProgramCounter() { + for (int i = gProgramCounter.size(); i < Globals.getHarts(); i++) { + Register temp = new Register("pc", -1, Memory.textBaseAddress); + gProgramCounter.add(temp); + } + } + + public static void initGRegisterBlock() { + if (gInstance == null) + gInstance = new ArrayList<>(); + for(int i = gInstance.size(); i < Globals.getHarts(); i++) { + RegisterBlock temp = new RegisterBlock('x', new Register[]{ + new Register("zero", 0, 0, i), new Register("ra", 1, 0, i), + new Register("sp", STACK_POINTER_REGISTER, Memory.stackPointer, i), + new Register("gp", GLOBAL_POINTER_REGISTER, Memory.globalPointer, i), + new Register("tp", 4, 0, i), new Register("t0", 5, 0, i), + new Register("t1", 6, 0, i), new Register("t2", 7, 0, i), + new Register("s0", 8, 0, i), new Register("s1", 9, 0, i), + new Register("a0", 10, 0, i), new Register("a1", 11, 0, i), + new Register("a2", 12, 0, i), new Register("a3", 13, 0, i), + new Register("a4", 14, 0, i), new Register("a5", 15, 0, i), + new Register("a6", 16, 0, i), new Register("a7", 17, 0, i), + new Register("s2", 18, 0, i), new Register("s3", 19, 0, i), + new Register("s4", 20, 0, i), new Register("s5", 21, 0, i), + new Register("s6", 22, 0, i), new Register("s7", 23, 0, i), + new Register("s8", 24, 0, i), new Register("s9", 25, 0, i), + new Register("s10", 26, 0,i), new Register("s11", 27, 0, i), + new Register("t3", 28, 0, i), new Register("t4", 29, 0, i), + new Register("t5", 30, 0, i), new Register("t6", 31, 0, i) + }); + gInstance.add(temp); + } + + } + public static void changeHarts(int sign){ + if(gInstance == null){ + initGRegisterBlock(); + } + if(sign > 0){ + int i = gInstance.size(); + RegisterBlock temp = new RegisterBlock('x', new Register[]{ + new Register("zero", 0, 0, i), new Register("ra", 1, 0, i), + new Register("sp", STACK_POINTER_REGISTER, Memory.stackPointer, i), + new Register("gp", GLOBAL_POINTER_REGISTER, Memory.globalPointer, i), + new Register("tp", 4, 0, i), new Register("t0", 5, 0, i), + new Register("t1", 6, 0, i), new Register("t2", 7, 0, i), + new Register("s0", 8, 0, i), new Register("s1", 9, 0, i), + new Register("a0", 10, 0, i), new Register("a1", 11, 0, i), + new Register("a2", 12, 0, i), new Register("a3", 13, 0, i), + new Register("a4", 14, 0, i), new Register("a5", 15, 0, i), + new Register("a6", 16, 0, i), new Register("a7", 17, 0, i), + new Register("s2", 18, 0, i), new Register("s3", 19, 0, i), + new Register("s4", 20, 0, i), new Register("s5", 21, 0, i), + new Register("s6", 22, 0, i), new Register("s7", 23, 0, i), + new Register("s8", 24, 0, i), new Register("s9", 25, 0, i), + new Register("s10", 26, 0,i), new Register("s11", 27, 0, i), + new Register("t3", 28, 0, i), new Register("t4", 29, 0, i), + new Register("t5", 30, 0, i), new Register("t6", 31, 0, i) + }); + gInstance.add(temp); + } + if(sign < 0){ + gInstance.remove(gInstance.size() -1); + gProgramCounter.remove(gProgramCounter.size()-1); + } + + } /** * This method updates the register value who's number is num. Also handles the lo and hi registers * @@ -86,7 +156,13 @@ public static void updateRegister(int num, long val) { } } } - + public static void updateRegister(int num, long val, int hart) { + if (num == 0) { + ; + } else { + gInstance.get(hart).updateRegister(num, val); + } + } /** * Sets the value of the register given to the value given. * @@ -97,7 +173,9 @@ public static void updateRegister(int num, long val) { public static void updateRegister(String name, long val) { updateRegister(instance.getRegister(name).getNumber(), val); } - + public static void updateRegister(String name, long val, int hart) { + updateRegister(gInstance.get(hart).getRegister(name).getNumber(), val, hart); + } /** * Returns the value of the register. * @@ -110,6 +188,10 @@ public static int getValue(int num) { } + public static int getValue(int num, int hart) { + return (int) gInstance.get(hart).getValue(num); + } + /** * Returns the value of the register. * @@ -121,18 +203,24 @@ public static long getValueLong(int num) { return instance.getValue(num); } + public static long getValueLong(int num, int hart) { + return gInstance.get(hart).getValue(num); + } /** * Returns the value of the register. * * @param name The register's name. * @return The value of the given register. **/ - public static int getValue(String name) { return (int) instance.getValue(name); } + public static int getValue(String name, int hart) { + return (int) gInstance.get(hart).getValue(name); + } + /** * For returning the set of registers. * @@ -142,7 +230,11 @@ public static int getValue(String name) { public static Register[] getRegisters() { return instance.getRegisters(); } - + public static Register[] getRegisters(int hart) { + if(gInstance == null) + initGRegisterBlock(); + return gInstance.get(hart).getRegisters(); + } /** * Get register object corresponding to given name. If no match, return null. * @@ -166,9 +258,14 @@ public static Register getRegister(String name) { **/ public static void initializeProgramCounter(int value) { - programCounter.setValue((long)value); + programCounter.setValue((long) value); + for (int i = 0; i < gProgramCounter.size(); i++) { + initializeProgramCounter(value, i); + } + } + public static void initializeProgramCounter(int value, int hart){ + gProgramCounter.get(hart).setValue((long) value); } - /** * Will initialize the Program Counter to either the default reset value, or the address * associated with source program global label "main", if it exists as a text segment label @@ -204,7 +301,14 @@ public static int setProgramCounter(int value) { } return old; } - + public static int setProgramCounter(int value, int hart) { + int old = (int)gProgramCounter.get(hart).getValue(); + gProgramCounter.get(hart).setValue(value); + // if (Globals.getSettings().getBackSteppingEnabled()) { + // Globals.program.getBackStepper().addPCRestore(old); + // } + return old; + } /** * For returning the program counters value. * @@ -214,7 +318,9 @@ public static int setProgramCounter(int value) { public static int getProgramCounter() { return (int)programCounter.getValue(); } - + public static int getProgramCounter(int hart){ + return (int) gProgramCounter.get(hart).getValue(); + } /** * Returns Register object for program counter. Use with caution. * @@ -223,7 +329,9 @@ public static int getProgramCounter() { public static Register getProgramCounterRegister() { return programCounter; } - + public static Register getProgramCounterRegister(int hart) { + return gProgramCounter.get(hart); + } /** * For returning the program counter's initial (reset) value. * @@ -246,6 +354,12 @@ public static int getInitialProgramCounter() { public static void resetRegisters() { instance.resetRegisters(); initializeProgramCounter(Globals.getSettings().getBooleanSetting(Settings.Bool.START_AT_MAIN));// replaces "programCounter.resetValue()", DPS 3/3/09 + if(gInstance == null) + return; + for(int i = 0; i < gInstance.size(); i++){ + gInstance.get(i).resetRegisters(); + } + } /** @@ -255,7 +369,9 @@ public static void resetRegisters() { public static void incrementPC() { programCounter.setValue(programCounter.getValue() + Instruction.INSTRUCTION_LENGTH); } - + public static void incrementPC(int hart){ + gProgramCounter.get(hart).setValue(gProgramCounter.get(hart).getValue() + Instruction.INSTRUCTION_LENGTH); + } /** * Each individual register is a separate object and Observable. This handy method * will add the given Observer to each one. Currently does not apply to Program @@ -264,7 +380,9 @@ public static void incrementPC() { public static void addRegistersObserver(Observer observer) { instance.addRegistersObserver(observer); } - + public static void addRegistersObserver(Observer observer, int hart) { + gInstance.get(hart).addRegistersObserver(observer); + } /** * Each individual register is a separate object and Observable. This handy method * will delete the given Observer from each one. Currently does not apply to Program diff --git a/src/rars/riscv/hardware/ReservationTable.java b/src/rars/riscv/hardware/ReservationTable.java new file mode 100644 index 00000000..1bee1ae8 --- /dev/null +++ b/src/rars/riscv/hardware/ReservationTable.java @@ -0,0 +1,108 @@ +package rars.riscv.hardware; + +import java.util.ArrayList; +import java.util.function.Predicate; + +/* +Copyright (c) 2021, Siva Chowdeswar Nandipati & Giancarlo Pernudi Segura. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject +to the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +(MIT license, http://www.opensource.org/licenses/mit-license.html) + */ + +public class ReservationTable { + private ArrayList table; + public final static int capacity = 8; + private final static int doubleAlignMask = ~0x7; + + public enum bitWidth { + word, + doubleWord + } + + protected class ReservationTableEntry { + protected Integer address; + protected bitWidth width; + + public ReservationTableEntry(Integer address, bitWidth width) { + this.address = address; + this.width = width; + } + + public boolean equals(Object o) { + ReservationTableEntry other = (ReservationTableEntry) o; + return address.equals(other.address) && width.equals(other.width); + } + } + + public ReservationTable() { + table = new ArrayList(); + } + + public void reserveAddress(int address, bitWidth width) { + ReservationTableEntry newEntry = new ReservationTableEntry(address, width); + if(table.contains(newEntry)) + return; + if (table.size() == capacity) + table.remove(0); + table.add(newEntry); + } + + public void unreserveAddress(int address, bitWidth width) { + Predicate filter = entry -> + (entry.address == address && entry.width == width) + || ((address & doubleAlignMask) == entry.address && entry.width == bitWidth.doubleWord); + table.removeIf(filter); + } + + public boolean contains(int address, bitWidth width) { + for (ReservationTableEntry entry : table) { + if ((entry.address == address && entry.width == width) + || ((address & doubleAlignMask) == entry.address && entry.width == bitWidth.doubleWord)) + return true; + } + return false; + } + + public Integer[] getAddresses() { + Integer[] addresses = new Integer[capacity]; + for (int i = 0; i < capacity; i++) { + try { + addresses[i] = this.table.get(i).address; + } catch (IndexOutOfBoundsException e) { + addresses[i] = 0; + } + } + return addresses; + } + + public bitWidth[] getWidths() { + bitWidth[] addresses = new bitWidth[capacity]; + for (int i = 0; i < capacity; i++) { + try { + addresses[i] = this.table.get(i).width; + } catch (IndexOutOfBoundsException e) { + addresses[i] = null; + } + } + return addresses; + } +} diff --git a/src/rars/riscv/hardware/ReservationTables.java b/src/rars/riscv/hardware/ReservationTables.java new file mode 100644 index 00000000..fe6c393b --- /dev/null +++ b/src/rars/riscv/hardware/ReservationTables.java @@ -0,0 +1,145 @@ +package rars.riscv.hardware; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Observable; +import java.util.Observer; +import java.util.Vector; + +import rars.SimulationException; +import rars.riscv.hardware.ReservationTable.bitWidth; +import rars.tools.ReservationTablesTool; + +/* +Copyright (c) 2021, Siva Chowdeswar Nandipati & Giancarlo Pernudi Segura. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject +to the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +(MIT license, http://www.opensource.org/licenses/mit-license.html) + */ + +public class ReservationTables extends Observable { + private ReservationTable[] reservationTables; + public int harts; + private Collection observables = new Vector<>(); + private static final ArrayList toolObserver = new ArrayList<>(); + + public ReservationTables(int harts) { + this.harts = harts; + reset(); + } + + public void reset() { + reservationTables = new ReservationTable[harts]; + for (int i = 0; i < reservationTables.length; i++) { + reservationTables[i] = new ReservationTable(); + } + } + + public void reserveAddress(int hart, int address, bitWidth width) throws AddressErrorException { + int modulo = width == bitWidth.doubleWord ? 8 : 4; + if (address % modulo != 0) { + throw new AddressErrorException("Reservation address not aligned to word boundary ", SimulationException.LOAD_ADDRESS_MISALIGNED, address); + } + reservationTables[hart].reserveAddress(address, width); + this.notifyTools(); + } + + public void subscribeTool(ReservationTablesTool tool) { + toolObserver.add(tool); + System.out.println(toolObserver.hashCode()); + } + + public void notifyTools() { + System.out.printf("NOTIFYING %d tools\n", toolObserver.hashCode()); + toolObserver.forEach(t -> t.update()); + } + + public boolean unreserveAddress(int hart, int address, bitWidth width) throws AddressErrorException { + int modulo = width == bitWidth.doubleWord ? 8 : 4; + if (address % modulo != 0) { + throw new AddressErrorException("Reservation address not aligned to word boundary ", SimulationException.STORE_ADDRESS_MISALIGNED, address); + } + if (reservationTables[hart].contains(address, width)) { + for (ReservationTable reservationTable : reservationTables) { + reservationTable.unreserveAddress(address, width); + } + this.notifyTools(); + return true; + } + this.notifyTools(); + return false; + } + + public String[][] getAllAddressesAsStrings() { + String[][] all = new String[ReservationTable.capacity][harts * 2]; + char width = '0'; + for (int i = 0; i < ReservationTable.capacity; i++) { + for (int j = 0; j < harts; j++) { + Integer[] addresses = reservationTables[j].getAddresses(); + ReservationTable.bitWidth[] widths = reservationTables[j].getWidths(); + if (widths[i] == ReservationTable.bitWidth.word) { + width = 'w'; + } else if (widths[i] == ReservationTable.bitWidth.doubleWord) { + width = 'd'; + } else { + width = ' '; + } + all[i][j * 2] = String.format("0x%08x", addresses[i]); + all[i][j * 2 + 1] = String.format("%c", width); + } + } + return all; + } + + public void addObserver(Observer obs) { + observables.add(new ReservationTablesObservable(obs)); + } + + /** + * Remove specified reservation tables observer + * + * @param obs Observer to be removed + */ + public void deleteObserver(Observer obs) { + for (ReservationTablesObservable o : observables) { + o.deleteObserver(obs); + } + } + + /** + * Remove all reservation tables observers + */ + public void deleteObservers() { + // just drop the collection + observables = new Vector<>(); + } + + private class ReservationTablesObservable extends Observable { + public ReservationTablesObservable(Observer obs) { + this.addObserver(obs); + } + + public void notifyObserver(MemoryAccessNotice notice) { + this.setChanged(); + this.notifyObservers(notice); + } + } +} diff --git a/src/rars/riscv/instructions/AMOADDD.java b/src/rars/riscv/instructions/AMOADDD.java new file mode 100644 index 00000000..cef47d85 --- /dev/null +++ b/src/rars/riscv/instructions/AMOADDD.java @@ -0,0 +1,39 @@ +package rars.riscv.instructions; + +/* +Copyright (c) 2021, Giancarlo Pernudi Segura + +Developed by Giancarlo Pernudi Segura at the University of Alberta (pernudi@ualberta.ca) + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject +to the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +(MIT license, http://www.opensource.org/licenses/mit-license.html) + */ + +public class AMOADDD extends AtomicMemoryOperation { + public AMOADDD() { + super("amoadd.d t0, t1, (t2)", "Loads value at t2 and places it into t0, adds value t1 and t0 (new), and saves at memory location t2.", "00000", true); + } + + @Override + protected long binaryOperation(long value1, long value2) { + return value1 + value2; + } +} diff --git a/src/rars/riscv/instructions/AMOADDW.java b/src/rars/riscv/instructions/AMOADDW.java new file mode 100644 index 00000000..8cad4e46 --- /dev/null +++ b/src/rars/riscv/instructions/AMOADDW.java @@ -0,0 +1,39 @@ +package rars.riscv.instructions; + +/* +Copyright (c) 2021, Giancarlo Pernudi Segura + +Developed by Giancarlo Pernudi Segura at the University of Alberta (pernudi@ualberta.ca) + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject +to the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +(MIT license, http://www.opensource.org/licenses/mit-license.html) + */ + +public class AMOADDW extends AtomicMemoryOperation { + public AMOADDW() { + super("amoadd.w t0, t1, (t2)", "Loads value at t2 and places it into t0, adds value t1 and t0 (new), and saves at memory location t2.", "00000"); + } + + @Override + protected long binaryOperation(long value1, long value2) { + return value1 + value2; + } +} diff --git a/src/rars/riscv/instructions/AMOANDD.java b/src/rars/riscv/instructions/AMOANDD.java new file mode 100644 index 00000000..ca9b07af --- /dev/null +++ b/src/rars/riscv/instructions/AMOANDD.java @@ -0,0 +1,39 @@ +package rars.riscv.instructions; + +/* +Copyright (c) 2021, Giancarlo Pernudi Segura + +Developed by Giancarlo Pernudi Segura at the University of Alberta (pernudi@ualberta.ca) + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject +to the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +(MIT license, http://www.opensource.org/licenses/mit-license.html) + */ + +public class AMOANDD extends AtomicMemoryOperation { + public AMOANDD() { + super("amoand.d t0, t1, (t2)", "Loads value at t2 and places it into t0, ANDS value t1 and t0 (new), and saves at memory location t2.", "01100", true); + } + + @Override + protected long binaryOperation(long value1, long value2) { + return value1 & value2; + } +} diff --git a/src/rars/riscv/instructions/AMOANDW.java b/src/rars/riscv/instructions/AMOANDW.java new file mode 100644 index 00000000..ade22070 --- /dev/null +++ b/src/rars/riscv/instructions/AMOANDW.java @@ -0,0 +1,39 @@ +package rars.riscv.instructions; + +/* +Copyright (c) 2021, Giancarlo Pernudi Segura + +Developed by Giancarlo Pernudi Segura at the University of Alberta (pernudi@ualberta.ca) + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject +to the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +(MIT license, http://www.opensource.org/licenses/mit-license.html) + */ + +public class AMOANDW extends AtomicMemoryOperation { + public AMOANDW() { + super("amoand.w t0, t1, (t2)", "Loads value at t2 and places it into t0, ANDS value t1 and t0 (new), and saves at memory location t2.", "01100"); + } + + @Override + protected long binaryOperation(long value1, long value2) { + return value1 & value2; + } +} diff --git a/src/rars/riscv/instructions/AMOMAXD.java b/src/rars/riscv/instructions/AMOMAXD.java new file mode 100644 index 00000000..7f6de467 --- /dev/null +++ b/src/rars/riscv/instructions/AMOMAXD.java @@ -0,0 +1,39 @@ +package rars.riscv.instructions; + +/* +Copyright (c) 2021, Giancarlo Pernudi Segura + +Developed by Giancarlo Pernudi Segura at the University of Alberta (pernudi@ualberta.ca) + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject +to the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +(MIT license, http://www.opensource.org/licenses/mit-license.html) + */ + +public class AMOMAXD extends AtomicMemoryOperation { + public AMOMAXD() { + super("amomax.d t0, t1, (t2)", "Loads value at t2 and places it into t0, and saves at memory location t2, the greatest value between value t1 and t0 (new).", "10100", true); + } + + @Override + protected long binaryOperation(long value1, long value2) { + return Long.max(value1, value2); + } +} diff --git a/src/rars/riscv/instructions/AMOMAXUD.java b/src/rars/riscv/instructions/AMOMAXUD.java new file mode 100644 index 00000000..eee095e9 --- /dev/null +++ b/src/rars/riscv/instructions/AMOMAXUD.java @@ -0,0 +1,39 @@ +package rars.riscv.instructions; + +/* +Copyright (c) 2021, Giancarlo Pernudi Segura + +Developed by Giancarlo Pernudi Segura at the University of Alberta (pernudi@ualberta.ca) + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject +to the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +(MIT license, http://www.opensource.org/licenses/mit-license.html) + */ + +public class AMOMAXUD extends AtomicMemoryOperation { + public AMOMAXUD() { + super("amomaxu.d t0, t1, (t2)", "Loads value at t2 and places it into t0, and saves at memory location t2, the greatest unsigned value between value t1 and t0 (new).", "11100", true); + } + + @Override + protected long binaryOperation(long value1, long value2) { + return Long.compareUnsigned(value1, value2) > 0 ? value1 : value2; + } +} diff --git a/src/rars/riscv/instructions/AMOMAXUW.java b/src/rars/riscv/instructions/AMOMAXUW.java new file mode 100644 index 00000000..e9a13139 --- /dev/null +++ b/src/rars/riscv/instructions/AMOMAXUW.java @@ -0,0 +1,39 @@ +package rars.riscv.instructions; + +/* +Copyright (c) 2021, Giancarlo Pernudi Segura + +Developed by Giancarlo Pernudi Segura at the University of Alberta (pernudi@ualberta.ca) + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject +to the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +(MIT license, http://www.opensource.org/licenses/mit-license.html) + */ + +public class AMOMAXUW extends AtomicMemoryOperation { + public AMOMAXUW() { + super("amomaxu.w t0, t1, (t2)", "Loads value at t2 and places it into t0, and saves at memory location t2, the greatest unsigned value between value t1 and t0 (new).", "11100"); + } + + @Override + protected long binaryOperation(long value1, long value2) { + return Long.compareUnsigned(value1, value2) > 0 ? value1 : value2; + } +} diff --git a/src/rars/riscv/instructions/AMOMAXW.java b/src/rars/riscv/instructions/AMOMAXW.java new file mode 100644 index 00000000..fe20615f --- /dev/null +++ b/src/rars/riscv/instructions/AMOMAXW.java @@ -0,0 +1,39 @@ +package rars.riscv.instructions; + +/* +Copyright (c) 2021, Giancarlo Pernudi Segura + +Developed by Giancarlo Pernudi Segura at the University of Alberta (pernudi@ualberta.ca) + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject +to the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +(MIT license, http://www.opensource.org/licenses/mit-license.html) + */ + +public class AMOMAXW extends AtomicMemoryOperation { + public AMOMAXW() { + super("amomax.w t0, t1, (t2)", "Loads value at t2 and places it into t0, and saves at memory location t2, the greatest value between value t1 and t0 (new).", "10100"); + } + + @Override + protected long binaryOperation(long value1, long value2) { + return Long.max(value1, value2); + } +} diff --git a/src/rars/riscv/instructions/AMOMIND.java b/src/rars/riscv/instructions/AMOMIND.java new file mode 100644 index 00000000..a339e477 --- /dev/null +++ b/src/rars/riscv/instructions/AMOMIND.java @@ -0,0 +1,39 @@ +package rars.riscv.instructions; + +/* +Copyright (c) 2021, Giancarlo Pernudi Segura + +Developed by Giancarlo Pernudi Segura at the University of Alberta (pernudi@ualberta.ca) + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject +to the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +(MIT license, http://www.opensource.org/licenses/mit-license.html) + */ + +public class AMOMIND extends AtomicMemoryOperation { + public AMOMIND() { + super("amomin.d t0, t1, (t2)", "Loads value at t2 and places it into t0, and saves at memory location t2, the lowest value between value t1 and t0 (new).", "10000", true); + } + + @Override + protected long binaryOperation(long value1, long value2) { + return Long.min(value1, value2); + } +} diff --git a/src/rars/riscv/instructions/AMOMINUD.java b/src/rars/riscv/instructions/AMOMINUD.java new file mode 100644 index 00000000..3f4e5348 --- /dev/null +++ b/src/rars/riscv/instructions/AMOMINUD.java @@ -0,0 +1,39 @@ +package rars.riscv.instructions; + +/* +Copyright (c) 2021, Giancarlo Pernudi Segura + +Developed by Giancarlo Pernudi Segura at the University of Alberta (pernudi@ualberta.ca) + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject +to the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +(MIT license, http://www.opensource.org/licenses/mit-license.html) + */ + +public class AMOMINUD extends AtomicMemoryOperation { + public AMOMINUD() { + super("amominu.d t0, t1, (t2)", "Loads value at t2 and places it into t0, and saves at memory location t2, the lowest unsigned value between value t1 and t0 (new).", "11000", true); + } + + @Override + protected long binaryOperation(long value1, long value2) { + return Long.compareUnsigned(value1, value2) < 0 ? value1 : value2; + } +} diff --git a/src/rars/riscv/instructions/AMOMINUW.java b/src/rars/riscv/instructions/AMOMINUW.java new file mode 100644 index 00000000..c9ed5836 --- /dev/null +++ b/src/rars/riscv/instructions/AMOMINUW.java @@ -0,0 +1,39 @@ +package rars.riscv.instructions; + +/* +Copyright (c) 2021, Giancarlo Pernudi Segura + +Developed by Giancarlo Pernudi Segura at the University of Alberta (pernudi@ualberta.ca) + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject +to the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +(MIT license, http://www.opensource.org/licenses/mit-license.html) + */ + +public class AMOMINUW extends AtomicMemoryOperation { + public AMOMINUW() { + super("amominu.w t0, t1, (t2)", "Loads value at t2 and places it into t0, and saves at memory location t2, the lowest unsigned value between value t1 and t0 (new).", "11000"); + } + + @Override + protected long binaryOperation(long value1, long value2) { + return Long.compareUnsigned(value1, value2) < 0 ? value1 : value2; + } +} diff --git a/src/rars/riscv/instructions/AMOMINW.java b/src/rars/riscv/instructions/AMOMINW.java new file mode 100644 index 00000000..f2f6d153 --- /dev/null +++ b/src/rars/riscv/instructions/AMOMINW.java @@ -0,0 +1,39 @@ +package rars.riscv.instructions; + +/* +Copyright (c) 2021, Giancarlo Pernudi Segura + +Developed by Giancarlo Pernudi Segura at the University of Alberta (pernudi@ualberta.ca) + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject +to the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +(MIT license, http://www.opensource.org/licenses/mit-license.html) + */ + +public class AMOMINW extends AtomicMemoryOperation { + public AMOMINW() { + super("amomin.w t0, t1, (t2)", "Loads value at t2 and places it into t0, and saves at memory location t2, the lowest value between value t1 and t0 (new).", "10000"); + } + + @Override + protected long binaryOperation(long value1, long value2) { + return Long.min(value1, value2); + } +} diff --git a/src/rars/riscv/instructions/AMOORD.java b/src/rars/riscv/instructions/AMOORD.java new file mode 100644 index 00000000..31a820ab --- /dev/null +++ b/src/rars/riscv/instructions/AMOORD.java @@ -0,0 +1,39 @@ +package rars.riscv.instructions; + +/* +Copyright (c) 2021, Giancarlo Pernudi Segura + +Developed by Giancarlo Pernudi Segura at the University of Alberta (pernudi@ualberta.ca) + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject +to the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +(MIT license, http://www.opensource.org/licenses/mit-license.html) + */ + +public class AMOORD extends AtomicMemoryOperation { + public AMOORD() { + super("amoor.d t0, t1, (t2)", "Loads value at t2 and places it into t0, ORS value t1 and t0 (new), and saves at memory location t2.", "01000", true); + } + + @Override + protected long binaryOperation(long value1, long value2) { + return value1 | value2; + } +} diff --git a/src/rars/riscv/instructions/AMOORW.java b/src/rars/riscv/instructions/AMOORW.java new file mode 100644 index 00000000..8b97511a --- /dev/null +++ b/src/rars/riscv/instructions/AMOORW.java @@ -0,0 +1,39 @@ +package rars.riscv.instructions; + +/* +Copyright (c) 2021, Giancarlo Pernudi Segura + +Developed by Giancarlo Pernudi Segura at the University of Alberta (pernudi@ualberta.ca) + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject +to the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +(MIT license, http://www.opensource.org/licenses/mit-license.html) + */ + +public class AMOORW extends AtomicMemoryOperation { + public AMOORW() { + super("amoor.w t0, t1, (t2)", "Loads value at t2 and places it into t0, ORS value t1 and t0 (new), and saves at memory location t2.", "01000"); + } + + @Override + protected long binaryOperation(long value1, long value2) { + return value1 | value2; + } +} diff --git a/src/rars/riscv/instructions/AMOSWAPD.java b/src/rars/riscv/instructions/AMOSWAPD.java new file mode 100644 index 00000000..0cdccb0b --- /dev/null +++ b/src/rars/riscv/instructions/AMOSWAPD.java @@ -0,0 +1,39 @@ +package rars.riscv.instructions; + +/* +Copyright (c) 2021, Giancarlo Pernudi Segura + +Developed by Giancarlo Pernudi Segura at the University of Alberta (pernudi@ualberta.ca) + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject +to the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +(MIT license, http://www.opensource.org/licenses/mit-license.html) + */ + +public class AMOSWAPD extends AtomicMemoryOperation { + public AMOSWAPD() { + super("amoswap.d t0, t1, (t2)", "Loads value at t2 and places it into t0, saves value t1 at memory location t2.", "00001", true); + } + + @Override + protected long binaryOperation(long value1, long value2) { + return value2; + } +} diff --git a/src/rars/riscv/instructions/AMOSWAPW.java b/src/rars/riscv/instructions/AMOSWAPW.java new file mode 100644 index 00000000..f2522a29 --- /dev/null +++ b/src/rars/riscv/instructions/AMOSWAPW.java @@ -0,0 +1,39 @@ +package rars.riscv.instructions; + +/* +Copyright (c) 2021, Giancarlo Pernudi Segura + +Developed by Giancarlo Pernudi Segura at the University of Alberta (pernudi@ualberta.ca) + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject +to the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +(MIT license, http://www.opensource.org/licenses/mit-license.html) + */ + +public class AMOSWAPW extends AtomicMemoryOperation { + public AMOSWAPW() { + super("amoswap.w t0, t1, (t2)", "Loads value at t2 and places it into t0, saves value t1 at memory location t2.", "00001"); + } + + @Override + protected long binaryOperation(long value1, long value2) { + return value2; + } +} diff --git a/src/rars/riscv/instructions/AMOXORD.java b/src/rars/riscv/instructions/AMOXORD.java new file mode 100644 index 00000000..5e558c75 --- /dev/null +++ b/src/rars/riscv/instructions/AMOXORD.java @@ -0,0 +1,39 @@ +package rars.riscv.instructions; + +/* +Copyright (c) 2021, Giancarlo Pernudi Segura + +Developed by Giancarlo Pernudi Segura at the University of Alberta (pernudi@ualberta.ca) + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject +to the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +(MIT license, http://www.opensource.org/licenses/mit-license.html) + */ + +public class AMOXORD extends AtomicMemoryOperation { + public AMOXORD() { + super("amoxor.d t0, t1, (t2)", "Loads value at t2 and places it into t0, XORS value t1 and t0 (new), and saves at memory location t2.", "00100", true); + } + + @Override + protected long binaryOperation(long value1, long value2) { + return value1 ^ value2; + } +} diff --git a/src/rars/riscv/instructions/AMOXORW.java b/src/rars/riscv/instructions/AMOXORW.java new file mode 100644 index 00000000..10dc0759 --- /dev/null +++ b/src/rars/riscv/instructions/AMOXORW.java @@ -0,0 +1,39 @@ +package rars.riscv.instructions; + +/* +Copyright (c) 2021, Giancarlo Pernudi Segura + +Developed by Giancarlo Pernudi Segura at the University of Alberta (pernudi@ualberta.ca) + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject +to the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +(MIT license, http://www.opensource.org/licenses/mit-license.html) + */ + +public class AMOXORW extends AtomicMemoryOperation { + public AMOXORW() { + super("amoxor.w t0, t1, (t2)", "Loads value at t2 and places it into t0, XORS value t1 and t0 (new), and saves at memory location t2.", "00100"); + } + + @Override + protected long binaryOperation(long value1, long value2) { + return value1 ^ value2; + } +} diff --git a/src/rars/riscv/instructions/AUIPC.java b/src/rars/riscv/instructions/AUIPC.java index cd5d6559..b8dd9a18 100644 --- a/src/rars/riscv/instructions/AUIPC.java +++ b/src/rars/riscv/instructions/AUIPC.java @@ -40,6 +40,10 @@ public AUIPC() { public void simulate(ProgramStatement statement) { int[] operands = statement.getOperands(); - RegisterFile.updateRegister(operands[0], RegisterFile.getProgramCounter() - INSTRUCTION_LENGTH + (operands[1] << 12)); + int hart = statement.getCurrentHart(); + if (hart == -1) + RegisterFile.updateRegister(operands[0], RegisterFile.getProgramCounter() - INSTRUCTION_LENGTH + (operands[1] << 12)); + else + RegisterFile.updateRegister(operands[0], RegisterFile.getProgramCounter(hart) - INSTRUCTION_LENGTH + (operands[1] << 12), hart); } } diff --git a/src/rars/riscv/instructions/Arithmetic.java b/src/rars/riscv/instructions/Arithmetic.java index 194d1570..f88e1fa5 100644 --- a/src/rars/riscv/instructions/Arithmetic.java +++ b/src/rars/riscv/instructions/Arithmetic.java @@ -53,9 +53,20 @@ public Arithmetic(String usage, String description, String funct7, String funct3 public void simulate(ProgramStatement statement) { int[] operands = statement.getOperands(); if (InstructionSet.rv64){ - RegisterFile.updateRegister(operands[0], compute(RegisterFile.getValueLong(operands[1]),RegisterFile.getValueLong(operands[2]))); - }else { - RegisterFile.updateRegister(operands[0], computeW(RegisterFile.getValue(operands[1]),RegisterFile.getValue(operands[2]))); + + if(statement.getCurrentHart() == -1) + RegisterFile.updateRegister(operands[0], compute(RegisterFile.getValueLong(operands[1]),RegisterFile.getValueLong(operands[2]))); + else{ + RegisterFile.updateRegister(operands[0], compute(RegisterFile.getValueLong(operands[1]),RegisterFile.getValueLong(operands[2])), statement.getCurrentHart()); + } + } + else { + + if(statement.getCurrentHart() == -1) + RegisterFile.updateRegister(operands[0], computeW(RegisterFile.getValue(operands[1]),RegisterFile.getValue(operands[2]))); + else{ + RegisterFile.updateRegister(operands[0], computeW(RegisterFile.getValue(operands[1]),RegisterFile.getValue(operands[2])), statement.getCurrentHart()); + } } } diff --git a/src/rars/riscv/instructions/Atomic.java b/src/rars/riscv/instructions/Atomic.java new file mode 100644 index 00000000..8cd2cf2b --- /dev/null +++ b/src/rars/riscv/instructions/Atomic.java @@ -0,0 +1,49 @@ +package rars.riscv.instructions; + +import rars.riscv.BasicInstruction; +import rars.riscv.BasicInstructionFormat; + +/* +Copyright (c) 2021, Giancarlo Pernudi Segura + +Developed by Giancarlo Pernudi Segura at the University of Alberta (pernudi@ualberta.ca) + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject +to the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +(MIT license, http://www.opensource.org/licenses/mit-license.html) + */ + +/** + * Base class for all Atomic instructions + * + * @author Giancarlo Pernudi Segura + * @version May 2017 + */ +public abstract class Atomic extends BasicInstruction { + public Atomic(String usage, String description, String funct3, String funct5) { + super(usage, description, BasicInstructionFormat.R_FORMAT, + funct5 + " 00sssss ttttt " + funct3 + " fffff 0101111"); + } + + public Atomic(String usage, String description, String funct3, String funct5, boolean rv64) { + super(usage, description, BasicInstructionFormat.R_FORMAT, + funct5 + " 00sssss ttttt " + funct3 + " fffff 0101111", rv64); + } +} diff --git a/src/rars/riscv/instructions/AtomicMemoryOperation.java b/src/rars/riscv/instructions/AtomicMemoryOperation.java new file mode 100644 index 00000000..c988183f --- /dev/null +++ b/src/rars/riscv/instructions/AtomicMemoryOperation.java @@ -0,0 +1,89 @@ +package rars.riscv.instructions; + +import rars.Globals; +import rars.ProgramStatement; +import rars.SimulationException; +import rars.riscv.InstructionSet; +import rars.riscv.hardware.AddressErrorException; +import rars.riscv.hardware.RegisterFile; +import rars.riscv.hardware.ReservationTable.bitWidth; + +/* +Copyright (c) 2021, Giancarlo Pernudi Segura + +Developed by Giancarlo Pernudi Segura at the University of Alberta (pernudi@ualberta.ca) + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject +to the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +(MIT license, http://www.opensource.org/licenses/mit-license.html) + */ + +/** + * Base class for all Atomic instructions + * + * @author Giancarlo Pernudi Segura + * @version May 2017 + */ +public abstract class AtomicMemoryOperation extends Atomic { + private bitWidth width; + + public AtomicMemoryOperation(String usage, String description, String funct5) { + super(usage, description, "010", funct5); + width = bitWidth.word; + } + + public AtomicMemoryOperation(String usage, String description, String funct5, boolean rv64) { + super(usage, description, rv64 ? "011" : "010", funct5, rv64); + width = rv64 ? bitWidth.doubleWord : bitWidth.word; + } + + public void simulate(ProgramStatement statement) throws SimulationException { + int[] operands = statement.getOperands(); + try { + int rs1Loc; + long rs2Value; + long rs1Data; + int hart = statement.getCurrentHart(); + if (hart == -1) { + rs1Loc = RegisterFile.getValue(operands[2]); + rs2Value = RegisterFile.getValueLong(operands[1]); + rs1Data = InstructionSet.rv64 ? Globals.memory.getDoubleWord(rs1Loc) : Globals.memory.getWord(rs1Loc); + RegisterFile.updateRegister(operands[0], rs1Data); + } else { + rs1Loc = RegisterFile.getValue(operands[2], hart); + rs2Value = RegisterFile.getValueLong(operands[1], hart); + rs1Data = InstructionSet.rv64 ? Globals.memory.getDoubleWord(rs1Loc) : Globals.memory.getWord(rs1Loc); + RegisterFile.updateRegister(operands[0], rs1Data, hart); + } + Globals.reservationTables.unreserveAddress(0, rs1Loc, width); + + rs1Data = binaryOperation(rs1Data, rs2Value); + if (InstructionSet.rv64) { + Globals.memory.setDoubleWord(rs1Loc, rs1Data); + } else { + Globals.memory.setWord(rs1Loc, (int) rs1Data); + } + } catch (AddressErrorException e) { + throw new SimulationException(statement, e); + } + } + + protected abstract long binaryOperation(long value1, long value2); +} diff --git a/src/rars/riscv/instructions/BEQ.java b/src/rars/riscv/instructions/BEQ.java index 250ce4b2..95a49d65 100644 --- a/src/rars/riscv/instructions/BEQ.java +++ b/src/rars/riscv/instructions/BEQ.java @@ -37,6 +37,10 @@ public BEQ() { public boolean willBranch(ProgramStatement statement) { int[] operands = statement.getOperands(); - return RegisterFile.getValueLong(operands[0]) == RegisterFile.getValueLong(operands[1]); + int hart = statement.getCurrentHart(); + if (hart == -1) + return RegisterFile.getValueLong(operands[0]) == RegisterFile.getValueLong(operands[1]); + else + return RegisterFile.getValueLong(operands[0], hart) == RegisterFile.getValueLong(operands[1], hart); } -} \ No newline at end of file +} diff --git a/src/rars/riscv/instructions/BGE.java b/src/rars/riscv/instructions/BGE.java index bb293912..d70aca75 100644 --- a/src/rars/riscv/instructions/BGE.java +++ b/src/rars/riscv/instructions/BGE.java @@ -37,6 +37,10 @@ public BGE() { public boolean willBranch(ProgramStatement statement) { int[] operands = statement.getOperands(); - return RegisterFile.getValueLong(operands[0]) >= RegisterFile.getValueLong(operands[1]); + int hart = statement.getCurrentHart(); + if (hart == -1) + return RegisterFile.getValueLong(operands[0]) >= RegisterFile.getValueLong(operands[1]); + else + return RegisterFile.getValueLong(operands[0], hart) >= RegisterFile.getValueLong(operands[1], hart); } -} \ No newline at end of file +} diff --git a/src/rars/riscv/instructions/BGEU.java b/src/rars/riscv/instructions/BGEU.java index 4afca9a2..e97205ed 100644 --- a/src/rars/riscv/instructions/BGEU.java +++ b/src/rars/riscv/instructions/BGEU.java @@ -37,6 +37,10 @@ public BGEU() { public boolean willBranch(ProgramStatement statement) { int[] operands = statement.getOperands(); - return Long.compareUnsigned(RegisterFile.getValueLong(operands[0]), RegisterFile.getValueLong(operands[1])) >= 0; + int hart = statement.getCurrentHart(); + if (hart == -1) + return Long.compareUnsigned(RegisterFile.getValueLong(operands[0]), RegisterFile.getValueLong(operands[1])) >= 0; + else + return Long.compareUnsigned(RegisterFile.getValueLong(operands[0], hart), RegisterFile.getValueLong(operands[1], hart)) >= 0; } -} \ No newline at end of file +} diff --git a/src/rars/riscv/instructions/BLT.java b/src/rars/riscv/instructions/BLT.java index df552406..f1e772d7 100644 --- a/src/rars/riscv/instructions/BLT.java +++ b/src/rars/riscv/instructions/BLT.java @@ -37,6 +37,10 @@ public BLT() { public boolean willBranch(ProgramStatement statement) { int[] operands = statement.getOperands(); - return RegisterFile.getValueLong(operands[0]) < RegisterFile.getValueLong(operands[1]); + int hart = statement.getCurrentHart(); + if (hart == -1) + return RegisterFile.getValueLong(operands[0]) < RegisterFile.getValueLong(operands[1]); + else + return RegisterFile.getValueLong(operands[0], hart) < RegisterFile.getValueLong(operands[1], hart); } -} \ No newline at end of file +} diff --git a/src/rars/riscv/instructions/BLTU.java b/src/rars/riscv/instructions/BLTU.java index f7545533..3e5952d7 100644 --- a/src/rars/riscv/instructions/BLTU.java +++ b/src/rars/riscv/instructions/BLTU.java @@ -37,6 +37,10 @@ public BLTU() { public boolean willBranch(ProgramStatement statement) { int[] operands = statement.getOperands(); - return Long.compareUnsigned(RegisterFile.getValueLong(operands[0]), RegisterFile.getValueLong(operands[1])) < 0; + int hart = statement.getCurrentHart(); + if (hart == -1) + return Long.compareUnsigned(RegisterFile.getValueLong(operands[0]), RegisterFile.getValueLong(operands[1])) < 0; + else + return Long.compareUnsigned(RegisterFile.getValueLong(operands[0], hart), RegisterFile.getValueLong(operands[1], hart)) < 0; } -} \ No newline at end of file +} diff --git a/src/rars/riscv/instructions/BNE.java b/src/rars/riscv/instructions/BNE.java index 44c56ba8..1b2d8bc4 100644 --- a/src/rars/riscv/instructions/BNE.java +++ b/src/rars/riscv/instructions/BNE.java @@ -37,6 +37,10 @@ public BNE() { public boolean willBranch(ProgramStatement statement) { int[] operands = statement.getOperands(); - return RegisterFile.getValueLong(operands[0]) != RegisterFile.getValueLong(operands[1]); + int hart = statement.getCurrentHart(); + if (hart == -1) + return RegisterFile.getValueLong(operands[0]) != RegisterFile.getValueLong(operands[1]); + else + return RegisterFile.getValueLong(operands[0], hart) != RegisterFile.getValueLong(operands[1], hart); } -} \ No newline at end of file +} diff --git a/src/rars/riscv/instructions/Branch.java b/src/rars/riscv/instructions/Branch.java index 2700e8e5..f8fb38ee 100644 --- a/src/rars/riscv/instructions/Branch.java +++ b/src/rars/riscv/instructions/Branch.java @@ -48,7 +48,12 @@ public Branch(String usage, String description, String funct) { public void simulate(ProgramStatement statement) { if (willBranch(statement)) { - InstructionSet.processBranch(statement.getOperands()[2]); + int hart = statement.getCurrentHart(); + if (hart == -1) { + InstructionSet.processBranch(statement.getOperands()[2]); + } else { + InstructionSet.processBranch(statement.getOperands()[2], hart); + } } } @@ -57,4 +62,4 @@ public void simulate(ProgramStatement statement) { * @return true if the Branch instruction will branch */ public abstract boolean willBranch(ProgramStatement statement); -} \ No newline at end of file +} diff --git a/src/rars/riscv/instructions/CSRRC.java b/src/rars/riscv/instructions/CSRRC.java index ceea2863..b45e250f 100644 --- a/src/rars/riscv/instructions/CSRRC.java +++ b/src/rars/riscv/instructions/CSRRC.java @@ -41,14 +41,29 @@ public CSRRC() { public void simulate(ProgramStatement statement) throws SimulationException { int[] operands = statement.getOperands(); + int hart = statement.getCurrentHart(); try { - long csr = ControlAndStatusRegisterFile.getValueLong(operands[1]); - if (operands[2] != 0) { - if(ControlAndStatusRegisterFile.clearRegister(operands[1], RegisterFile.getValueLong(operands[2]))){ - throw new SimulationException(statement, "Attempt to write to read-only CSR", SimulationException.ILLEGAL_INSTRUCTION); + if (hart == -1) { + long csr = ControlAndStatusRegisterFile.getValueLong(operands[1]); + if (operands[2] != 0) { + if (ControlAndStatusRegisterFile.clearRegister(operands[1], + RegisterFile.getValueLong(operands[2]))) { + throw new SimulationException(statement, "Attempt to write to read-only CSR", + SimulationException.ILLEGAL_INSTRUCTION); + } } + RegisterFile.updateRegister(operands[0], csr); + } else { + long csr = ControlAndStatusRegisterFile.getValueLong(operands[1], hart); + if (operands[2] != 0) { + if (ControlAndStatusRegisterFile.clearRegister(operands[1], + RegisterFile.getValueLong(operands[2], hart), hart)) { + throw new SimulationException(statement, "Attempt to write to read-only CSR", + SimulationException.ILLEGAL_INSTRUCTION); + } + } + RegisterFile.updateRegister(operands[0], csr, hart); } - RegisterFile.updateRegister(operands[0], csr); } catch (NullPointerException e) { throw new SimulationException(statement, "Attempt to access unavailable CSR", SimulationException.ILLEGAL_INSTRUCTION); } diff --git a/src/rars/riscv/instructions/CSRRCI.java b/src/rars/riscv/instructions/CSRRCI.java index 13a97d38..b48d7fdf 100644 --- a/src/rars/riscv/instructions/CSRRCI.java +++ b/src/rars/riscv/instructions/CSRRCI.java @@ -41,14 +41,27 @@ public CSRRCI() { public void simulate(ProgramStatement statement) throws SimulationException { int[] operands = statement.getOperands(); + int hart = statement.getCurrentHart(); try { - long csr = ControlAndStatusRegisterFile.getValueLong(operands[1]); - if (operands[2] != 0) { - if(ControlAndStatusRegisterFile.clearRegister(operands[1], operands[2])){ - throw new SimulationException(statement, "Attempt to write to read-only CSR", SimulationException.ILLEGAL_INSTRUCTION); + if (hart == -1) { + long csr = ControlAndStatusRegisterFile.getValueLong(operands[1]); + if (operands[2] != 0) { + if (ControlAndStatusRegisterFile.clearRegister(operands[1], operands[2])) { + throw new SimulationException(statement, "Attempt to write to read-only CSR", + SimulationException.ILLEGAL_INSTRUCTION); + } } + RegisterFile.updateRegister(operands[0], csr); + } else { + long csr = ControlAndStatusRegisterFile.getValueLong(operands[1], hart); + if (operands[2] != 0) { + if (ControlAndStatusRegisterFile.clearRegister(operands[1], operands[2], hart)) { + throw new SimulationException(statement, "Attempt to write to read-only CSR", + SimulationException.ILLEGAL_INSTRUCTION); + } + } + RegisterFile.updateRegister(operands[0], csr, hart); } - RegisterFile.updateRegister(operands[0], csr); } catch (NullPointerException e) { throw new SimulationException(statement, "Attempt to access unavailable CSR", SimulationException.ILLEGAL_INSTRUCTION); } diff --git a/src/rars/riscv/instructions/CSRRS.java b/src/rars/riscv/instructions/CSRRS.java index 80a4c8ff..fb689ff4 100644 --- a/src/rars/riscv/instructions/CSRRS.java +++ b/src/rars/riscv/instructions/CSRRS.java @@ -41,14 +41,27 @@ public CSRRS() { public void simulate(ProgramStatement statement) throws SimulationException { int[] operands = statement.getOperands(); + int hart = statement.getCurrentHart(); try { - long csr = ControlAndStatusRegisterFile.getValueLong(operands[1]); - if (operands[2] != 0) { - if(ControlAndStatusRegisterFile.orRegister(operands[1], RegisterFile.getValueLong(operands[2]))) { - throw new SimulationException(statement, "Attempt to write to read-only CSR", SimulationException.ILLEGAL_INSTRUCTION); + if (hart == -1) { + long csr = ControlAndStatusRegisterFile.getValueLong(operands[1]); + if (operands[2] != 0) { + if (ControlAndStatusRegisterFile.orRegister(operands[1], RegisterFile.getValueLong(operands[2]))) { + throw new SimulationException(statement, "Attempt to write to read-only CSR", + SimulationException.ILLEGAL_INSTRUCTION); + } } + RegisterFile.updateRegister(operands[0], csr); + } else { + long csr = ControlAndStatusRegisterFile.getValueLong(operands[1], hart); + if (operands[2] != 0) { + if (ControlAndStatusRegisterFile.orRegister(operands[1], RegisterFile.getValueLong(operands[2], hart), hart)) { + throw new SimulationException(statement, "Attempt to write to read-only CSR", + SimulationException.ILLEGAL_INSTRUCTION); + } + } + RegisterFile.updateRegister(operands[0], csr, hart); } - RegisterFile.updateRegister(operands[0], csr); } catch (NullPointerException e) { throw new SimulationException(statement, "Attempt to access unavailable CSR", SimulationException.ILLEGAL_INSTRUCTION); } diff --git a/src/rars/riscv/instructions/CSRRSI.java b/src/rars/riscv/instructions/CSRRSI.java index b0e5e9f9..2e4d48a8 100644 --- a/src/rars/riscv/instructions/CSRRSI.java +++ b/src/rars/riscv/instructions/CSRRSI.java @@ -41,14 +41,26 @@ public CSRRSI() { public void simulate(ProgramStatement statement) throws SimulationException { int[] operands = statement.getOperands(); + int hart = statement.getCurrentHart(); try { - long csr = ControlAndStatusRegisterFile.getValueLong(operands[1]); - if (operands[2] != 0){ - if(ControlAndStatusRegisterFile.orRegister(operands[1], operands[2])){ - throw new SimulationException(statement, "Attempt to write to read-only CSR", SimulationException.ILLEGAL_INSTRUCTION); + if (hart == -1) { + long csr = ControlAndStatusRegisterFile.getValueLong(operands[1]); + if (operands[2] != 0){ + if(ControlAndStatusRegisterFile.orRegister(operands[1], operands[2])){ + throw new SimulationException(statement, "Attempt to write to read-only CSR", SimulationException.ILLEGAL_INSTRUCTION); + } } + RegisterFile.updateRegister(operands[0], csr); + } else { + long csr = ControlAndStatusRegisterFile.getValueLong(operands[1], hart); + if (operands[2] != 0) { + if (ControlAndStatusRegisterFile.orRegister(operands[1], operands[2], hart)) { + throw new SimulationException(statement, "Attempt to write to read-only CSR", + SimulationException.ILLEGAL_INSTRUCTION); + } + } + RegisterFile.updateRegister(operands[0], csr, hart); } - RegisterFile.updateRegister(operands[0], csr); } catch (NullPointerException e) { throw new SimulationException(statement, "Attempt to access unavailable CSR", SimulationException.ILLEGAL_INSTRUCTION); } diff --git a/src/rars/riscv/instructions/CSRRW.java b/src/rars/riscv/instructions/CSRRW.java index 7cb44d46..5293d616 100644 --- a/src/rars/riscv/instructions/CSRRW.java +++ b/src/rars/riscv/instructions/CSRRW.java @@ -41,12 +41,23 @@ public CSRRW() { public void simulate(ProgramStatement statement) throws SimulationException { int[] operands = statement.getOperands(); + int hart = statement.getCurrentHart(); try { - long csr = ControlAndStatusRegisterFile.getValueLong(operands[1]); - if(ControlAndStatusRegisterFile.updateRegister(operands[1], RegisterFile.getValueLong(operands[2]))){ - throw new SimulationException(statement, "Attempt to write to read-only CSR", SimulationException.ILLEGAL_INSTRUCTION); + if (hart == -1) { + long csr = ControlAndStatusRegisterFile.getValueLong(operands[1]); + if (ControlAndStatusRegisterFile.updateRegister(operands[1], RegisterFile.getValueLong(operands[2]))) { + throw new SimulationException(statement, "Attempt to write to read-only CSR", + SimulationException.ILLEGAL_INSTRUCTION); + } + RegisterFile.updateRegister(operands[0], csr); + } else { + long csr = ControlAndStatusRegisterFile.getValueLong(operands[1], hart); + if (ControlAndStatusRegisterFile.updateRegister(operands[1], RegisterFile.getValueLong(operands[2], hart), hart)) { + throw new SimulationException(statement, "Attempt to write to read-only CSR", + SimulationException.ILLEGAL_INSTRUCTION); + } + RegisterFile.updateRegister(operands[0], csr, hart); } - RegisterFile.updateRegister(operands[0], csr); } catch (NullPointerException e) { throw new SimulationException(statement, "Attempt to access unavailable CSR", SimulationException.ILLEGAL_INSTRUCTION); } diff --git a/src/rars/riscv/instructions/CSRRWI.java b/src/rars/riscv/instructions/CSRRWI.java index 40efe473..cab428e7 100644 --- a/src/rars/riscv/instructions/CSRRWI.java +++ b/src/rars/riscv/instructions/CSRRWI.java @@ -41,12 +41,23 @@ public CSRRWI() { public void simulate(ProgramStatement statement) throws SimulationException { int[] operands = statement.getOperands(); + int hart = statement.getCurrentHart(); try { - long csr = ControlAndStatusRegisterFile.getValueLong(operands[1]); - if(ControlAndStatusRegisterFile.updateRegister(operands[1], operands[2])){ - throw new SimulationException(statement, "Attempt to write to read-only CSR", SimulationException.ILLEGAL_INSTRUCTION); + if (hart == -1) { + long csr = ControlAndStatusRegisterFile.getValueLong(operands[1]); + if (ControlAndStatusRegisterFile.updateRegister(operands[1], operands[2])) { + throw new SimulationException(statement, "Attempt to write to read-only CSR", + SimulationException.ILLEGAL_INSTRUCTION); + } + RegisterFile.updateRegister(operands[0], csr); + } else { + long csr = ControlAndStatusRegisterFile.getValueLong(operands[1], hart); + if (ControlAndStatusRegisterFile.updateRegister(operands[1], operands[2], hart)) { + throw new SimulationException(statement, "Attempt to write to read-only CSR", + SimulationException.ILLEGAL_INSTRUCTION); + } + RegisterFile.updateRegister(operands[0], csr, hart); } - RegisterFile.updateRegister(operands[0], csr); } catch (NullPointerException e) { throw new SimulationException(statement, "Attempt to access unavailable CSR", SimulationException.ILLEGAL_INSTRUCTION); } diff --git a/src/rars/riscv/instructions/DIV.java b/src/rars/riscv/instructions/DIV.java index 5553d929..dab9ec1f 100644 --- a/src/rars/riscv/instructions/DIV.java +++ b/src/rars/riscv/instructions/DIV.java @@ -1,7 +1,5 @@ package rars.riscv.instructions; -import rars.riscv.hardware.ControlAndStatusRegisterFile; - /* Copyright (c) 2017, Benjamin Landers diff --git a/src/rars/riscv/instructions/DIVU.java b/src/rars/riscv/instructions/DIVU.java index 27001a04..57400fae 100644 --- a/src/rars/riscv/instructions/DIVU.java +++ b/src/rars/riscv/instructions/DIVU.java @@ -1,7 +1,5 @@ package rars.riscv.instructions; -import rars.riscv.hardware.ControlAndStatusRegisterFile; - /* Copyright (c) 2017, Benjamin Landers @@ -45,4 +43,4 @@ public long compute(long value, long value2) { public int computeW(int value, int value2) { return (int)compute(value & 0xFFFFFFFFL, value2 & 0xFFFFFFFFL); } -} \ No newline at end of file +} diff --git a/src/rars/riscv/instructions/DIVUW.java b/src/rars/riscv/instructions/DIVUW.java index 1c355c5a..0a1579a6 100644 --- a/src/rars/riscv/instructions/DIVUW.java +++ b/src/rars/riscv/instructions/DIVUW.java @@ -5,5 +5,4 @@ public DIVUW() { super("divuw t1,t2,t3", "Division: set t1 to the result of t2/t3 using unsigned division limited to 32 bits", "0000001", "101",new DIVU()); } - -} \ No newline at end of file +} diff --git a/src/rars/riscv/instructions/Double.java b/src/rars/riscv/instructions/Double.java index 0edc8011..7d214f3d 100644 --- a/src/rars/riscv/instructions/Double.java +++ b/src/rars/riscv/instructions/Double.java @@ -16,18 +16,34 @@ protected Double(String name, String description, String funct) { protected Double(String name, String description, String funct, String rm) { super(name + " f1, f2, f3", description, BasicInstructionFormat.R_FORMAT, funct + "ttttt sssss " + rm + " fffff 1010011"); } - public void simulate(ProgramStatement statement) throws SimulationException{ + public void simulate(ProgramStatement statement) throws SimulationException { int[] operands = statement.getOperands(); + int hart = statement.getCurrentHart(); Environment e = new Environment(); e.mode = Floating.getRoundingMode(operands[3],statement); - Float64 result = compute(new Float64(FloatingPointRegisterFile.getValueLong(operands[1])),new Float64(FloatingPointRegisterFile.getValueLong(operands[2])),e); - Floating.setfflags(e); - FloatingPointRegisterFile.updateRegisterLong(operands[0], result.bits); + Float64 result = compute( + new Float64((hart == -1) + ? FloatingPointRegisterFile.getValueLong(operands[1]) + : FloatingPointRegisterFile.getValueLong(operands[1], hart) + ), + new Float64((hart == -1) + ? FloatingPointRegisterFile.getValueLong(operands[2]) + : FloatingPointRegisterFile.getValueLong(operands[2], hart)), + e); + Floating.setfflags(e, hart); + if (hart == -1) + FloatingPointRegisterFile.updateRegisterLong(operands[0], result.bits); + else + FloatingPointRegisterFile.updateRegisterLong(operands[0], result.bits, hart); } public abstract Float64 compute(Float64 f1, Float64 f2, Environment e); - public static Float64 getDouble(int num){ + public static Float64 getDouble(int num) { return new Float64(FloatingPointRegisterFile.getValueLong(num)); } -} \ No newline at end of file + + public static Float64 getDouble(int num, int hart) { + return new Float64(FloatingPointRegisterFile.getValueLong(num, hart)); + } +} diff --git a/src/rars/riscv/instructions/ECALL.java b/src/rars/riscv/instructions/ECALL.java index 48e66c7d..c339d254 100644 --- a/src/rars/riscv/instructions/ECALL.java +++ b/src/rars/riscv/instructions/ECALL.java @@ -41,6 +41,10 @@ public ECALL() { } public void simulate(ProgramStatement statement) throws SimulationException { - InstructionSet.findAndSimulateSyscall(RegisterFile.getValue("a7"), statement); + int hart = statement.getCurrentHart(); + if (hart == -1) + InstructionSet.findAndSimulateSyscall(RegisterFile.getValue("a7"), statement); + else + InstructionSet.findAndSimulateSyscall(RegisterFile.getValue("a7", hart), statement); } -} \ No newline at end of file +} diff --git a/src/rars/riscv/instructions/FCLASSD.java b/src/rars/riscv/instructions/FCLASSD.java index ef1ea9c0..ac9f46bf 100644 --- a/src/rars/riscv/instructions/FCLASSD.java +++ b/src/rars/riscv/instructions/FCLASSD.java @@ -14,7 +14,13 @@ public FCLASSD() { public void simulate(ProgramStatement statement) { int[] operands = statement.getOperands(); - Float64 in = new Float64(FloatingPointRegisterFile.getValueLong(operands[1])); - FCLASSS.fclass(in,operands[0]); + int hart = statement.getCurrentHart(); + Float64 in = (hart == -1) + ? new Float64(FloatingPointRegisterFile.getValueLong(operands[1])) + : new Float64(FloatingPointRegisterFile.getValueLong(operands[1], hart)); + if (hart == -1) + FCLASSS.fclass(in, operands[0]); + else + FCLASSS.fclass(in, operands[0], hart); } -} \ No newline at end of file +} diff --git a/src/rars/riscv/instructions/FCLASSS.java b/src/rars/riscv/instructions/FCLASSS.java index ad613829..242adf57 100644 --- a/src/rars/riscv/instructions/FCLASSS.java +++ b/src/rars/riscv/instructions/FCLASSS.java @@ -54,8 +54,14 @@ public FCLASSS() { */ public void simulate(ProgramStatement statement) { int[] operands = statement.getOperands(); - Float32 in = new Float32(FloatingPointRegisterFile.getValue(operands[1])); - fclass(in,operands[0]); + int hart = statement.getCurrentHart(); + Float32 in = (hart == -1) + ? new Float32(FloatingPointRegisterFile.getValue(operands[1])) + : new Float32(FloatingPointRegisterFile.getValue(operands[1], hart)); + if (hart == -1) + fclass(in, operands[0]); + else + fclass(in, operands[0], hart); } public static > void fclass(T in, int out){ @@ -74,4 +80,21 @@ public static > void fclass(T in, int out } } } -} \ No newline at end of file + + public static > void fclass(T in, int out, int hart) { + if (in.isNaN()) { + RegisterFile.updateRegister(out, in.isSignalling() ? 0x100 : 0x200, hart); + } else { + boolean negative = in.isSignMinus(); + if (in.isInfinite()) { + RegisterFile.updateRegister(out, negative ? 0x001 : 0x080, hart); + } else if (in.isZero()) { + RegisterFile.updateRegister(out, negative ? 0x008 : 0x010, hart); + } else if (in.isSubnormal()) { + RegisterFile.updateRegister(out, negative ? 0x004 : 0x020, hart); + } else { + RegisterFile.updateRegister(out, negative ? 0x002 : 0x040, hart); + } + } + } +} diff --git a/src/rars/riscv/instructions/FCVTDL.java b/src/rars/riscv/instructions/FCVTDL.java index e004b451..06fbc47a 100644 --- a/src/rars/riscv/instructions/FCVTDL.java +++ b/src/rars/riscv/instructions/FCVTDL.java @@ -1,6 +1,7 @@ package rars.riscv.instructions; import jsoftfloat.Environment; +import jsoftfloat.operations.Conversions; import jsoftfloat.types.Float64; import rars.ProgramStatement; import rars.SimulationException; @@ -19,12 +20,20 @@ public FCVTDL() { public void simulate(ProgramStatement statement) throws SimulationException { int[] operands = statement.getOperands(); + int hart = statement.getCurrentHart(); Environment e = new Environment(); e.mode = Floating.getRoundingMode(operands[2],statement); Float64 tmp = new Float64(0); - Float64 converted = jsoftfloat.operations.Conversions.convertFromInt(BigInteger.valueOf(RegisterFile.getValueLong(operands[1])),e,tmp); - Floating.setfflags(e); - FloatingPointRegisterFile.updateRegisterLong(operands[0],converted.bits); + Float64 converted = Conversions + .convertFromInt(BigInteger.valueOf( + (hart == -1) + ? RegisterFile.getValueLong(operands[1]) + : RegisterFile.getValueLong(operands[1], hart)), + e, tmp); + Floating.setfflags(e, hart); + if (hart == -1) + FloatingPointRegisterFile.updateRegisterLong(operands[0], converted.bits); + else + FloatingPointRegisterFile.updateRegisterLong(operands[0], converted.bits, hart); } } - diff --git a/src/rars/riscv/instructions/FCVTDLU.java b/src/rars/riscv/instructions/FCVTDLU.java index c73e52fa..25c81f01 100644 --- a/src/rars/riscv/instructions/FCVTDLU.java +++ b/src/rars/riscv/instructions/FCVTDLU.java @@ -1,6 +1,7 @@ package rars.riscv.instructions; import jsoftfloat.Environment; +import jsoftfloat.operations.Conversions; import jsoftfloat.types.Float64; import rars.ProgramStatement; import rars.SimulationException; @@ -19,17 +20,22 @@ public FCVTDLU() { public void simulate(ProgramStatement statement) throws SimulationException { int[] operands = statement.getOperands(); + int hart = statement.getCurrentHart(); Environment e = new Environment(); e.mode = Floating.getRoundingMode(operands[2],statement); Float64 tmp = new Float64(0); - long value = RegisterFile.getValueLong(operands[1]); + long value = (hart == -1) + ? RegisterFile.getValueLong(operands[1]) + : RegisterFile.getValueLong(operands[1], hart); BigInteger unsigned = BigInteger.valueOf(value); if (value < 0) { unsigned = unsigned.add(BigInteger.ONE.shiftLeft(64)); } - Float64 converted = jsoftfloat.operations.Conversions.convertFromInt(unsigned,e,tmp); - Floating.setfflags(e); - FloatingPointRegisterFile.updateRegisterLong(operands[0],converted.bits); + Float64 converted = Conversions.convertFromInt(unsigned,e,tmp); + Floating.setfflags(e, hart); + if (hart == -1) + FloatingPointRegisterFile.updateRegisterLong(operands[0], converted.bits); + else + FloatingPointRegisterFile.updateRegisterLong(operands[0], converted.bits, hart); } } - diff --git a/src/rars/riscv/instructions/FCVTDS.java b/src/rars/riscv/instructions/FCVTDS.java index 25c6189d..6b0c73d0 100644 --- a/src/rars/riscv/instructions/FCVTDS.java +++ b/src/rars/riscv/instructions/FCVTDS.java @@ -17,12 +17,18 @@ public FCVTDS() { public void simulate(ProgramStatement statement) throws SimulationException { int[] operands = statement.getOperands(); + int hart = statement.getCurrentHart(); Environment e = new Environment(); e.mode = Floating.getRoundingMode(operands[2],statement); - Float32 in = new Float32(FloatingPointRegisterFile.getValue(operands[1])); + Float32 in = new Float32((hart == -1) + ? FloatingPointRegisterFile.getValue(operands[1]) + : FloatingPointRegisterFile.getValue(operands[1])); Float64 out = new Float64(0); out = FCVTSD.convert(in,out,e); - Floating.setfflags(e); - FloatingPointRegisterFile.updateRegisterLong(operands[0],out.bits); + Floating.setfflags(e, hart); + if (hart == -1) + FloatingPointRegisterFile.updateRegisterLong(operands[0], out.bits); + else + FloatingPointRegisterFile.updateRegisterLong(operands[0], out.bits, hart); } -} \ No newline at end of file +} diff --git a/src/rars/riscv/instructions/FCVTDW.java b/src/rars/riscv/instructions/FCVTDW.java index 57e4f779..c239f9a7 100644 --- a/src/rars/riscv/instructions/FCVTDW.java +++ b/src/rars/riscv/instructions/FCVTDW.java @@ -1,6 +1,7 @@ package rars.riscv.instructions; import jsoftfloat.Environment; +import jsoftfloat.operations.Conversions; import jsoftfloat.types.Float64; import rars.ProgramStatement; import rars.SimulationException; @@ -19,12 +20,15 @@ public FCVTDW() { public void simulate(ProgramStatement statement) throws SimulationException { int[] operands = statement.getOperands(); + int hart = statement.getCurrentHart(); Environment e = new Environment(); e.mode = Floating.getRoundingMode(operands[2],statement); Float64 tmp = new Float64(0); - Float64 converted = jsoftfloat.operations.Conversions.convertFromInt(BigInteger.valueOf(RegisterFile.getValue(operands[1])),e,tmp); - Floating.setfflags(e); - FloatingPointRegisterFile.updateRegisterLong(operands[0],converted.bits); + Float64 converted = Conversions.convertFromInt(BigInteger.valueOf(RegisterFile.getValue(operands[1])),e,tmp); + Floating.setfflags(e, hart); + if (hart == -1) + FloatingPointRegisterFile.updateRegisterLong(operands[0], converted.bits); + else + FloatingPointRegisterFile.updateRegisterLong(operands[0], converted.bits, hart); } } - diff --git a/src/rars/riscv/instructions/FCVTDWU.java b/src/rars/riscv/instructions/FCVTDWU.java index 0644c2fc..d308d97b 100644 --- a/src/rars/riscv/instructions/FCVTDWU.java +++ b/src/rars/riscv/instructions/FCVTDWU.java @@ -1,6 +1,7 @@ package rars.riscv.instructions; import jsoftfloat.Environment; +import jsoftfloat.operations.Conversions; import jsoftfloat.types.Float64; import rars.ProgramStatement; import rars.SimulationException; @@ -19,12 +20,19 @@ public FCVTDWU() { public void simulate(ProgramStatement statement) throws SimulationException { int[] operands = statement.getOperands(); + int hart = statement.getCurrentHart(); Environment e = new Environment(); e.mode = Floating.getRoundingMode(operands[2],statement); Float64 tmp = new Float64(0); - Float64 converted = jsoftfloat.operations.Conversions.convertFromInt(BigInteger.valueOf(RegisterFile.getValue(operands[1]) & 0xFFFFFFFFL),e,tmp); - Floating.setfflags(e); - FloatingPointRegisterFile.updateRegisterLong(operands[0],converted.bits); + Float64 converted = Conversions + .convertFromInt(BigInteger.valueOf(((hart == -1) + ? RegisterFile.getValue(operands[1]) + : RegisterFile.getValue(operands[1])) + & 0xFFFFFFFFL), e, tmp); + Floating.setfflags(e, hart); + if (hart == -1) + FloatingPointRegisterFile.updateRegisterLong(operands[0], converted.bits); + else + FloatingPointRegisterFile.updateRegisterLong(operands[0], converted.bits, hart); } } - diff --git a/src/rars/riscv/instructions/FCVTLD.java b/src/rars/riscv/instructions/FCVTLD.java index 9648376a..af43608b 100644 --- a/src/rars/riscv/instructions/FCVTLD.java +++ b/src/rars/riscv/instructions/FCVTLD.java @@ -1,6 +1,7 @@ package rars.riscv.instructions; import jsoftfloat.Environment; +import jsoftfloat.operations.Conversions; import jsoftfloat.types.Float64; import rars.ProgramStatement; import rars.SimulationException; @@ -17,11 +18,17 @@ public FCVTLD() { public void simulate(ProgramStatement statement) throws SimulationException { int[] operands = statement.getOperands(); + int hart = statement.getCurrentHart(); Environment e = new Environment(); e.mode = Floating.getRoundingMode(operands[2],statement); - Float64 in = new Float64(FloatingPointRegisterFile.getValueLong(operands[1])); - long out = jsoftfloat.operations.Conversions.convertToLong(in,e,false); - Floating.setfflags(e); - RegisterFile.updateRegister(operands[0],out); + Float64 in = new Float64((hart == -1) + ? FloatingPointRegisterFile.getValueLong(operands[1]) + : FloatingPointRegisterFile.getValueLong(operands[1], hart)); + long out = Conversions.convertToLong(in,e,false); + Floating.setfflags(e, hart); + if (hart == -1) + RegisterFile.updateRegister(operands[0], out); + else + RegisterFile.updateRegister(operands[0], out, hart); } -} \ No newline at end of file +} diff --git a/src/rars/riscv/instructions/FCVTLS.java b/src/rars/riscv/instructions/FCVTLS.java index 4e8869fc..cc4d7e64 100644 --- a/src/rars/riscv/instructions/FCVTLS.java +++ b/src/rars/riscv/instructions/FCVTLS.java @@ -17,11 +17,17 @@ public FCVTLS() { public void simulate(ProgramStatement statement) throws SimulationException { int[] operands = statement.getOperands(); + int hart = statement.getCurrentHart(); Environment e = new Environment(); e.mode = Floating.getRoundingMode(operands[2],statement); - Float32 in = new Float32(FloatingPointRegisterFile.getValue(operands[1])); + Float32 in = new Float32((hart == -1) + ? FloatingPointRegisterFile.getValue(operands[1]) + : FloatingPointRegisterFile.getValue(operands[1], hart)); long out = jsoftfloat.operations.Conversions.convertToLong(in,e,false); - Floating.setfflags(e); - RegisterFile.updateRegister(operands[0],out); + Floating.setfflags(e, hart); + if (hart == -1) + RegisterFile.updateRegister(operands[0], out); + else + RegisterFile.updateRegister(operands[1], out, hart); } -} \ No newline at end of file +} diff --git a/src/rars/riscv/instructions/FCVTLUD.java b/src/rars/riscv/instructions/FCVTLUD.java index f8834248..96a7bb90 100644 --- a/src/rars/riscv/instructions/FCVTLUD.java +++ b/src/rars/riscv/instructions/FCVTLUD.java @@ -1,6 +1,7 @@ package rars.riscv.instructions; import jsoftfloat.Environment; +import jsoftfloat.operations.Conversions; import jsoftfloat.types.Float64; import rars.ProgramStatement; import rars.SimulationException; @@ -17,11 +18,17 @@ public FCVTLUD() { public void simulate(ProgramStatement statement) throws SimulationException { int[] operands = statement.getOperands(); + int hart = statement.getCurrentHart(); Environment e = new Environment(); e.mode = Floating.getRoundingMode(operands[2],statement); - Float64 in = new Float64(FloatingPointRegisterFile.getValueLong(operands[1])); - long out = jsoftfloat.operations.Conversions.convertToUnsignedLong(in,e,false); - Floating.setfflags(e); - RegisterFile.updateRegister(operands[0],out); + Float64 in = new Float64((hart == -1) + ? FloatingPointRegisterFile.getValueLong(operands[1]) + : FloatingPointRegisterFile.getValueLong(operands[1], hart)); + long out = Conversions.convertToUnsignedLong(in,e,false); + Floating.setfflags(e, hart); + if (hart == -1) + RegisterFile.updateRegister(operands[0], out); + else + RegisterFile.updateRegister(operands[0], out, hart); } -} \ No newline at end of file +} diff --git a/src/rars/riscv/instructions/FCVTLUS.java b/src/rars/riscv/instructions/FCVTLUS.java index 1f38cb05..9ad96d09 100644 --- a/src/rars/riscv/instructions/FCVTLUS.java +++ b/src/rars/riscv/instructions/FCVTLUS.java @@ -17,11 +17,17 @@ public FCVTLUS() { public void simulate(ProgramStatement statement) throws SimulationException { int[] operands = statement.getOperands(); + int hart = statement.getCurrentHart(); Environment e = new Environment(); e.mode = Floating.getRoundingMode(operands[2],statement); - Float32 in = new Float32(FloatingPointRegisterFile.getValue(operands[1])); + Float32 in = new Float32((hart == -1) + ? FloatingPointRegisterFile.getValue(operands[1]) + : FloatingPointRegisterFile.getValue(operands[1], hart)); long out = jsoftfloat.operations.Conversions.convertToUnsignedLong(in,e,false); - Floating.setfflags(e); - RegisterFile.updateRegister(operands[0],out); + Floating.setfflags(e, hart); + if (hart == -1) + RegisterFile.updateRegister(operands[0], out); + else + RegisterFile.updateRegister(operands[0], out, hart); } -} \ No newline at end of file +} diff --git a/src/rars/riscv/instructions/FCVTSD.java b/src/rars/riscv/instructions/FCVTSD.java index 1c073569..266fa131 100644 --- a/src/rars/riscv/instructions/FCVTSD.java +++ b/src/rars/riscv/instructions/FCVTSD.java @@ -17,13 +17,19 @@ public FCVTSD() { public void simulate(ProgramStatement statement) throws SimulationException { int[] operands = statement.getOperands(); + int hart = statement.getCurrentHart(); Environment e = new Environment(); e.mode = Floating.getRoundingMode(operands[2],statement); - Float64 in = new Float64(FloatingPointRegisterFile.getValueLong(operands[1])); + Float64 in = (hart == -1) + ? new Float64(FloatingPointRegisterFile.getValueLong(operands[1])) + : new Float64(FloatingPointRegisterFile.getValueLong(operands[1], hart)); Float32 out = new Float32(0); out = convert(in,out,e); - Floating.setfflags(e); - FloatingPointRegisterFile.updateRegister(operands[0],out.bits); + Floating.setfflags(e, hart); + if (hart == -1) + FloatingPointRegisterFile.updateRegister(operands[0], out.bits); + else + FloatingPointRegisterFile.updateRegister(operands[0], out.bits, hart); } // Kindof a long type, but removes duplicate code and would make it easy for quads to be implemented. public static ,D extends jsoftfloat.types.Floating> @@ -39,4 +45,4 @@ S convert(D toconvert, S constructor, Environment e){ } return constructor.fromExactFloat(toconvert.toExactFloat(),e); } -} \ No newline at end of file +} diff --git a/src/rars/riscv/instructions/FCVTSL.java b/src/rars/riscv/instructions/FCVTSL.java index eeca22a9..fb97f019 100644 --- a/src/rars/riscv/instructions/FCVTSL.java +++ b/src/rars/riscv/instructions/FCVTSL.java @@ -1,6 +1,7 @@ package rars.riscv.instructions; import jsoftfloat.Environment; +import jsoftfloat.operations.Conversions; import jsoftfloat.types.Float32; import rars.ProgramStatement; import rars.SimulationException; @@ -19,12 +20,18 @@ public FCVTSL() { public void simulate(ProgramStatement statement) throws SimulationException { int[] operands = statement.getOperands(); + int hart = statement.getCurrentHart(); Environment e = new Environment(); e.mode = Floating.getRoundingMode(operands[2],statement); Float32 tmp = new Float32(0); - Float32 converted = jsoftfloat.operations.Conversions.convertFromInt(BigInteger.valueOf(RegisterFile.getValueLong(operands[1])),e,tmp); - Floating.setfflags(e); - FloatingPointRegisterFile.updateRegister(operands[0],converted.bits); + Float32 converted = Conversions.convertFromInt(BigInteger.valueOf((hart == -1) + ? RegisterFile.getValueLong(operands[1]) + : RegisterFile.getValueLong(operands[1], hart) + ), e, tmp); + Floating.setfflags(e, hart); + if (hart == -1) + FloatingPointRegisterFile.updateRegister(operands[0], converted.bits); + else + FloatingPointRegisterFile.updateRegister(operands[0], converted.bits, hart); } } - diff --git a/src/rars/riscv/instructions/FCVTSLU.java b/src/rars/riscv/instructions/FCVTSLU.java index 37360d4c..42b0d732 100644 --- a/src/rars/riscv/instructions/FCVTSLU.java +++ b/src/rars/riscv/instructions/FCVTSLU.java @@ -1,6 +1,7 @@ package rars.riscv.instructions; import jsoftfloat.Environment; +import jsoftfloat.operations.Conversions; import jsoftfloat.types.Float32; import rars.ProgramStatement; import rars.SimulationException; @@ -19,17 +20,22 @@ public FCVTSLU() { public void simulate(ProgramStatement statement) throws SimulationException { int[] operands = statement.getOperands(); + int hart = statement.getCurrentHart(); Environment e = new Environment(); e.mode = Floating.getRoundingMode(operands[2],statement); Float32 tmp = new Float32(0); - long value = RegisterFile.getValueLong(operands[1]); + long value = (hart == -1) + ? RegisterFile.getValueLong(operands[1]) + : RegisterFile.getValueLong(operands[1], hart); BigInteger unsigned = BigInteger.valueOf(value); if (value < 0) { unsigned = unsigned.add(BigInteger.ONE.shiftLeft(64)); } - Float32 converted = jsoftfloat.operations.Conversions.convertFromInt(unsigned,e,tmp); - Floating.setfflags(e); - FloatingPointRegisterFile.updateRegister(operands[0],converted.bits); + Float32 converted = Conversions.convertFromInt(unsigned,e,tmp); + Floating.setfflags(e, hart); + if (hart == -1) + FloatingPointRegisterFile.updateRegister(operands[0], converted.bits); + else + FloatingPointRegisterFile.updateRegister(operands[0], converted.bits, hart); } } - diff --git a/src/rars/riscv/instructions/FCVTSW.java b/src/rars/riscv/instructions/FCVTSW.java index 3902630c..ec05f340 100644 --- a/src/rars/riscv/instructions/FCVTSW.java +++ b/src/rars/riscv/instructions/FCVTSW.java @@ -1,6 +1,7 @@ package rars.riscv.instructions; import jsoftfloat.Environment; +import jsoftfloat.operations.Conversions; import jsoftfloat.types.Float32; import rars.ProgramStatement; import rars.SimulationException; @@ -46,12 +47,18 @@ public FCVTSW() { public void simulate(ProgramStatement statement) throws SimulationException { int[] operands = statement.getOperands(); + int hart = statement.getCurrentHart(); Environment e = new Environment(); e.mode = Floating.getRoundingMode(operands[2],statement); Float32 tmp = new Float32(0); - Float32 converted = jsoftfloat.operations.Conversions.convertFromInt(BigInteger.valueOf(RegisterFile.getValue(operands[1])),e,tmp); - Floating.setfflags(e); - FloatingPointRegisterFile.updateRegister(operands[0],converted.bits); + Float32 converted = Conversions.convertFromInt(BigInteger.valueOf((hart == -1) + ? RegisterFile.getValue(operands[1]) + : RegisterFile.getValueLong(operands[1], hart) + ), e, tmp); + Floating.setfflags(e, hart); + if (hart == -1) + FloatingPointRegisterFile.updateRegister(operands[0], converted.bits); + else + FloatingPointRegisterFile.updateRegister(operands[0], converted.bits, hart); } } - diff --git a/src/rars/riscv/instructions/FCVTSWU.java b/src/rars/riscv/instructions/FCVTSWU.java index 4a452ae8..34f92488 100644 --- a/src/rars/riscv/instructions/FCVTSWU.java +++ b/src/rars/riscv/instructions/FCVTSWU.java @@ -1,6 +1,7 @@ package rars.riscv.instructions; import jsoftfloat.Environment; +import jsoftfloat.operations.Conversions; import jsoftfloat.types.Float32; import rars.ProgramStatement; import rars.SimulationException; @@ -46,12 +47,18 @@ public FCVTSWU() { public void simulate(ProgramStatement statement) throws SimulationException { int[] operands = statement.getOperands(); + int hart = statement.getCurrentHart(); Environment e = new Environment(); e.mode = Floating.getRoundingMode(operands[2],statement); Float32 tmp = new Float32(0); - Float32 converted = jsoftfloat.operations.Conversions.convertFromInt(BigInteger.valueOf(RegisterFile.getValue(operands[1]) &0xFFFFFFFFL),e,tmp); - Floating.setfflags(e); - FloatingPointRegisterFile.updateRegister(operands[0],converted.bits); + Float32 converted = Conversions.convertFromInt(BigInteger.valueOf(((hart == -1) + ? RegisterFile.getValue(operands[1]) + : RegisterFile.getValue(operands[1], hart)) & 0xFFFFFFFFL), + e, tmp); + Floating.setfflags(e, hart); + if (hart == -1) + FloatingPointRegisterFile.updateRegister(operands[0], converted.bits); + else + FloatingPointRegisterFile.updateRegister(operands[0], converted.bits, hart); } } - diff --git a/src/rars/riscv/instructions/FCVTWD.java b/src/rars/riscv/instructions/FCVTWD.java index c6ff4f10..48fc1fa2 100644 --- a/src/rars/riscv/instructions/FCVTWD.java +++ b/src/rars/riscv/instructions/FCVTWD.java @@ -1,6 +1,7 @@ package rars.riscv.instructions; import jsoftfloat.Environment; +import jsoftfloat.operations.Conversions; import jsoftfloat.types.Float64; import rars.ProgramStatement; import rars.SimulationException; @@ -17,12 +18,17 @@ public FCVTWD() { public void simulate(ProgramStatement statement) throws SimulationException { int[] operands = statement.getOperands(); + int hart = statement.getCurrentHart(); Environment e = new Environment(); e.mode = Floating.getRoundingMode(operands[2],statement); - Float64 in = new Float64(FloatingPointRegisterFile.getValueLong(operands[1])); - int out = jsoftfloat.operations.Conversions.convertToInt(in,e,false); - Floating.setfflags(e); - RegisterFile.updateRegister(operands[0],out); + Float64 in = new Float64((hart == -1) + ? FloatingPointRegisterFile.getValueLong(operands[1]) + : FloatingPointRegisterFile.getValueLong(operands[1], hart)); + int out = Conversions.convertToInt(in,e,false); + Floating.setfflags(e, hart); + if (hart == -1) + RegisterFile.updateRegister(operands[0], out); + else + RegisterFile.updateRegister(operands[0], out, hart); } } - diff --git a/src/rars/riscv/instructions/FCVTWS.java b/src/rars/riscv/instructions/FCVTWS.java index 84792325..d904a6dd 100644 --- a/src/rars/riscv/instructions/FCVTWS.java +++ b/src/rars/riscv/instructions/FCVTWS.java @@ -1,18 +1,15 @@ package rars.riscv.instructions; import jsoftfloat.Environment; +import jsoftfloat.operations.Conversions; import jsoftfloat.types.Float32; import rars.ProgramStatement; import rars.SimulationException; -import rars.assembler.DataTypes; -import rars.riscv.hardware.ControlAndStatusRegisterFile; import rars.riscv.hardware.FloatingPointRegisterFile; import rars.riscv.hardware.RegisterFile; import rars.riscv.BasicInstruction; import rars.riscv.BasicInstructionFormat; -import java.math.BigInteger; - /* Copyright (c) 2017, Benjamin Landers @@ -48,12 +45,17 @@ public FCVTWS() { public void simulate(ProgramStatement statement) throws SimulationException { int[] operands = statement.getOperands(); + int hart = statement.getCurrentHart(); Environment e = new Environment(); e.mode = Floating.getRoundingMode(operands[2],statement); - Float32 in = new Float32(FloatingPointRegisterFile.getValue(operands[1])); - int out = jsoftfloat.operations.Conversions.convertToInt(in,e,false); - Floating.setfflags(e); - RegisterFile.updateRegister(operands[0],out); + Float32 in = new Float32((hart == -1) + ? FloatingPointRegisterFile.getValue(operands[1]) + : FloatingPointRegisterFile.getValue(operands[1], hart)); + int out = Conversions.convertToInt(in,e,false); + Floating.setfflags(e, hart); + if (hart == -1) + RegisterFile.updateRegister(operands[0], out); + else + RegisterFile.updateRegister(operands[0], out, hart); } } - diff --git a/src/rars/riscv/instructions/FCVTWUD.java b/src/rars/riscv/instructions/FCVTWUD.java index 1b889fdd..14736092 100644 --- a/src/rars/riscv/instructions/FCVTWUD.java +++ b/src/rars/riscv/instructions/FCVTWUD.java @@ -1,6 +1,7 @@ package rars.riscv.instructions; import jsoftfloat.Environment; +import jsoftfloat.operations.Conversions; import jsoftfloat.types.Float64; import rars.ProgramStatement; import rars.SimulationException; @@ -17,11 +18,17 @@ public FCVTWUD() { public void simulate(ProgramStatement statement) throws SimulationException { int[] operands = statement.getOperands(); + int hart = statement.getCurrentHart(); Environment e = new Environment(); e.mode = Floating.getRoundingMode(operands[2],statement); - Float64 in = new Float64(FloatingPointRegisterFile.getValueLong(operands[1])); - int out = jsoftfloat.operations.Conversions.convertToUnsignedInt(in,e,false); - Floating.setfflags(e); - RegisterFile.updateRegister(operands[0],out); + Float64 in = new Float64((hart == -1) + ? FloatingPointRegisterFile.getValueLong(operands[1]) + : FloatingPointRegisterFile.getValueLong(operands[1], hart)); + int out = Conversions.convertToUnsignedInt(in,e,false); + Floating.setfflags(e, hart); + if (hart == -1) + RegisterFile.updateRegister(operands[0], out); + else + RegisterFile.updateRegister(operands[0], out, hart); } -} \ No newline at end of file +} diff --git a/src/rars/riscv/instructions/FCVTWUS.java b/src/rars/riscv/instructions/FCVTWUS.java index 3babac10..657a706c 100644 --- a/src/rars/riscv/instructions/FCVTWUS.java +++ b/src/rars/riscv/instructions/FCVTWUS.java @@ -1,11 +1,10 @@ package rars.riscv.instructions; import jsoftfloat.Environment; +import jsoftfloat.operations.Conversions; import jsoftfloat.types.Float32; import rars.ProgramStatement; import rars.SimulationException; -import rars.assembler.DataTypes; -import rars.riscv.hardware.ControlAndStatusRegisterFile; import rars.riscv.hardware.FloatingPointRegisterFile; import rars.riscv.hardware.RegisterFile; import rars.riscv.BasicInstruction; @@ -46,11 +45,17 @@ public FCVTWUS() { public void simulate(ProgramStatement statement) throws SimulationException { int[] operands = statement.getOperands(); + int hart = statement.getCurrentHart(); Environment e = new Environment(); e.mode = Floating.getRoundingMode(operands[2],statement); - Float32 in = new Float32(FloatingPointRegisterFile.getValue(operands[1])); - int out = jsoftfloat.operations.Conversions.convertToUnsignedInt(in,e,false); - Floating.setfflags(e); - RegisterFile.updateRegister(operands[0],out); + Float32 in = new Float32((hart == -1) + ? FloatingPointRegisterFile.getValue(operands[1]) + : FloatingPointRegisterFile.getValue(operands[1])); + int out = Conversions.convertToUnsignedInt(in,e,false); + Floating.setfflags(e, hart); + if (hart == -1) + RegisterFile.updateRegister(operands[0],out); + else + RegisterFile.updateRegister(operands[0], out); } -} \ No newline at end of file +} diff --git a/src/rars/riscv/instructions/FENCE.java b/src/rars/riscv/instructions/FENCE.java index e5324a6c..a15cf3b2 100644 --- a/src/rars/riscv/instructions/FENCE.java +++ b/src/rars/riscv/instructions/FENCE.java @@ -39,5 +39,6 @@ public FENCE() { public void simulate(ProgramStatement statement) { // Do nothing, currently there are no other threads so local consitency is enough + // TODO idk what to do for now but something will need to be implemented, maybe with a global variable? } -} \ No newline at end of file +} diff --git a/src/rars/riscv/instructions/FEQD.java b/src/rars/riscv/instructions/FEQD.java index ead483a2..d54b7c5c 100644 --- a/src/rars/riscv/instructions/FEQD.java +++ b/src/rars/riscv/instructions/FEQD.java @@ -1,6 +1,7 @@ package rars.riscv.instructions; import jsoftfloat.Environment; +import jsoftfloat.operations.Comparisons; import jsoftfloat.types.Float64; import rars.ProgramStatement; import rars.riscv.BasicInstruction; @@ -15,10 +16,14 @@ public FEQD() { public void simulate(ProgramStatement statement) { int[] operands = statement.getOperands(); + int hart = statement.getCurrentHart(); Float64 f1 = Double.getDouble(operands[1]), f2 = Double.getDouble(operands[2]); Environment e = new Environment(); - boolean result = jsoftfloat.operations.Comparisons.compareQuietEqual(f1,f2,e); - Floating.setfflags(e); - RegisterFile.updateRegister(operands[0], result ? 1 : 0); + boolean result = Comparisons.compareQuietEqual(f1,f2,e); + Floating.setfflags(e, hart); + if (hart == -1) + RegisterFile.updateRegister(operands[0], result ? 1 : 0); + else + RegisterFile.updateRegister(operands[0], result ? 1 : 0, hart); } -} \ No newline at end of file +} diff --git a/src/rars/riscv/instructions/FEQS.java b/src/rars/riscv/instructions/FEQS.java index 5c7f71d3..473d0a2f 100644 --- a/src/rars/riscv/instructions/FEQS.java +++ b/src/rars/riscv/instructions/FEQS.java @@ -1,10 +1,9 @@ package rars.riscv.instructions; import jsoftfloat.Environment; +import jsoftfloat.operations.Comparisons; import jsoftfloat.types.Float32; import rars.ProgramStatement; -import rars.riscv.hardware.ControlAndStatusRegisterFile; -import rars.riscv.hardware.FloatingPointRegisterFile; import rars.riscv.hardware.RegisterFile; import rars.riscv.BasicInstruction; import rars.riscv.BasicInstructionFormat; @@ -44,10 +43,14 @@ public FEQS() { public void simulate(ProgramStatement statement) { int[] operands = statement.getOperands(); + int hart = statement.getCurrentHart(); Float32 f1 = Floating.getFloat(operands[1]), f2 = Floating.getFloat(operands[2]); Environment e = new Environment(); - boolean result = jsoftfloat.operations.Comparisons.compareQuietEqual(f1,f2,e); - Floating.setfflags(e); - RegisterFile.updateRegister(operands[0], result ? 1 : 0); + boolean result = Comparisons.compareQuietEqual(f1,f2,e); + Floating.setfflags(e, hart); + if (hart == -1) + RegisterFile.updateRegister(operands[0], result ? 1 : 0); + else + RegisterFile.updateRegister(operands[0], result ? 1 : 0, hart); } -} \ No newline at end of file +} diff --git a/src/rars/riscv/instructions/FLD.java b/src/rars/riscv/instructions/FLD.java index cbe27744..84aec4ba 100644 --- a/src/rars/riscv/instructions/FLD.java +++ b/src/rars/riscv/instructions/FLD.java @@ -17,13 +17,21 @@ public FLD() { public void simulate(ProgramStatement statement) throws SimulationException { int[] operands = statement.getOperands(); + int hart = statement.getCurrentHart(); operands[1] = (operands[1] << 20) >> 20; try { - long low = Globals.memory.getWord(RegisterFile.getValue(operands[2]) + operands[1]); - long high = Globals.memory.getWord(RegisterFile.getValue(operands[2]) + operands[1]+4); - FloatingPointRegisterFile.updateRegisterLong(operands[0], (high << 32) | (low & 0xFFFFFFFFL)); + long low = Globals.memory.getWord(((hart == -1) + ? RegisterFile.getValue(operands[2]) + : RegisterFile.getValue(operands[2])) + operands[1]); + long high = Globals.memory.getWord(((hart == -1) + ? RegisterFile.getValue(operands[2]) + : RegisterFile.getValue(operands[2])) + operands[1] + 4); + if (hart == -1) + FloatingPointRegisterFile.updateRegisterLong(operands[0], (high << 32) | (low & 0xFFFFFFFFL)); + else + FloatingPointRegisterFile.updateRegisterLong(operands[0], (high << 32) | (low & 0xFFFFFFFFL), hart); } catch (AddressErrorException e) { throw new SimulationException(statement, e); } } -} \ No newline at end of file +} diff --git a/src/rars/riscv/instructions/FLED.java b/src/rars/riscv/instructions/FLED.java index 25af82ab..b0d9039c 100644 --- a/src/rars/riscv/instructions/FLED.java +++ b/src/rars/riscv/instructions/FLED.java @@ -1,6 +1,7 @@ package rars.riscv.instructions; import jsoftfloat.Environment; +import jsoftfloat.operations.Comparisons; import jsoftfloat.types.Float64; import rars.ProgramStatement; import rars.riscv.BasicInstruction; @@ -15,10 +16,14 @@ public FLED() { public void simulate(ProgramStatement statement) { int[] operands = statement.getOperands(); + int hart = statement.getCurrentHart(); Float64 f1 = Double.getDouble(operands[1]), f2 = Double.getDouble(operands[2]); Environment e = new Environment(); - boolean result = jsoftfloat.operations.Comparisons.compareSignalingLessThanEqual(f1,f2,e); - Floating.setfflags(e); - RegisterFile.updateRegister(operands[0], result ? 1 : 0); + boolean result = Comparisons.compareSignalingLessThanEqual(f1,f2,e); + Floating.setfflags(e, hart); + if (hart == -1) + RegisterFile.updateRegister(operands[0], result ? 1 : 0); + else + RegisterFile.updateRegister(operands[0], result ? 1 : 0, hart); } -} \ No newline at end of file +} diff --git a/src/rars/riscv/instructions/FLES.java b/src/rars/riscv/instructions/FLES.java index f0404acf..e8c775b4 100644 --- a/src/rars/riscv/instructions/FLES.java +++ b/src/rars/riscv/instructions/FLES.java @@ -1,10 +1,9 @@ package rars.riscv.instructions; import jsoftfloat.Environment; +import jsoftfloat.operations.Comparisons; import jsoftfloat.types.Float32; import rars.ProgramStatement; -import rars.riscv.hardware.ControlAndStatusRegisterFile; -import rars.riscv.hardware.FloatingPointRegisterFile; import rars.riscv.hardware.RegisterFile; import rars.riscv.BasicInstruction; import rars.riscv.BasicInstructionFormat; @@ -44,10 +43,14 @@ public FLES() { public void simulate(ProgramStatement statement) { int[] operands = statement.getOperands(); + int hart = statement.getCurrentHart(); Float32 f1 = Floating.getFloat(operands[1]), f2 = Floating.getFloat(operands[2]); Environment e = new Environment(); - boolean result = jsoftfloat.operations.Comparisons.compareSignalingLessThanEqual(f1,f2,e); - Floating.setfflags(e); - RegisterFile.updateRegister(operands[0], result ? 1 : 0); + boolean result = Comparisons.compareSignalingLessThanEqual(f1,f2,e); + Floating.setfflags(e, hart); + if (hart == -1) + RegisterFile.updateRegister(operands[0], result ? 1 : 0); + else + RegisterFile.updateRegister(operands[0], result ? 1 : 0, hart); } -} \ No newline at end of file +} diff --git a/src/rars/riscv/instructions/FLTD.java b/src/rars/riscv/instructions/FLTD.java index 0d4709f4..e9f406bf 100644 --- a/src/rars/riscv/instructions/FLTD.java +++ b/src/rars/riscv/instructions/FLTD.java @@ -1,6 +1,7 @@ package rars.riscv.instructions; import jsoftfloat.Environment; +import jsoftfloat.operations.Comparisons; import jsoftfloat.types.Float64; import rars.ProgramStatement; import rars.riscv.BasicInstruction; @@ -15,10 +16,14 @@ public FLTD() { public void simulate(ProgramStatement statement) { int[] operands = statement.getOperands(); + int hart = statement.getCurrentHart(); Float64 f1 = Double.getDouble(operands[1]), f2 = Double.getDouble(operands[2]); Environment e = new Environment(); - boolean result = jsoftfloat.operations.Comparisons.compareSignalingLessThan(f1,f2,e); - Floating.setfflags(e); - RegisterFile.updateRegister(operands[0], result ? 1 : 0); + boolean result = Comparisons.compareSignalingLessThan(f1,f2,e); + Floating.setfflags(e, hart); + if (hart == -1) + RegisterFile.updateRegister(operands[0], result ? 1 : 0); + else + RegisterFile.updateRegister(operands[0], result ? 1 : 0, hart); } -} \ No newline at end of file +} diff --git a/src/rars/riscv/instructions/FLTS.java b/src/rars/riscv/instructions/FLTS.java index b979eb53..b2f8a970 100644 --- a/src/rars/riscv/instructions/FLTS.java +++ b/src/rars/riscv/instructions/FLTS.java @@ -1,10 +1,9 @@ package rars.riscv.instructions; import jsoftfloat.Environment; +import jsoftfloat.operations.Comparisons; import jsoftfloat.types.Float32; import rars.ProgramStatement; -import rars.riscv.hardware.ControlAndStatusRegisterFile; -import rars.riscv.hardware.FloatingPointRegisterFile; import rars.riscv.hardware.RegisterFile; import rars.riscv.BasicInstruction; import rars.riscv.BasicInstructionFormat; @@ -44,10 +43,14 @@ public FLTS() { public void simulate(ProgramStatement statement) { int[] operands = statement.getOperands(); + int hart = statement.getCurrentHart(); Float32 f1 = Floating.getFloat(operands[1]), f2 = Floating.getFloat(operands[2]); Environment e = new Environment(); - boolean result = jsoftfloat.operations.Comparisons.compareSignalingLessThan(f1,f2,e); - Floating.setfflags(e); - RegisterFile.updateRegister(operands[0], result ? 1 : 0); + boolean result = Comparisons.compareSignalingLessThan(f1,f2,e); + Floating.setfflags(e, hart); + if (hart == -1) + RegisterFile.updateRegister(operands[0], result ? 1 : 0); + else + RegisterFile.updateRegister(operands[0], result ? 1 : 0, hart); } -} \ No newline at end of file +} diff --git a/src/rars/riscv/instructions/FLW.java b/src/rars/riscv/instructions/FLW.java index 76565885..4d41f462 100644 --- a/src/rars/riscv/instructions/FLW.java +++ b/src/rars/riscv/instructions/FLW.java @@ -44,11 +44,18 @@ public FLW() { public void simulate(ProgramStatement statement) throws SimulationException { int[] operands = statement.getOperands(); + int hart = statement.getCurrentHart(); operands[1] = (operands[1] << 20) >> 20; try { - FloatingPointRegisterFile.updateRegister(operands[0], Globals.memory.getWord(RegisterFile.getValue(operands[2]) + operands[1])); + if (hart == -1) + FloatingPointRegisterFile.updateRegister(operands[0], + Globals.memory.getWord(RegisterFile.getValue(operands[2]) + operands[1])); + else + FloatingPointRegisterFile.updateRegister(operands[0], + Globals.memory.getWord(RegisterFile.getValue(operands[2], hart) + operands[1]), + hart); } catch (AddressErrorException e) { throw new SimulationException(statement, e); } } -} \ No newline at end of file +} diff --git a/src/rars/riscv/instructions/FMVDX.java b/src/rars/riscv/instructions/FMVDX.java index 8f45800c..f4957922 100644 --- a/src/rars/riscv/instructions/FMVDX.java +++ b/src/rars/riscv/instructions/FMVDX.java @@ -14,6 +14,12 @@ public FMVDX() { public void simulate(ProgramStatement statement) { int[] operands = statement.getOperands(); - FloatingPointRegisterFile.updateRegisterLong(operands[0], RegisterFile.getValueLong(operands[1])); + int hart = statement.getCurrentHart(); + if (hart == -1) + FloatingPointRegisterFile.updateRegisterLong(operands[0], + RegisterFile.getValueLong(operands[1])); + else + FloatingPointRegisterFile.updateRegisterLong(operands[0], + RegisterFile.getValueLong(operands[1], hart), hart); } -} \ No newline at end of file +} diff --git a/src/rars/riscv/instructions/FMVSX.java b/src/rars/riscv/instructions/FMVSX.java index 7670a204..18bcb123 100644 --- a/src/rars/riscv/instructions/FMVSX.java +++ b/src/rars/riscv/instructions/FMVSX.java @@ -41,6 +41,12 @@ public FMVSX() { public void simulate(ProgramStatement statement) { int[] operands = statement.getOperands(); - FloatingPointRegisterFile.updateRegister(operands[0], RegisterFile.getValue(operands[1])); + int hart = statement.getCurrentHart(); + if (hart == -1) + FloatingPointRegisterFile.updateRegister(operands[0], + RegisterFile.getValue(operands[1])); + else + FloatingPointRegisterFile.updateRegister(operands[0], + RegisterFile.getValue(operands[1], hart), hart); } -} \ No newline at end of file +} diff --git a/src/rars/riscv/instructions/FMVXD.java b/src/rars/riscv/instructions/FMVXD.java index 7d0b1c3f..ebccb65e 100644 --- a/src/rars/riscv/instructions/FMVXD.java +++ b/src/rars/riscv/instructions/FMVXD.java @@ -14,6 +14,12 @@ public FMVXD() { public void simulate(ProgramStatement statement) { int[] operands = statement.getOperands(); - RegisterFile.updateRegister(operands[0], FloatingPointRegisterFile.getValueLong(operands[1])); + int hart = statement.getCurrentHart(); + if (hart == -1) + RegisterFile.updateRegister(operands[0], + FloatingPointRegisterFile.getValueLong(operands[1])); + else + RegisterFile.updateRegister(operands[0], + FloatingPointRegisterFile.getValueLong(operands[1], hart), hart); } -} \ No newline at end of file +} diff --git a/src/rars/riscv/instructions/FMVXS.java b/src/rars/riscv/instructions/FMVXS.java index 095f34e5..056d66fd 100644 --- a/src/rars/riscv/instructions/FMVXS.java +++ b/src/rars/riscv/instructions/FMVXS.java @@ -41,6 +41,12 @@ public FMVXS() { public void simulate(ProgramStatement statement) { int[] operands = statement.getOperands(); - RegisterFile.updateRegister(operands[0], (int)FloatingPointRegisterFile.getValueLong(operands[1])); + int hart = statement.getCurrentHart(); + if (hart == -1) + RegisterFile.updateRegister(operands[0], + (int) FloatingPointRegisterFile.getValueLong(operands[1])); + else + RegisterFile.updateRegister(operands[0], + (int) FloatingPointRegisterFile.getValueLong(operands[1], hart), hart); } -} \ No newline at end of file +} diff --git a/src/rars/riscv/instructions/FSD.java b/src/rars/riscv/instructions/FSD.java index 686f6712..c72042f5 100644 --- a/src/rars/riscv/instructions/FSD.java +++ b/src/rars/riscv/instructions/FSD.java @@ -17,11 +17,17 @@ public FSD() { public void simulate(ProgramStatement statement) throws SimulationException { int[] operands = statement.getOperands(); + int hart = statement.getCurrentHart(); operands[1] = (operands[1] << 20) >> 20; try { - Globals.memory.setDoubleWord(RegisterFile.getValue(operands[2]) + operands[1], FloatingPointRegisterFile.getValueLong(operands[0])); + Globals.memory.setDoubleWord(((hart == -1) + ? RegisterFile.getValue(operands[2]) + : RegisterFile.getValue(operands[2], hart)) + operands[1], + (hart == -1) + ? FloatingPointRegisterFile.getValueLong(operands[0]) + : FloatingPointRegisterFile.getValueLong(operands[0], hart)); } catch (AddressErrorException e) { throw new SimulationException(statement, e); } } -} \ No newline at end of file +} diff --git a/src/rars/riscv/instructions/FSGNJD.java b/src/rars/riscv/instructions/FSGNJD.java index 966d372a..35d3b3a3 100644 --- a/src/rars/riscv/instructions/FSGNJD.java +++ b/src/rars/riscv/instructions/FSGNJD.java @@ -13,8 +13,18 @@ public FSGNJD() { public void simulate(ProgramStatement statement) { int[] operands = statement.getOperands(); - long result = (FloatingPointRegisterFile.getValueLong(operands[1]) & 0x7FFFFFFF_FFFFFFFFL) | - (FloatingPointRegisterFile.getValueLong(operands[2]) & 0x80000000_00000000L); - FloatingPointRegisterFile.updateRegisterLong(operands[0], result); + int hart = statement.getCurrentHart(); + long op1 = (hart == -1) + ? FloatingPointRegisterFile.getValueLong(operands[1]) + : FloatingPointRegisterFile.getValueLong(operands[1], hart); + long op2 = (hart == -1) + ? FloatingPointRegisterFile.getValueLong(operands[2]) + : FloatingPointRegisterFile.getValueLong(operands[2], hart); + long result = (op1 & 0x7FFFFFFF_FFFFFFFFL) | + (op2 & 0x80000000_00000000L); + if (hart == -1) + FloatingPointRegisterFile.updateRegisterLong(operands[0], result); + else + FloatingPointRegisterFile.updateRegisterLong(operands[0], result, hart); } -} \ No newline at end of file +} diff --git a/src/rars/riscv/instructions/FSGNJND.java b/src/rars/riscv/instructions/FSGNJND.java index 7767f246..c6cebbf0 100644 --- a/src/rars/riscv/instructions/FSGNJND.java +++ b/src/rars/riscv/instructions/FSGNJND.java @@ -13,8 +13,18 @@ public FSGNJND() { public void simulate(ProgramStatement statement) { int[] operands = statement.getOperands(); - long result = (FloatingPointRegisterFile.getValueLong(operands[1]) & 0x7FFFFFFF_FFFFFFFFL) | - ((~FloatingPointRegisterFile.getValueLong(operands[2])) & 0x80000000_00000000L); - FloatingPointRegisterFile.updateRegisterLong(operands[0], result); + int hart = statement.getCurrentHart(); + long op1 = (hart == -1) + ? FloatingPointRegisterFile.getValueLong(operands[1]) + : FloatingPointRegisterFile.getValueLong(operands[1], hart); + long op2= (hart == -1) + ? FloatingPointRegisterFile.getValueLong(operands[2]) + : FloatingPointRegisterFile.getValueLong(operands[2], hart); + long result = (op1 & 0x7FFFFFFF_FFFFFFFFL) | + ((~op2) & 0x80000000_00000000L); + if (hart == -1) + FloatingPointRegisterFile.updateRegisterLong(operands[0], result); + else + FloatingPointRegisterFile.updateRegisterLong(operands[0], result, hart); } -} \ No newline at end of file +} diff --git a/src/rars/riscv/instructions/FSGNJNS.java b/src/rars/riscv/instructions/FSGNJNS.java index e8d3b3c0..0e2ba086 100644 --- a/src/rars/riscv/instructions/FSGNJNS.java +++ b/src/rars/riscv/instructions/FSGNJNS.java @@ -40,7 +40,18 @@ public FSGNJNS() { public void simulate(ProgramStatement statement) { int[] operands = statement.getOperands(); - int result = (FloatingPointRegisterFile.getValue(operands[1]) & 0x7FFFFFFF) | ((~FloatingPointRegisterFile.getValue(operands[2])) & 0x80000000); - FloatingPointRegisterFile.updateRegister(operands[0], result); + int hart = statement.getCurrentHart(); + int op1 = (hart == -1) + ? FloatingPointRegisterFile.getValue(operands[1]) + : FloatingPointRegisterFile.getValue(operands[1], hart); + int op2 = (hart == -1) + ? FloatingPointRegisterFile.getValue(operands[2]) + : FloatingPointRegisterFile.getValue(operands[2], hart); + int result = (op1 & 0x7FFFFFFF) | + ((~op2) & 0x80000000); + if (hart == -1) + FloatingPointRegisterFile.updateRegister(operands[0], result); + else + FloatingPointRegisterFile.updateRegister(operands[0], result, hart); } -} \ No newline at end of file +} diff --git a/src/rars/riscv/instructions/FSGNJS.java b/src/rars/riscv/instructions/FSGNJS.java index 19cec7c8..f972789f 100644 --- a/src/rars/riscv/instructions/FSGNJS.java +++ b/src/rars/riscv/instructions/FSGNJS.java @@ -40,7 +40,17 @@ public FSGNJS() { public void simulate(ProgramStatement statement) { int[] operands = statement.getOperands(); - int result = (FloatingPointRegisterFile.getValue(operands[1]) & 0x7FFFFFFF) | (FloatingPointRegisterFile.getValue(operands[2]) & 0x80000000); - FloatingPointRegisterFile.updateRegister(operands[0], result); + int hart = statement.getCurrentHart(); + int op1 = (hart == -1) + ? FloatingPointRegisterFile.getValue(operands[1]) + : FloatingPointRegisterFile.getValue(operands[1], hart); + int op2 = (hart == -1) + ? FloatingPointRegisterFile.getValue(operands[2]) + : FloatingPointRegisterFile.getValue(operands[2], hart); + int result = (op1 & 0x7FFFFFFF) | (op2 & 0x80000000); + if (hart == -1) + FloatingPointRegisterFile.updateRegister(operands[0], result); + else + FloatingPointRegisterFile.updateRegister(operands[0], result, hart); } -} \ No newline at end of file +} diff --git a/src/rars/riscv/instructions/FSGNJXD.java b/src/rars/riscv/instructions/FSGNJXD.java index 01f9b34d..3cc4cf1b 100644 --- a/src/rars/riscv/instructions/FSGNJXD.java +++ b/src/rars/riscv/instructions/FSGNJXD.java @@ -13,8 +13,17 @@ public FSGNJXD() { public void simulate(ProgramStatement statement) { int[] operands = statement.getOperands(); - long f2 = FloatingPointRegisterFile.getValueLong(operands[1]), f3 = FloatingPointRegisterFile.getValueLong(operands[2]); + int hart = statement.getCurrentHart(); + long f2 = (hart == -1) + ? FloatingPointRegisterFile.getValueLong(operands[1]) + : FloatingPointRegisterFile.getValueLong(operands[1], hart); + long f3 = (hart == -1) + ? FloatingPointRegisterFile.getValueLong(operands[2]) + : FloatingPointRegisterFile.getValueLong(operands[2], hart); long result = (f2 & 0x7FFFFFFF_FFFFFFFFL) | ((f2 ^ f3) & 0x80000000_00000000L); - FloatingPointRegisterFile.updateRegisterLong(operands[0], result); + if (hart == -1) + FloatingPointRegisterFile.updateRegisterLong(operands[0], result); + else + FloatingPointRegisterFile.updateRegisterLong(operands[0], result, hart); } -} \ No newline at end of file +} diff --git a/src/rars/riscv/instructions/FSGNJXS.java b/src/rars/riscv/instructions/FSGNJXS.java index 8f9aae61..86fb3a03 100644 --- a/src/rars/riscv/instructions/FSGNJXS.java +++ b/src/rars/riscv/instructions/FSGNJXS.java @@ -40,8 +40,17 @@ public FSGNJXS() { public void simulate(ProgramStatement statement) { int[] operands = statement.getOperands(); - int f2 = FloatingPointRegisterFile.getValue(operands[1]), f3 = FloatingPointRegisterFile.getValue(operands[2]); + int hart = statement.getCurrentHart(); + int f2 = (hart == -1) + ? FloatingPointRegisterFile.getValue(operands[1]) + : FloatingPointRegisterFile.getValue(operands[1], hart); + int f3 = (hart == -1) + ? FloatingPointRegisterFile.getValue(operands[2]) + : FloatingPointRegisterFile.getValue(operands[2], hart); int result = (f2 & 0x7FFFFFFF) | ((f2 ^ f3) & 0x80000000); - FloatingPointRegisterFile.updateRegister(operands[0], result); + if (hart == -1) + FloatingPointRegisterFile.updateRegister(operands[0], result); + else + FloatingPointRegisterFile.updateRegister(operands[0], result, hart); } -} \ No newline at end of file +} diff --git a/src/rars/riscv/instructions/FSQRTD.java b/src/rars/riscv/instructions/FSQRTD.java index 17b49be0..f497493d 100644 --- a/src/rars/riscv/instructions/FSQRTD.java +++ b/src/rars/riscv/instructions/FSQRTD.java @@ -1,6 +1,7 @@ package rars.riscv.instructions; import jsoftfloat.Environment; +import jsoftfloat.operations.Arithmetic; import jsoftfloat.types.Float64; import rars.ProgramStatement; import rars.SimulationException; @@ -16,10 +17,17 @@ public FSQRTD() { public void simulate(ProgramStatement statement) throws SimulationException { int[] operands = statement.getOperands(); + int hart = statement.getCurrentHart(); Environment e = new Environment(); e.mode = Floating.getRoundingMode(operands[2],statement); - Float64 result = jsoftfloat.operations.Arithmetic.squareRoot(new Float64(FloatingPointRegisterFile.getValueLong(operands[1])),e); - Floating.setfflags(e); - FloatingPointRegisterFile.updateRegisterLong(operands[0],result.bits); + Float64 result = Arithmetic.squareRoot(new Float64((hart == -1) + ? FloatingPointRegisterFile.getValueLong(operands[1]) + : FloatingPointRegisterFile.getValueLong(operands[1], hart)), + e); + Floating.setfflags(e, hart); + if (hart == -1) + FloatingPointRegisterFile.updateRegisterLong(operands[0], result.bits); + else + FloatingPointRegisterFile.updateRegisterLong(operands[0], result.bits, hart); } -} \ No newline at end of file +} diff --git a/src/rars/riscv/instructions/FSQRTS.java b/src/rars/riscv/instructions/FSQRTS.java index 0c889d79..e3311c45 100644 --- a/src/rars/riscv/instructions/FSQRTS.java +++ b/src/rars/riscv/instructions/FSQRTS.java @@ -1,10 +1,10 @@ package rars.riscv.instructions; import jsoftfloat.Environment; +import jsoftfloat.operations.Arithmetic; import jsoftfloat.types.Float32; import rars.ProgramStatement; import rars.SimulationException; -import rars.riscv.hardware.ControlAndStatusRegisterFile; import rars.riscv.hardware.FloatingPointRegisterFile; import rars.riscv.BasicInstruction; import rars.riscv.BasicInstructionFormat; @@ -44,10 +44,17 @@ public FSQRTS() { public void simulate(ProgramStatement statement) throws SimulationException { int[] operands = statement.getOperands(); + int hart = statement.getCurrentHart(); Environment e = new Environment(); e.mode = Floating.getRoundingMode(operands[2],statement); - Float32 result = jsoftfloat.operations.Arithmetic.squareRoot(new Float32(FloatingPointRegisterFile.getValue(operands[1])),e); - Floating.setfflags(e); - FloatingPointRegisterFile.updateRegister(operands[0],result.bits); + Float32 result = Arithmetic.squareRoot(new Float32((hart == -1) + ? FloatingPointRegisterFile.getValue(operands[1]) + : FloatingPointRegisterFile.getValue(operands[1], hart)), + e); + Floating.setfflags(e, hart); + if (hart == -1) + FloatingPointRegisterFile.updateRegister(operands[0], result.bits); + else + FloatingPointRegisterFile.updateRegister(operands[0], result.bits, hart); } -} \ No newline at end of file +} diff --git a/src/rars/riscv/instructions/FSW.java b/src/rars/riscv/instructions/FSW.java index 3c5cbee3..b5621dfe 100644 --- a/src/rars/riscv/instructions/FSW.java +++ b/src/rars/riscv/instructions/FSW.java @@ -44,11 +44,17 @@ public FSW() { public void simulate(ProgramStatement statement) throws SimulationException { int[] operands = statement.getOperands(); + int hart = statement.getCurrentHart(); operands[1] = (operands[1] << 20) >> 20; try { - Globals.memory.setWord(RegisterFile.getValue(operands[2]) + operands[1], (int)FloatingPointRegisterFile.getValueLong(operands[0])); + Globals.memory.setWord(((hart == -1) + ? RegisterFile.getValue(operands[2]) + : RegisterFile.getValue(operands[2], hart)) + operands[1], + (hart == -1) + ? (int) FloatingPointRegisterFile.getValueLong(operands[0]) + : (int) FloatingPointRegisterFile.getValue(operands[0], hart)); } catch (AddressErrorException e) { throw new SimulationException(statement, e); } } -} \ No newline at end of file +} diff --git a/src/rars/riscv/instructions/Floating.java b/src/rars/riscv/instructions/Floating.java index 5955db2f..3b1c00c5 100644 --- a/src/rars/riscv/instructions/Floating.java +++ b/src/rars/riscv/instructions/Floating.java @@ -52,27 +52,48 @@ protected Floating(String name, String description, String funct) { protected Floating(String name, String description, String funct, String rm) { super(name + " f1, f2, f3", description, BasicInstructionFormat.R_FORMAT, funct + "ttttt sssss " + rm + " fffff 1010011"); } - public void simulate(ProgramStatement statement) throws SimulationException{ + + public void simulate(ProgramStatement statement) throws SimulationException { int[] operands = statement.getOperands(); + int hart = statement.getCurrentHart(); Environment e = new Environment(); - e.mode = getRoundingMode(operands[3],statement); - Float32 result = compute(new Float32(FloatingPointRegisterFile.getValue(operands[1])),new Float32(FloatingPointRegisterFile.getValue(operands[2])),e); - setfflags(e); - FloatingPointRegisterFile.updateRegister(operands[0], result.bits); + e.mode = getRoundingMode(operands[3], statement); + Float32 result = compute( + new Float32((hart == -1) + ? FloatingPointRegisterFile.getValue(operands[1]) + : FloatingPointRegisterFile.getValue(operands[1], hart) + ), + new Float32((hart == -1) + ? FloatingPointRegisterFile.getValue(operands[2]) + : FloatingPointRegisterFile.getValue(operands[2], hart) + ), + e); + setfflags(e, hart); + if (hart == -1) + FloatingPointRegisterFile.updateRegister(operands[0], result.bits); + else + FloatingPointRegisterFile.updateRegister(operands[0], result.bits, hart); } - public static void setfflags(Environment e){ + public static void setfflags(Environment e, int hart){ int fflags =(e.flags.contains(Flags.inexact)?1:0)+ (e.flags.contains(Flags.underflow)?2:0)+ (e.flags.contains(Flags.overflow)?4:0)+ (e.flags.contains(Flags.divByZero)?8:0)+ (e.flags.contains(Flags.invalid)?16:0); - if(fflags != 0) ControlAndStatusRegisterFile.orRegister("fflags",fflags); + if (fflags != 0) + if (hart == -1) + ControlAndStatusRegisterFile.orRegister("fflags", fflags); + else + ControlAndStatusRegisterFile.orRegister("fflags", fflags, hart); } public static RoundingMode getRoundingMode(int RM, ProgramStatement statement) throws SimulationException { int rm = RM; - int frm = ControlAndStatusRegisterFile.getValue("frm"); + int hart = statement.getCurrentHart(); + int frm = (hart == -1) + ? ControlAndStatusRegisterFile.getValue("frm") + : ControlAndStatusRegisterFile.getValue("frm", hart); if (rm == 7) rm = frm; switch (rm){ case 0: // RNE @@ -92,7 +113,11 @@ public static RoundingMode getRoundingMode(int RM, ProgramStatement statement) t public abstract Float32 compute(Float32 f1, Float32 f2, Environment e); - public static Float32 getFloat(int num){ + public static Float32 getFloat(int num) { return new Float32(FloatingPointRegisterFile.getValue(num)); } -} \ No newline at end of file + + public static Float32 getFloat(int num, int hart) { + return new Float32(FloatingPointRegisterFile.getValue(num, hart)); + } +} diff --git a/src/rars/riscv/instructions/FusedDouble.java b/src/rars/riscv/instructions/FusedDouble.java index 78e7f2ff..95aaa3a8 100644 --- a/src/rars/riscv/instructions/FusedDouble.java +++ b/src/rars/riscv/instructions/FusedDouble.java @@ -19,13 +19,24 @@ public FusedDouble(String usage, String description, String op) { public void simulate(ProgramStatement statement) throws SimulationException { int[] operands = statement.getOperands(); + int hart = statement.getCurrentHart(); Environment e = new Environment(); e.mode = Floating.getRoundingMode(operands[4],statement); - Float64 result = compute(new Float64(FloatingPointRegisterFile.getValueLong(operands[1])), - new Float64(FloatingPointRegisterFile.getValueLong(operands[2])), - new Float64(FloatingPointRegisterFile.getValueLong(operands[3])),e); - Floating.setfflags(e); - FloatingPointRegisterFile.updateRegisterLong(operands[0],result.bits); + Float64 result = compute(new Float64((hart == -1) + ? FloatingPointRegisterFile.getValueLong(operands[1]) + : FloatingPointRegisterFile.getValueLong(operands[1], hart)), + new Float64((hart == -1) + ? FloatingPointRegisterFile.getValueLong(operands[2]) + : FloatingPointRegisterFile.getValueLong(operands[2], hart)), + new Float64((hart == -1) + ? FloatingPointRegisterFile.getValueLong(operands[3]) + : FloatingPointRegisterFile.getValueLong(operands[3], hart)), + e); + Floating.setfflags(e, hart); + if (hart == -1) + FloatingPointRegisterFile.updateRegisterLong(operands[0], result.bits); + else + FloatingPointRegisterFile.updateRegisterLong(operands[0], result.bits, hart); } /** diff --git a/src/rars/riscv/instructions/FusedFloat.java b/src/rars/riscv/instructions/FusedFloat.java index 893ac6d1..a026aa31 100644 --- a/src/rars/riscv/instructions/FusedFloat.java +++ b/src/rars/riscv/instructions/FusedFloat.java @@ -5,7 +5,6 @@ import jsoftfloat.types.Float32; import rars.ProgramStatement; import rars.SimulationException; -import rars.riscv.hardware.ControlAndStatusRegisterFile; import rars.riscv.hardware.FloatingPointRegisterFile; import rars.riscv.BasicInstruction; import rars.riscv.BasicInstructionFormat; @@ -48,13 +47,24 @@ public FusedFloat(String usage, String description, String op) { public void simulate(ProgramStatement statement) throws SimulationException { int[] operands = statement.getOperands(); + int hart = statement.getCurrentHart(); Environment e = new Environment(); e.mode = Floating.getRoundingMode(operands[4],statement); - Float32 result = compute(new Float32(FloatingPointRegisterFile.getValue(operands[1])), - new Float32(FloatingPointRegisterFile.getValue(operands[2])), - new Float32(FloatingPointRegisterFile.getValue(operands[3])),e); - Floating.setfflags(e); - FloatingPointRegisterFile.updateRegister(operands[0],result.bits); + Float32 result = compute(new Float32((hart == -1) + ? FloatingPointRegisterFile.getValue(operands[1]) + : FloatingPointRegisterFile.getValue(operands[1], hart)), + new Float32((hart == -1) + ? FloatingPointRegisterFile.getValue(operands[2]) + : FloatingPointRegisterFile.getValue(operands[2])), + new Float32((hart == -1) + ? FloatingPointRegisterFile.getValue(operands[3]) + : FloatingPointRegisterFile.getValue(operands[2])), + e); + Floating.setfflags(e, hart); + if (hart == -1) + FloatingPointRegisterFile.updateRegister(operands[0],result.bits); + else + FloatingPointRegisterFile.updateRegisterLong(operands[0], result.bits, hart); } public static void flipRounding(Environment e){ diff --git a/src/rars/riscv/instructions/ImmediateInstruction.java b/src/rars/riscv/instructions/ImmediateInstruction.java index bb9a081a..0fda4448 100644 --- a/src/rars/riscv/instructions/ImmediateInstruction.java +++ b/src/rars/riscv/instructions/ImmediateInstruction.java @@ -51,12 +51,21 @@ public ImmediateInstruction(String usage, String description, String funct, bool public void simulate(ProgramStatement statement) { int[] operands = statement.getOperands(); - if (InstructionSet.rv64){ - RegisterFile.updateRegister(operands[0], compute(RegisterFile.getValueLong(operands[1]), + int hart = statement.getCurrentHart(); + if (InstructionSet.rv64) { + if (hart == -1) + RegisterFile.updateRegister(operands[0], compute(RegisterFile.getValueLong(operands[1]), (operands[2] << 20) >> 20)); // make sure the immediate is sign-extended - }else { - RegisterFile.updateRegister(operands[0], computeW(RegisterFile.getValue(operands[1]), + else + RegisterFile.updateRegister(operands[0], compute(RegisterFile.getValueLong(operands[1], hart), + (operands[2] << 20) >> 20), hart); // make sure the immediate is sign-extended + } else { + if (hart == -1) + RegisterFile.updateRegister(operands[0], computeW(RegisterFile.getValue(operands[1]), (operands[2] << 20) >> 20)); // make sure the immediate is sign-extended + else + RegisterFile.updateRegister(operands[0], computeW(RegisterFile.getValue(operands[1], hart), + (operands[2] << 20) >> 20), hart); // make sure the immediate is sign-extended } } @@ -72,6 +81,6 @@ public void simulate(ProgramStatement statement) { * @return the result to be stored from the instruction */ protected int computeW(int value, int immediate){ - return (int) compute(value,immediate); + return (int) compute(value, immediate); } -} \ No newline at end of file +} diff --git a/src/rars/riscv/instructions/JAL.java b/src/rars/riscv/instructions/JAL.java index 685bed0a..969e2f0e 100644 --- a/src/rars/riscv/instructions/JAL.java +++ b/src/rars/riscv/instructions/JAL.java @@ -42,7 +42,13 @@ public JAL() { public void simulate(ProgramStatement statement) { int[] operands = statement.getOperands(); + int hart = statement.getCurrentHart(); + if (hart >= 0) { + InstructionSet.processReturnAddress(operands[0], hart); + InstructionSet.processJump(RegisterFile.getProgramCounter(hart) - Instruction.INSTRUCTION_LENGTH + operands[1], hart); + return; + } InstructionSet.processReturnAddress(operands[0]); InstructionSet.processJump(RegisterFile.getProgramCounter() - Instruction.INSTRUCTION_LENGTH + operands[1]); } -} \ No newline at end of file +} diff --git a/src/rars/riscv/instructions/JALR.java b/src/rars/riscv/instructions/JALR.java index 2f209ac5..548a820f 100644 --- a/src/rars/riscv/instructions/JALR.java +++ b/src/rars/riscv/instructions/JALR.java @@ -41,9 +41,17 @@ public JALR() { public void simulate(ProgramStatement statement) { int[] operands = statement.getOperands(); - int target = RegisterFile.getValue(operands[1]); - InstructionSet.processReturnAddress(operands[0]); - // Set PC = $t2 + immediate with the last bit set to 0 - InstructionSet.processJump((target + ((operands[2]<<20)>>20)) & 0xFFFFFFFE); + int hart = statement.getCurrentHart(); + if (hart == -1) { + int target = RegisterFile.getValue(operands[1]); + InstructionSet.processReturnAddress(operands[0]); + // Set PC = $t2 + immediate with the last bit set to 0 + InstructionSet.processJump((target + ((operands[2] << 20) >> 20)) & 0xFFFFFFFE); + } else { + int target = RegisterFile.getValue(operands[1], hart); + InstructionSet.processReturnAddress(operands[0], hart); + // Set PC = $t2 + immediate with the last bit set to 0 + InstructionSet.processJump((target + ((operands[2] << 20) >> 20)) & 0xFFFFFFFE, hart); + } } -} \ No newline at end of file +} diff --git a/src/rars/riscv/instructions/LRD.java b/src/rars/riscv/instructions/LRD.java new file mode 100644 index 00000000..8417bd02 --- /dev/null +++ b/src/rars/riscv/instructions/LRD.java @@ -0,0 +1,32 @@ +package rars.riscv.instructions; + +import rars.Globals; +import rars.riscv.hardware.AddressErrorException; +import rars.ProgramStatement; +import rars.SimulationException; +import rars.riscv.hardware.RegisterFile; +import rars.riscv.hardware.ReservationTable.bitWidth; + +public class LRD extends Atomic { + public LRD() { + super("lr.d t1, (t2)", "Set t1 to contents of effective memory word address and reserve", "011", "00010", true); + } + + public void simulate(ProgramStatement statement) throws SimulationException { + int[] operands = statement.getOperands(); + try { + int hart = statement.getCurrentHart(); + if (hart == -1) + RegisterFile.updateRegister(operands[0], load(RegisterFile.getValue(operands[1]), hart)); + else + RegisterFile.updateRegister(operands[0], load(RegisterFile.getValue(operands[1], hart), hart), hart); + } catch (AddressErrorException e) { + throw new SimulationException(statement, e); + } + } + + private long load(int address, int hart) throws AddressErrorException { + Globals.reservationTables.reserveAddress(hart + 1, address, bitWidth.doubleWord); + return Globals.memory.getDoubleWord(address); + } +} diff --git a/src/rars/riscv/instructions/LRW.java b/src/rars/riscv/instructions/LRW.java new file mode 100644 index 00000000..4a37cb89 --- /dev/null +++ b/src/rars/riscv/instructions/LRW.java @@ -0,0 +1,32 @@ +package rars.riscv.instructions; + +import rars.Globals; +import rars.riscv.hardware.AddressErrorException; +import rars.ProgramStatement; +import rars.SimulationException; +import rars.riscv.hardware.RegisterFile; +import rars.riscv.hardware.ReservationTable.bitWidth; + +public class LRW extends Atomic { + public LRW() { + super("lr.w t1, (t2)", "Set t1 to contents of effective memory word address and reserve", "010", "00010"); + } + + public void simulate(ProgramStatement statement) throws SimulationException { + int[] operands = statement.getOperands(); + try { + int hart = statement.getCurrentHart(); + if (hart == -1) + RegisterFile.updateRegister(operands[0], load(RegisterFile.getValue(operands[1]), hart)); + else + RegisterFile.updateRegister(operands[0], load(RegisterFile.getValue(operands[1], hart), hart), hart); + } catch (AddressErrorException e) { + throw new SimulationException(statement, e); + } + } + + private long load(int address, int hart) throws AddressErrorException { + Globals.reservationTables.reserveAddress(hart + 1, address, bitWidth.word); + return Globals.memory.getWord(address); + } +} diff --git a/src/rars/riscv/instructions/LUI.java b/src/rars/riscv/instructions/LUI.java index 0a162a71..a3a3468e 100644 --- a/src/rars/riscv/instructions/LUI.java +++ b/src/rars/riscv/instructions/LUI.java @@ -40,6 +40,10 @@ public LUI() { public void simulate(ProgramStatement statement) { int[] operands = statement.getOperands(); - RegisterFile.updateRegister(operands[0], operands[1] << 12); + int hart = statement.getCurrentHart(); + if (hart == -1) + RegisterFile.updateRegister(operands[0], operands[1] << 12); + else + RegisterFile.updateRegister(operands[0], operands[1] << 12, hart); } } diff --git a/src/rars/riscv/instructions/Load.java b/src/rars/riscv/instructions/Load.java index e2c89eb7..9f5df928 100644 --- a/src/rars/riscv/instructions/Load.java +++ b/src/rars/riscv/instructions/Load.java @@ -42,21 +42,24 @@ a copy of this software and associated documentation files (the */ public abstract class Load extends BasicInstruction { public Load(String usage, String description, String funct) { - super(usage, description, BasicInstructionFormat.I_FORMAT, - "ssssssssssss ttttt " + funct + " fffff 0000011"); + super(usage, description, BasicInstructionFormat.I_FORMAT, "ssssssssssss ttttt " + funct + " fffff 0000011"); } + public Load(String usage, String description, String funct, boolean rv64) { super(usage, description, BasicInstructionFormat.I_FORMAT, "ssssssssssss ttttt " + funct + " fffff 0000011",rv64); - } public void simulate(ProgramStatement statement) throws SimulationException { int[] operands = statement.getOperands(); operands[1] = (operands[1] << 20) >> 20; + int hart = statement.getCurrentHart(); try { - RegisterFile.updateRegister(operands[0], load(RegisterFile.getValue(operands[2]) + operands[1])); + if (hart == -1) + RegisterFile.updateRegister(operands[0], load(RegisterFile.getValue(operands[2]) + operands[1])); + else + RegisterFile.updateRegister(operands[0], load(RegisterFile.getValue(operands[2], hart) + operands[1]), hart); } catch (AddressErrorException e) { throw new SimulationException(statement, e); } @@ -67,4 +70,4 @@ public void simulate(ProgramStatement statement) throws SimulationException { * @return The value to store to the register */ protected abstract long load(int address) throws AddressErrorException; -} \ No newline at end of file +} diff --git a/src/rars/riscv/instructions/REM.java b/src/rars/riscv/instructions/REM.java index 1fa9644e..c0ad5930 100644 --- a/src/rars/riscv/instructions/REM.java +++ b/src/rars/riscv/instructions/REM.java @@ -1,7 +1,5 @@ package rars.riscv.instructions; -import rars.riscv.hardware.ControlAndStatusRegisterFile; - /* Copyright (c) 2017, Benjamin Landers diff --git a/src/rars/riscv/instructions/REMU.java b/src/rars/riscv/instructions/REMU.java index b7f517e1..2c22e437 100644 --- a/src/rars/riscv/instructions/REMU.java +++ b/src/rars/riscv/instructions/REMU.java @@ -1,7 +1,5 @@ package rars.riscv.instructions; -import rars.riscv.hardware.ControlAndStatusRegisterFile; - /* Copyright (c) 2017, Benjamin Landers diff --git a/src/rars/riscv/instructions/REMUW.java b/src/rars/riscv/instructions/REMUW.java index 5e9d4da4..c7dda11d 100644 --- a/src/rars/riscv/instructions/REMUW.java +++ b/src/rars/riscv/instructions/REMUW.java @@ -3,6 +3,6 @@ public class REMUW extends ArithmeticW { public REMUW() { super("remuw t1,t2,t3", "Remainder: set t1 to the remainder of t2/t3 using unsigned division limited to 32 bits", - "0000001", "111",new REMU()); + "0000001", "111", new REMU()); } -} \ No newline at end of file +} diff --git a/src/rars/riscv/instructions/REMW.java b/src/rars/riscv/instructions/REMW.java index a6f31f61..43d37ad6 100644 --- a/src/rars/riscv/instructions/REMW.java +++ b/src/rars/riscv/instructions/REMW.java @@ -3,6 +3,6 @@ public class REMW extends ArithmeticW { public REMW() { super("remw t1,t2,t3", "Remainder: set t1 to the remainder of t2/t3 using only the lower 32 bits", - "0000001", "110",new REM()); + "0000001", "110", new REM()); } -} \ No newline at end of file +} diff --git a/src/rars/riscv/instructions/SB.java b/src/rars/riscv/instructions/SB.java index bc8f3446..ea31292a 100644 --- a/src/rars/riscv/instructions/SB.java +++ b/src/rars/riscv/instructions/SB.java @@ -2,6 +2,7 @@ import rars.Globals; import rars.riscv.hardware.AddressErrorException; +import rars.riscv.hardware.ReservationTable.bitWidth; /* Copyright (c) 2017, Benjamin Landers @@ -35,10 +36,8 @@ public SB() { super("sb t1, -100(t2)", "Store byte : Store the low-order 8 bits of t1 into the effective memory byte address", "000"); } - public void store(int address, long data) throws AddressErrorException { + public void store(int address, long data, int hart) throws AddressErrorException { + Globals.reservationTables.unreserveAddress(hart + 1, address & ~0b11, bitWidth.word); Globals.memory.setByte(address, (int)data & 0x000000FF); } } - - - diff --git a/src/rars/riscv/instructions/SCD.java b/src/rars/riscv/instructions/SCD.java new file mode 100644 index 00000000..474da212 --- /dev/null +++ b/src/rars/riscv/instructions/SCD.java @@ -0,0 +1,38 @@ +package rars.riscv.instructions; + +import rars.Globals; +import rars.riscv.hardware.AddressErrorException; +import rars.ProgramStatement; +import rars.SimulationException; +import rars.riscv.hardware.RegisterFile; +import rars.riscv.hardware.ReservationTable.bitWidth; + +public class SCD extends Atomic { + public SCD() { + super("sc.d t0, t1, (t2)", "Try to store t1 to contents of effective memory word address, sets t0 to store attempt result", "011", "00011", true); + } + + public void simulate(ProgramStatement statement) throws SimulationException { + int[] operands = statement.getOperands(); + int hart = statement.getCurrentHart(); + try { + if (hart == -1) { + long result = store(RegisterFile.getValue(operands[2]), RegisterFile.getValue(operands[1]), hart); + RegisterFile.updateRegister(operands[0], result); + } else { + long result = store(RegisterFile.getValue(operands[2], hart), RegisterFile.getValue(operands[1], hart), hart); + RegisterFile.updateRegister(operands[0], result, hart); + } + } catch (AddressErrorException e) { + throw new SimulationException(statement, e); + } + } + + private long store(int address, int value, int hart) throws AddressErrorException { + if (Globals.reservationTables.unreserveAddress(hart + 1, address, bitWidth.doubleWord)) { + Globals.memory.setDoubleWord(address, value); + return 0; + } + return 1; + } +} diff --git a/src/rars/riscv/instructions/SCW.java b/src/rars/riscv/instructions/SCW.java new file mode 100644 index 00000000..0d058d7c --- /dev/null +++ b/src/rars/riscv/instructions/SCW.java @@ -0,0 +1,38 @@ +package rars.riscv.instructions; + +import rars.Globals; +import rars.riscv.hardware.AddressErrorException; +import rars.ProgramStatement; +import rars.SimulationException; +import rars.riscv.hardware.RegisterFile; +import rars.riscv.hardware.ReservationTable.bitWidth; + +public class SCW extends Atomic { + public SCW() { + super("sc.w t0, t1, (t2)", "Try to store t1 to contents of effective memory word address, sets t0 to store attempt result", "010", "00011"); + } + + public void simulate(ProgramStatement statement) throws SimulationException { + int[] operands = statement.getOperands(); + int hart = statement.getCurrentHart(); + try { + if (hart == - 1) { + int result = store(RegisterFile.getValue(operands[2]), RegisterFile.getValue(operands[1]), hart); + RegisterFile.updateRegister(operands[0], result); + } else { + int result = store(RegisterFile.getValue(operands[2], hart), RegisterFile.getValue(operands[1], hart), hart); + RegisterFile.updateRegister(operands[0], result, hart); + } + } catch (AddressErrorException e) { + throw new SimulationException(statement, e); + } + } + + private int store(int address, int value, int hart) throws AddressErrorException { + if (Globals.reservationTables.unreserveAddress(hart + 1, address, bitWidth.word)) { + Globals.memory.setWord(address, value); + return 0; + } + return 1; + } +} diff --git a/src/rars/riscv/instructions/SD.java b/src/rars/riscv/instructions/SD.java index 20228068..bddaa0de 100644 --- a/src/rars/riscv/instructions/SD.java +++ b/src/rars/riscv/instructions/SD.java @@ -2,16 +2,15 @@ import rars.Globals; import rars.riscv.hardware.AddressErrorException; +import rars.riscv.hardware.ReservationTable.bitWidth; public class SD extends Store { public SD() { super("sd t1, -100(t2)", "Store double word : Store contents of t1 into effective memory double word address", "011",true); } - public void store(int address, long data) throws AddressErrorException { + public void store(int address, long data, int hart) throws AddressErrorException { + Globals.reservationTables.unreserveAddress(hart + 1, address, bitWidth.doubleWord); Globals.memory.setDoubleWord(address, data); } } - - - diff --git a/src/rars/riscv/instructions/SH.java b/src/rars/riscv/instructions/SH.java index 829b6cba..de249dd5 100644 --- a/src/rars/riscv/instructions/SH.java +++ b/src/rars/riscv/instructions/SH.java @@ -2,6 +2,7 @@ import rars.Globals; import rars.riscv.hardware.AddressErrorException; +import rars.riscv.hardware.ReservationTable.bitWidth; /* Copyright (c) 2017, Benjamin Landers @@ -35,10 +36,8 @@ public SH() { super("sh t1, -100(t2)", "Store halfword : Store the low-order 16 bits of t1 into the effective memory halfword address", "001"); } - public void store(int address, long data) throws AddressErrorException { - Globals.memory.setHalf(address, (int)data & 0x0000FFFF); + public void store(int address, long data, int hart) throws AddressErrorException { + Globals.reservationTables.unreserveAddress(hart + 1, address & ~0b11, bitWidth.word); + Globals.memory.setHalf(address, (int) data & 0x0000FFFF); } } - - - diff --git a/src/rars/riscv/instructions/SW.java b/src/rars/riscv/instructions/SW.java index 73b3ca65..6fbd4aa8 100644 --- a/src/rars/riscv/instructions/SW.java +++ b/src/rars/riscv/instructions/SW.java @@ -2,6 +2,7 @@ import rars.Globals; import rars.riscv.hardware.AddressErrorException; +import rars.riscv.hardware.ReservationTable.bitWidth; /* Copyright (c) 2017, Benjamin Landers @@ -35,10 +36,8 @@ public SW() { super("sw t1, -100(t2)", "Store word : Store contents of t1 into effective memory word address", "010"); } - public void store(int address, long data) throws AddressErrorException { + public void store(int address, long data, int hart) throws AddressErrorException { + Globals.reservationTables.unreserveAddress(hart + 1, address, bitWidth.word); Globals.memory.setWord(address, (int) data); } } - - - diff --git a/src/rars/riscv/instructions/Store.java b/src/rars/riscv/instructions/Store.java index 7f309041..ddab202e 100644 --- a/src/rars/riscv/instructions/Store.java +++ b/src/rars/riscv/instructions/Store.java @@ -47,14 +47,21 @@ public Store(String usage, String description, String funct) { } public Store(String usage, String description, String funct, boolean rv64) { super(usage, description, BasicInstructionFormat.S_FORMAT, - "sssssss fffff ttttt " + funct + " sssss 0100011",rv64); + "sssssss fffff ttttt " + funct + " sssss 0100011", rv64); } public void simulate(ProgramStatement statement) throws SimulationException { int[] operands = statement.getOperands(); + int hart = statement.getCurrentHart(); operands[1] = (operands[1] << 20) >> 20; try { - store(RegisterFile.getValue(operands[2]) + operands[1], RegisterFile.getValueLong(operands[0])); + int base = (hart == -1) + ? RegisterFile.getValue(operands[2]) + : RegisterFile.getValue(operands[2], hart); + long value = (hart == -1) + ? RegisterFile.getValueLong(operands[0]) + : RegisterFile.getValueLong(operands[0], hart); + store(base + operands[1], value, hart); } catch (AddressErrorException e) { throw new SimulationException(statement, e); } @@ -63,6 +70,7 @@ public void simulate(ProgramStatement statement) throws SimulationException { /** * @param address the address to store to * @param value the value to store + * @param hart the hart to store from */ - protected abstract void store(int address, long value) throws AddressErrorException; -} \ No newline at end of file + protected abstract void store(int address, long value, int hart) throws AddressErrorException; +} diff --git a/src/rars/riscv/instructions/URET.java b/src/rars/riscv/instructions/URET.java index 2c142e3d..a2e96f33 100644 --- a/src/rars/riscv/instructions/URET.java +++ b/src/rars/riscv/instructions/URET.java @@ -39,13 +39,25 @@ public URET() { } public void simulate(ProgramStatement statement) { - boolean upie = (ControlAndStatusRegisterFile.getValue("ustatus") & 0x10) == 0x10; - ControlAndStatusRegisterFile.clearRegister("ustatus", 0x10); // Clear UPIE - if (upie) { // Set UIE to UPIE - ControlAndStatusRegisterFile.orRegister("ustatus", 0x1); + int hart = statement.getCurrentHart(); + if (hart == -1) { + boolean upie = (ControlAndStatusRegisterFile.getValue("ustatus") & 0x10) == 0x10; + ControlAndStatusRegisterFile.clearRegister("ustatus", 0x10); // Clear UPIE + if (upie) { // Set UIE to UPIE + ControlAndStatusRegisterFile.orRegister("ustatus", 0x1); + } else { + ControlAndStatusRegisterFile.clearRegister("ustatus", 0x1); + } + RegisterFile.setProgramCounter(ControlAndStatusRegisterFile.getValue("uepc")); } else { - ControlAndStatusRegisterFile.clearRegister("ustatus", 0x1); + boolean upie = (ControlAndStatusRegisterFile.getValue("ustatus", hart) & 0x10) == 0x10; + ControlAndStatusRegisterFile.clearRegister("ustatus", 0x10, hart); // Clear UPIE + if (upie) { // Set UIE to UPIE + ControlAndStatusRegisterFile.orRegister("ustatus", 0x1, hart); + } else { + ControlAndStatusRegisterFile.clearRegister("ustatus", 0x1, hart); + } + RegisterFile.setProgramCounter(ControlAndStatusRegisterFile.getValue("uepc", hart), hart); } - RegisterFile.setProgramCounter(ControlAndStatusRegisterFile.getValue("uepc")); } } diff --git a/src/rars/riscv/syscalls/NullString.java b/src/rars/riscv/syscalls/NullString.java index bfd26418..d993ec41 100644 --- a/src/rars/riscv/syscalls/NullString.java +++ b/src/rars/riscv/syscalls/NullString.java @@ -58,7 +58,10 @@ public static String get(ProgramStatement statement) throws ExitingException { * @throws ExitingException if it hits a #AddressErrorException */ public static String get(ProgramStatement statement, String reg) throws ExitingException { - int byteAddress = RegisterFile.getValue(reg); + int hart = statement.getCurrentHart(); + int byteAddress = hart == -1 + ? RegisterFile.getValue(reg) + : RegisterFile.getValue(reg, hart); ArrayList utf8BytesList = new ArrayList<>(); // Need an array to hold bytes try { utf8BytesList.add((byte) Globals.memory.getByte(byteAddress)); diff --git a/src/rars/riscv/syscalls/RandomStreams.java b/src/rars/riscv/syscalls/RandomStreams.java index b4718327..ae98f7a8 100644 --- a/src/rars/riscv/syscalls/RandomStreams.java +++ b/src/rars/riscv/syscalls/RandomStreams.java @@ -61,5 +61,15 @@ static Random get(String reg) { RandomStreams.randomStreams.put(index, stream); } return stream; + + } + static Random get(String reg, int hart) { + int index = RegisterFile.getValue(reg, hart); + Random stream = randomStreams.get(index); + if (stream == null) { + stream = new Random(); // create a non-seeded stream + RandomStreams.randomStreams.put(index, stream); + } + return stream; } } \ No newline at end of file diff --git a/src/rars/riscv/syscalls/SyscallClose.java b/src/rars/riscv/syscalls/SyscallClose.java index 1f96be13..9960c455 100644 --- a/src/rars/riscv/syscalls/SyscallClose.java +++ b/src/rars/riscv/syscalls/SyscallClose.java @@ -39,6 +39,9 @@ public SyscallClose() { } public void simulate(ProgramStatement statement) { - SystemIO.closeFile(RegisterFile.getValue("a0")); + if(statement.getCurrentHart() == -1) + SystemIO.closeFile(RegisterFile.getValue("a0")); + else + SystemIO.closeFile(RegisterFile.getValue("a0", statement.getCurrentHart())); } } \ No newline at end of file diff --git a/src/rars/riscv/syscalls/SyscallConfirmDialog.java b/src/rars/riscv/syscalls/SyscallConfirmDialog.java index b4736892..b3c15eec 100644 --- a/src/rars/riscv/syscalls/SyscallConfirmDialog.java +++ b/src/rars/riscv/syscalls/SyscallConfirmDialog.java @@ -44,7 +44,10 @@ public SyscallConfirmDialog() { public void simulate(ProgramStatement statement) throws ExitingException { String message = NullString.get(statement); - RegisterFile.updateRegister("a0", JOptionPane.showConfirmDialog(null, message)); + if(statement.getCurrentHart() == -1) + RegisterFile.updateRegister("a0", JOptionPane.showConfirmDialog(null, message)); + else + RegisterFile.updateRegister("a0", JOptionPane.showConfirmDialog(null, message), statement.getCurrentHart()); } diff --git a/src/rars/riscv/syscalls/SyscallExit2.java b/src/rars/riscv/syscalls/SyscallExit2.java index 26cdf76f..dab8f028 100644 --- a/src/rars/riscv/syscalls/SyscallExit2.java +++ b/src/rars/riscv/syscalls/SyscallExit2.java @@ -40,7 +40,10 @@ public SyscallExit2() { } public void simulate(ProgramStatement statement) throws ExitingException { - Globals.exitCode = RegisterFile.getValue("a0"); + if(statement.getCurrentHart() == -1) + Globals.exitCode = RegisterFile.getValue("a0"); + else + Globals.exitCode = RegisterFile.getValue("a0", statement.getCurrentHart()); throw new ExitingException(); // empty error list } } \ No newline at end of file diff --git a/src/rars/riscv/syscalls/SyscallGetCWD.java b/src/rars/riscv/syscalls/SyscallGetCWD.java index 7c51ad63..d60a6f72 100644 --- a/src/rars/riscv/syscalls/SyscallGetCWD.java +++ b/src/rars/riscv/syscalls/SyscallGetCWD.java @@ -45,24 +45,48 @@ public SyscallGetCWD() { public void simulate(ProgramStatement statement) throws ExitingException { String path = System.getProperty("user.dir"); - int buf = RegisterFile.getValue("a0"); - int length = RegisterFile.getValue("a1"); + int hart = statement.getCurrentHart(); + if(hart == -1){ + int buf = RegisterFile.getValue("a0"); + int length = RegisterFile.getValue("a1"); - byte[] utf8BytesList = path.getBytes(StandardCharsets.UTF_8); - if(length < utf8BytesList.length+1){ - // This should be -34 (ERANGE) for compatability with spike, but until other syscalls are ready with compatable - // error codes, lets keep internal consitency. - RegisterFile.updateRegister("a0",-1); - return; + byte[] utf8BytesList = path.getBytes(StandardCharsets.UTF_8); + if(length < utf8BytesList.length+1){ + // This should be -34 (ERANGE) for compatability with spike, but until other syscalls are ready with compatable + // error codes, lets keep internal consitency. + RegisterFile.updateRegister("a0",-1); + return; + } + try { + for (int index = 0; index < utf8BytesList.length; index++) { + Globals.memory.setByte(buf + index, + utf8BytesList[index]); + } + Globals.memory.setByte(buf + utf8BytesList.length, 0); + } catch (AddressErrorException e) { + throw new ExitingException(statement, e); + } } - try { - for (int index = 0; index < utf8BytesList.length; index++) { - Globals.memory.setByte(buf + index, - utf8BytesList[index]); + else{ + int buf = RegisterFile.getValue("a0", hart); + int length = RegisterFile.getValue("a1", hart); + + byte[] utf8BytesList = path.getBytes(StandardCharsets.UTF_8); + if(length < utf8BytesList.length+1){ + // This should be -34 (ERANGE) for compatability with spike, but until other syscalls are ready with compatable + // error codes, lets keep internal consitency. + RegisterFile.updateRegister("a0",-1, hart); + return; + } + try { + for (int index = 0; index < utf8BytesList.length; index++) { + Globals.memory.setByte(buf + index, + utf8BytesList[index]); + } + Globals.memory.setByte(buf + utf8BytesList.length, 0); + } catch (AddressErrorException e) { + throw new ExitingException(statement, e); } - Globals.memory.setByte(buf + utf8BytesList.length, 0); - } catch (AddressErrorException e) { - throw new ExitingException(statement, e); } } } \ No newline at end of file diff --git a/src/rars/riscv/syscalls/SyscallInputDialogDouble.java b/src/rars/riscv/syscalls/SyscallInputDialogDouble.java index a51fbd00..1e393460 100644 --- a/src/rars/riscv/syscalls/SyscallInputDialogDouble.java +++ b/src/rars/riscv/syscalls/SyscallInputDialogDouble.java @@ -63,9 +63,13 @@ public void simulate(ProgramStatement statement) throws ExitingException { // -2: Cancel was chosen // -3: OK was chosen but no data had been input into field - + int hart = statement.getCurrentHart(); String message = new String(); // = ""; - int byteAddress = RegisterFile.getValue(4); + int byteAddress; + if(hart == -1) + byteAddress= RegisterFile.getValue(4); + else + byteAddress = RegisterFile.getValue(4, hart); char ch[] = {' '}; // Need an array to convert to String try { ch[0] = (char) Globals.memory.getByte(byteAddress); @@ -85,26 +89,49 @@ public void simulate(ProgramStatement statement) throws ExitingException { // means that OK was chosen but no string was input. String inputValue = null; inputValue = JOptionPane.showInputDialog(message); - - try { - FloatingPointRegisterFile.updateRegisterLong(0, 0); // set $f0 to zero - if (inputValue == null) // Cancel was chosen + if(hart == -1){ + try { + FloatingPointRegisterFile.updateRegisterLong(0, 0); // set $f0 to zero + if (inputValue == null) // Cancel was chosen + { + RegisterFile.updateRegister("a1", -2); // set $a1 to -2 flag + } else if (inputValue.length() == 0) // OK was chosen but there was no input + { + RegisterFile.updateRegister("a1", -3); // set $a1 to -3 flag + } else { + double doubleValue = Double.parseDouble(inputValue); + + // Successful parse of valid input data + FloatingPointRegisterFile.updateRegisterLong(10, Double.doubleToRawLongBits(doubleValue)); + RegisterFile.updateRegister("a1", 0); // set $a1 to valid flag + + } + }catch (NumberFormatException e) // Unsuccessful parse of input data { - RegisterFile.updateRegister("a1", -2); // set $a1 to -2 flag - } else if (inputValue.length() == 0) // OK was chosen but there was no input + RegisterFile.updateRegister("a1", -1); // set $a1 to -1 flag + } + } + else{ + try { + FloatingPointRegisterFile.updateRegisterLong(0, 0, hart); // set $f0 to zero + if (inputValue == null) // Cancel was chosen + { + RegisterFile.updateRegister("a1", -2, hart); // set $a1 to -2 flag + } else if (inputValue.length() == 0) // OK was chosen but there was no input + { + RegisterFile.updateRegister("a1", -3, hart); // set $a1 to -3 flag + } else { + double doubleValue = Double.parseDouble(inputValue); + + // Successful parse of valid input data + FloatingPointRegisterFile.updateRegisterLong(10, Double.doubleToRawLongBits(doubleValue), hart); + RegisterFile.updateRegister("a1", 0, hart); // set $a1 to valid flag + + } + }catch (NumberFormatException e) // Unsuccessful parse of input data { - RegisterFile.updateRegister("a1", -3); // set $a1 to -3 flag - } else { - double doubleValue = Double.parseDouble(inputValue); - - // Successful parse of valid input data - FloatingPointRegisterFile.updateRegisterLong(10, Double.doubleToRawLongBits(doubleValue)); - RegisterFile.updateRegister("a1", 0); // set $a1 to valid flag - + RegisterFile.updateRegister("a1", -1, hart); // set $a1 to -1 flag } - }catch (NumberFormatException e) // Unsuccessful parse of input data - { - RegisterFile.updateRegister("a1", -1); // set $a1 to -1 flag } } } diff --git a/src/rars/riscv/syscalls/SyscallInputDialogFloat.java b/src/rars/riscv/syscalls/SyscallInputDialogFloat.java index 3437b2f1..ca0eab93 100644 --- a/src/rars/riscv/syscalls/SyscallInputDialogFloat.java +++ b/src/rars/riscv/syscalls/SyscallInputDialogFloat.java @@ -62,31 +62,59 @@ public void simulate(ProgramStatement statement) throws ExitingException { // An empty string returned (that is, inputValue.length() of zero) // means that OK was chosen but no string was input. String inputValue = null; + int hart = statement.getCurrentHart(); inputValue = JOptionPane.showInputDialog(message); + if(hart == -1){ + try { + FloatingPointRegisterFile.setRegisterToFloat(0, (float) 0.0); // set f0 to zero + if (inputValue == null) // Cancel was chosen + { + RegisterFile.updateRegister("a1", -2); + } else if (inputValue.length() == 0) // OK was chosen but there was no input + { + RegisterFile.updateRegister("a1", -3); + } else { - try { - FloatingPointRegisterFile.setRegisterToFloat(0, (float) 0.0); // set f0 to zero - if (inputValue == null) // Cancel was chosen - { - RegisterFile.updateRegister("a1", -2); - } else if (inputValue.length() == 0) // OK was chosen but there was no input - { - RegisterFile.updateRegister("a1", -3); - } else { + float floatValue = Float.parseFloat(inputValue); - float floatValue = Float.parseFloat(inputValue); + //System.out.println("SyscallInputDialogFloat: floatValue is " + floatValue); - //System.out.println("SyscallInputDialogFloat: floatValue is " + floatValue); + // Successful parse of valid input data + FloatingPointRegisterFile.setRegisterToFloat(0, floatValue); // set f0 to input data + RegisterFile.updateRegister("a1", 0); // set to valid flag - // Successful parse of valid input data - FloatingPointRegisterFile.setRegisterToFloat(0, floatValue); // set f0 to input data - RegisterFile.updateRegister("a1", 0); // set to valid flag + } + } catch (NumberFormatException e) // Unsuccessful parse of input data + { + RegisterFile.updateRegister("a1", -1); } + } + else{ + try { + FloatingPointRegisterFile.setRegisterToFloat(0, (float) 0.0, hart); // set f0 to zero + if (inputValue == null) // Cancel was chosen + { + RegisterFile.updateRegister("a1", -2, hart); + } else if (inputValue.length() == 0) // OK was chosen but there was no input + { + RegisterFile.updateRegister("a1", -3, hart); + } else { + + float floatValue = Float.parseFloat(inputValue); - } catch (NumberFormatException e) // Unsuccessful parse of input data - { - RegisterFile.updateRegister("a1", -1); + //System.out.println("SyscallInputDialogFloat: floatValue is " + floatValue); + + // Successful parse of valid input data + FloatingPointRegisterFile.setRegisterToFloat(0, floatValue, hart); // set f0 to input data + RegisterFile.updateRegister("a1", 0, hart); // set to valid flag + + } + + } catch (NumberFormatException e) // Unsuccessful parse of input data + { + RegisterFile.updateRegister("a1", -1, hart); + } } } } diff --git a/src/rars/riscv/syscalls/SyscallInputDialogInt.java b/src/rars/riscv/syscalls/SyscallInputDialogInt.java index ffac8081..0305cb48 100644 --- a/src/rars/riscv/syscalls/SyscallInputDialogInt.java +++ b/src/rars/riscv/syscalls/SyscallInputDialogInt.java @@ -62,29 +62,56 @@ public void simulate(ProgramStatement statement) throws ExitingException { // means that OK was chosen but no string was input. String inputValue = null; inputValue = JOptionPane.showInputDialog(message); - if (inputValue == null) // Cancel was chosen - { - RegisterFile.updateRegister("a0", 0); - RegisterFile.updateRegister("a1", -2); - } else if (inputValue.length() == 0) // OK was chosen but there was no input - { - RegisterFile.updateRegister("a0", 0); - RegisterFile.updateRegister("a1", -3); - } else { - try { - int i = Integer.parseInt(inputValue); - - // Successful parse of valid input data - RegisterFile.updateRegister("a0", i); // set to the data read - RegisterFile.updateRegister("a1", 0); // set to valid flag - } catch (NumberFormatException e) { - // Unsuccessful parse of input data + int hart = statement.getCurrentHart(); + if(hart == -1){ + if (inputValue == null) // Cancel was chosen + { RegisterFile.updateRegister("a0", 0); - RegisterFile.updateRegister("a1", -1); - - } - - } // end else + RegisterFile.updateRegister("a1", -2); + } else if (inputValue.length() == 0) // OK was chosen but there was no input + { + RegisterFile.updateRegister("a0", 0); + RegisterFile.updateRegister("a1", -3); + } else { + try { + int i = Integer.parseInt(inputValue); + + // Successful parse of valid input data + RegisterFile.updateRegister("a0", i); // set to the data read + RegisterFile.updateRegister("a1", 0); // set to valid flag + } catch (NumberFormatException e) { + // Unsuccessful parse of input data + RegisterFile.updateRegister("a0", 0); + RegisterFile.updateRegister("a1", -1); + + } + + } // end else + } + else{ + if (inputValue == null) // Cancel was chosen + { + RegisterFile.updateRegister("a0", 0, hart); + RegisterFile.updateRegister("a1", -2, hart); + } else if (inputValue.length() == 0) // OK was chosen but there was no input + { + RegisterFile.updateRegister("a0", 0, hart); + RegisterFile.updateRegister("a1", -3, hart); + } else { + try { + int i = Integer.parseInt(inputValue); + + // Successful parse of valid input data + RegisterFile.updateRegister("a0", i, hart); // set to the data read + RegisterFile.updateRegister("a1", 0, hart); // set to valid flag + } catch (NumberFormatException e) { + // Unsuccessful parse of input data + RegisterFile.updateRegister("a0", 0, hart); + RegisterFile.updateRegister("a1", -1, hart); + } + + } // end else + } } diff --git a/src/rars/riscv/syscalls/SyscallInputDialogString.java b/src/rars/riscv/syscalls/SyscallInputDialogString.java index 209e0c7a..7c609650 100644 --- a/src/rars/riscv/syscalls/SyscallInputDialogString.java +++ b/src/rars/riscv/syscalls/SyscallInputDialogString.java @@ -71,44 +71,85 @@ public void simulate(ProgramStatement statement) throws ExitingException { // means that OK was chosen but no string was input. String inputString = null; inputString = JOptionPane.showInputDialog(message); - int byteAddress = RegisterFile.getValue("a1"); // byteAddress of string is in a1 - int maxLength = RegisterFile.getValue("a2"); // input buffer size for input string is in a2 - - try { - if (inputString == null) // Cancel was chosen - { - RegisterFile.updateRegister("a1", -2); - } else if (inputString.length() == 0) // OK was chosen but there was no input - { - RegisterFile.updateRegister("a1", -3); - } else { - byte[] utf8BytesList = inputString.getBytes(StandardCharsets.UTF_8); - // The buffer will contain characters, a '\n' character, and the null character - // Copy the input data to buffer as space permits - int stringLength = Math.min(maxLength-1, utf8BytesList.length); - for (int index = 0; index < stringLength; index++) { - Globals.memory.setByte(byteAddress+ index, - utf8BytesList[index]); - } - if (stringLength < maxLength-1) { - Globals.memory.setByte(byteAddress + stringLength, '\n'); - stringLength++; - } - Globals.memory.setByte(byteAddress + stringLength, 0); - - if (utf8BytesList.length > maxLength - 1) { - // length of the input string exceeded the specified maximum - RegisterFile.updateRegister("a1", -4); + int hart = statement.getCurrentHart(); + if(hart == -1){ + int byteAddress = RegisterFile.getValue("a1"); // byteAddress of string is in a1 + int maxLength = RegisterFile.getValue("a2"); // input buffer size for input string is in a2 + + try { + if (inputString == null) // Cancel was chosen + { + RegisterFile.updateRegister("a1", -2); + } else if (inputString.length() == 0) // OK was chosen but there was no input + { + RegisterFile.updateRegister("a1", -3); } else { - RegisterFile.updateRegister("a1", 0); - } - } // end else - - } // end try - catch (AddressErrorException e) { - throw new ExitingException(statement, e); + byte[] utf8BytesList = inputString.getBytes(StandardCharsets.UTF_8); + // The buffer will contain characters, a '\n' character, and the null character + // Copy the input data to buffer as space permits + int stringLength = Math.min(maxLength-1, utf8BytesList.length); + for (int index = 0; index < stringLength; index++) { + Globals.memory.setByte(byteAddress+ index, + utf8BytesList[index]); + } + if (stringLength < maxLength-1) { + Globals.memory.setByte(byteAddress + stringLength, '\n'); + stringLength++; + } + Globals.memory.setByte(byteAddress + stringLength, 0); + + if (utf8BytesList.length > maxLength - 1) { + // length of the input string exceeded the specified maximum + RegisterFile.updateRegister("a1", -4); + } else { + RegisterFile.updateRegister("a1", 0); + } + } // end else + + } // end try + catch (AddressErrorException e) { + throw new ExitingException(statement, e); + } + } + else{ + int byteAddress = RegisterFile.getValue("a1", hart); // byteAddress of string is in a1 + int maxLength = RegisterFile.getValue("a2", hart); // input buffer size for input string is in a2 + + try { + if (inputString == null) // Cancel was chosen + { + RegisterFile.updateRegister("a1", -2, hart); + } else if (inputString.length() == 0) // OK was chosen but there was no input + { + RegisterFile.updateRegister("a1", -3, hart); + } else { + byte[] utf8BytesList = inputString.getBytes(StandardCharsets.UTF_8); + // The buffer will contain characters, a '\n' character, and the null character + // Copy the input data to buffer as space permits + int stringLength = Math.min(maxLength-1, utf8BytesList.length); + for (int index = 0; index < stringLength; index++) { + Globals.memory.setByte(byteAddress+ index, + utf8BytesList[index]); + } + if (stringLength < maxLength-1) { + Globals.memory.setByte(byteAddress + stringLength, '\n'); + stringLength++; + } + Globals.memory.setByte(byteAddress + stringLength, 0); + + if (utf8BytesList.length > maxLength - 1) { + // length of the input string exceeded the specified maximum + RegisterFile.updateRegister("a1", -4, hart); + } else { + RegisterFile.updateRegister("a1", 0, hart); + } + } // end else + + } // end try + catch (AddressErrorException e) { + throw new ExitingException(statement, e); + } } - } diff --git a/src/rars/riscv/syscalls/SyscallLSeek.java b/src/rars/riscv/syscalls/SyscallLSeek.java index cd0812f6..db0426a5 100644 --- a/src/rars/riscv/syscalls/SyscallLSeek.java +++ b/src/rars/riscv/syscalls/SyscallLSeek.java @@ -42,9 +42,18 @@ public SyscallLSeek() { } public void simulate(ProgramStatement statement) throws ExitingException { + int hart = statement.getCurrentHart(); + if(hart == -1){ int result = SystemIO.seek(RegisterFile.getValue("a0"), RegisterFile.getValue("a1"), RegisterFile.getValue("a2")); RegisterFile.updateRegister("a0", result); + } + else{ + int result = SystemIO.seek(RegisterFile.getValue("a0", hart), + RegisterFile.getValue("a1", hart), + RegisterFile.getValue("a2", hart)); + RegisterFile.updateRegister("a0", result, hart); + } } } \ No newline at end of file diff --git a/src/rars/riscv/syscalls/SyscallMessageDialog.java b/src/rars/riscv/syscalls/SyscallMessageDialog.java index db2c60bd..1baacad3 100644 --- a/src/rars/riscv/syscalls/SyscallMessageDialog.java +++ b/src/rars/riscv/syscalls/SyscallMessageDialog.java @@ -45,7 +45,11 @@ public SyscallMessageDialog() { public void simulate(ProgramStatement statement) throws ExitingException { // Display the dialog. - int msgType = RegisterFile.getValue("a1"); + int hart = statement.getCurrentHart(), msgType; + if(hart == -1) + msgType = RegisterFile.getValue("a1"); + else + msgType = RegisterFile.getValue("a1", hart); if (msgType < 0 || msgType > 3) msgType = -1; // See values in http://java.sun.com/j2se/1.5.0/docs/api/constant-values.html JOptionPane.showMessageDialog(null, NullString.get(statement), null, msgType); diff --git a/src/rars/riscv/syscalls/SyscallMessageDialogDouble.java b/src/rars/riscv/syscalls/SyscallMessageDialogDouble.java index 7980f8f7..d48e9cec 100644 --- a/src/rars/riscv/syscalls/SyscallMessageDialogDouble.java +++ b/src/rars/riscv/syscalls/SyscallMessageDialogDouble.java @@ -57,7 +57,11 @@ public SyscallMessageDialogDouble() { public void simulate(ProgramStatement statement) throws ExitingException { // TODO: maybe refactor this, other null strings are handled in a central place now String message = new String(); // = ""; - int byteAddress = RegisterFile.getValue("a0"); + int byteAddress; + if(statement.getCurrentHart() == -1) + byteAddress = RegisterFile.getValue("a0"); + else + byteAddress = RegisterFile.getValue("a0", statement.getCurrentHart()); char ch[] = {' '}; // Need an array to convert to String try { ch[0] = (char) Globals.memory.getByte(byteAddress); @@ -70,10 +74,15 @@ public void simulate(ProgramStatement statement) throws ExitingException { } catch (AddressErrorException e) { throw new ExitingException(statement, e); } - - JOptionPane.showMessageDialog(null, - message + Double.longBitsToDouble(FloatingPointRegisterFile.getValueLong(10)), - null, - JOptionPane.INFORMATION_MESSAGE); + if(statement.getCurrentHart() == -1) + JOptionPane.showMessageDialog(null, + message + Double.longBitsToDouble(FloatingPointRegisterFile.getValueLong(10)), + null, + JOptionPane.INFORMATION_MESSAGE); + else + JOptionPane.showMessageDialog(null, + message + Double.longBitsToDouble(FloatingPointRegisterFile.getValueLong(10, statement.getCurrentHart())), + null, + JOptionPane.INFORMATION_MESSAGE); } } diff --git a/src/rars/riscv/syscalls/SyscallMessageDialogFloat.java b/src/rars/riscv/syscalls/SyscallMessageDialogFloat.java index 83822d9d..fe3e579c 100644 --- a/src/rars/riscv/syscalls/SyscallMessageDialogFloat.java +++ b/src/rars/riscv/syscalls/SyscallMessageDialogFloat.java @@ -46,8 +46,14 @@ public void simulate(ProgramStatement statement) throws ExitingException { String message = NullString.get(statement); // Display the dialog. - JOptionPane.showMessageDialog(null, - message + Float.toString(FloatingPointRegisterFile.getFloatFromRegister("fa1")), + if(statement.getCurrentHart() == -1) + JOptionPane.showMessageDialog(null, + message + Float.toString(FloatingPointRegisterFile.getFloatFromRegister("fa1")), + null, + JOptionPane.INFORMATION_MESSAGE); + else + JOptionPane.showMessageDialog(null, + message + Float.toString(FloatingPointRegisterFile.getFloatFromRegister("fa1", statement.getCurrentHart())), null, JOptionPane.INFORMATION_MESSAGE); } diff --git a/src/rars/riscv/syscalls/SyscallMessageDialogInt.java b/src/rars/riscv/syscalls/SyscallMessageDialogInt.java index daaeb97f..b8eecb80 100644 --- a/src/rars/riscv/syscalls/SyscallMessageDialogInt.java +++ b/src/rars/riscv/syscalls/SyscallMessageDialogInt.java @@ -46,8 +46,14 @@ public void simulate(ProgramStatement statement) throws ExitingException { String message = NullString.get(statement); // Display the dialog. - JOptionPane.showMessageDialog(null, - message + Integer.toString(RegisterFile.getValue("a1")), + if(statement.getCurrentHart() == -1) + JOptionPane.showMessageDialog(null, + message + Integer.toString(RegisterFile.getValue("a1")), + null, + JOptionPane.INFORMATION_MESSAGE); + else + JOptionPane.showMessageDialog(null, + message + Integer.toString(RegisterFile.getValue("a1", statement.getCurrentHart())), null, JOptionPane.INFORMATION_MESSAGE); } diff --git a/src/rars/riscv/syscalls/SyscallMidiOut.java b/src/rars/riscv/syscalls/SyscallMidiOut.java index f2bfd0bc..dfd32d3e 100644 --- a/src/rars/riscv/syscalls/SyscallMidiOut.java +++ b/src/rars/riscv/syscalls/SyscallMidiOut.java @@ -58,10 +58,17 @@ public SyscallMidiOut() { * use the range 1-128. */ public void simulate(ProgramStatement statement) { - int pitch = RegisterFile.getValue("a0"); - int duration = RegisterFile.getValue("a1"); - int instrument = RegisterFile.getValue("a2"); - int volume = RegisterFile.getValue("a3"); + int hart = statement.getCurrentHart(); + int pitch, duration , instrument, volume; + if(hart == -1){ + pitch = RegisterFile.getValue("a0"); duration = RegisterFile.getValue("a1"); instrument = RegisterFile.getValue("a2"); + volume = RegisterFile.getValue("a3"); + } + else{ + pitch = RegisterFile.getValue("a0", hart); duration = RegisterFile.getValue("a1", hart) ; + instrument = RegisterFile.getValue("a2", hart); + volume = RegisterFile.getValue("a3", hart); + } if (pitch < rangeLowEnd || pitch > rangeHighEnd) pitch = ToneGenerator.DEFAULT_PITCH; if (duration < 0) duration = ToneGenerator.DEFAULT_DURATION; if (instrument < rangeLowEnd || instrument > rangeHighEnd) instrument = ToneGenerator.DEFAULT_INSTRUMENT; @@ -70,4 +77,3 @@ public void simulate(ProgramStatement statement) { } } - diff --git a/src/rars/riscv/syscalls/SyscallMidiOutSync.java b/src/rars/riscv/syscalls/SyscallMidiOutSync.java index 77aa6f71..ea41237e 100644 --- a/src/rars/riscv/syscalls/SyscallMidiOutSync.java +++ b/src/rars/riscv/syscalls/SyscallMidiOutSync.java @@ -67,10 +67,17 @@ public SyscallMidiOutSync() { * use the range 1-128. */ public void simulate(ProgramStatement statement) { - int pitch = RegisterFile.getValue("a0"); - int duration = RegisterFile.getValue("a1"); - int instrument = RegisterFile.getValue("a2"); - int volume = RegisterFile.getValue("a3"); + int hart = statement.getCurrentHart(); + int pitch, duration , instrument, volume; + if(hart == -1){ + pitch = RegisterFile.getValue("a0"); duration = RegisterFile.getValue("a1"); instrument = RegisterFile.getValue("a2"); + volume = RegisterFile.getValue("a3"); + } + else{ + pitch = RegisterFile.getValue("a0", hart); duration = RegisterFile.getValue("a1", hart) ; + instrument = RegisterFile.getValue("a2", hart); + volume = RegisterFile.getValue("a3", hart); + } if (pitch < rangeLowEnd || pitch > rangeHighEnd) pitch = ToneGenerator.DEFAULT_PITCH; if (duration < 0) duration = ToneGenerator.DEFAULT_DURATION; if (instrument < rangeLowEnd || instrument > rangeHighEnd) instrument = ToneGenerator.DEFAULT_INSTRUMENT; diff --git a/src/rars/riscv/syscalls/SyscallOpen.java b/src/rars/riscv/syscalls/SyscallOpen.java index 8eb50b1a..0c444dca 100644 --- a/src/rars/riscv/syscalls/SyscallOpen.java +++ b/src/rars/riscv/syscalls/SyscallOpen.java @@ -43,8 +43,16 @@ public SyscallOpen() { } public void simulate(ProgramStatement statement) throws ExitingException { - int retValue = SystemIO.openFile(NullString.get(statement), - RegisterFile.getValue("a1")); - RegisterFile.updateRegister("a0", retValue); // set returned fd value in register + int retValue, hart = statement.getCurrentHart(); + if (hart == -1) { + retValue = SystemIO.openFile(NullString.get(statement), + RegisterFile.getValue("a1")); + RegisterFile.updateRegister("a0", retValue); // set returned fd value in register + return; + } + retValue = SystemIO.openFile(NullString.get(statement), + RegisterFile.getValue("a1", hart)); + RegisterFile.updateRegister("a0", (long) retValue, hart); // set returned fd value in register + return; } -} \ No newline at end of file +} diff --git a/src/rars/riscv/syscalls/SyscallPrintChar.java b/src/rars/riscv/syscalls/SyscallPrintChar.java index 58b130f9..03877722 100644 --- a/src/rars/riscv/syscalls/SyscallPrintChar.java +++ b/src/rars/riscv/syscalls/SyscallPrintChar.java @@ -40,8 +40,12 @@ public SyscallPrintChar() { } public void simulate(ProgramStatement statement) { - char t = (char) (RegisterFile.getValue("a0") & 0x000000ff); + char t; + if(statement.getCurrentHart() == -1) + t = (char) (RegisterFile.getValue("a0") & 0x000000ff); + else + t = (char) (RegisterFile.getValue("a0", statement.getCurrentHart()) & 0x000000ff); SystemIO.printString(Character.toString(t)); } -} \ No newline at end of file +} diff --git a/src/rars/riscv/syscalls/SyscallPrintFloat.java b/src/rars/riscv/syscalls/SyscallPrintFloat.java index 51102270..66592878 100644 --- a/src/rars/riscv/syscalls/SyscallPrintFloat.java +++ b/src/rars/riscv/syscalls/SyscallPrintFloat.java @@ -39,7 +39,11 @@ public SyscallPrintFloat() { } public void simulate(ProgramStatement statement) { - SystemIO.printString(Float.toString(Float.intBitsToFloat( - FloatingPointRegisterFile.getValue("fa0")))); + if(statement.getCurrentHart() == -1) + SystemIO.printString(Float.toString(Float.intBitsToFloat( + FloatingPointRegisterFile.getValue("fa0")))); + else + SystemIO.printString(Float.toString(Float.intBitsToFloat( + FloatingPointRegisterFile.getValue("fa0", statement.getCurrentHart())))); } } \ No newline at end of file diff --git a/src/rars/riscv/syscalls/SyscallPrintInt.java b/src/rars/riscv/syscalls/SyscallPrintInt.java index 81a41377..71f19740 100644 --- a/src/rars/riscv/syscalls/SyscallPrintInt.java +++ b/src/rars/riscv/syscalls/SyscallPrintInt.java @@ -39,6 +39,9 @@ public SyscallPrintInt() { } public void simulate(ProgramStatement statement) { - SystemIO.printString(Integer.toString(RegisterFile.getValue("a0"))); + if(statement.getCurrentHart() == -1) + SystemIO.printString(Integer.toString(RegisterFile.getValue("a0"))); + else + SystemIO.printString(Integer.toString(RegisterFile.getValue("a0", statement.getCurrentHart()))); } } \ No newline at end of file diff --git a/src/rars/riscv/syscalls/SyscallPrintIntBinary.java b/src/rars/riscv/syscalls/SyscallPrintIntBinary.java index 6d1cd0cd..ee5e689a 100644 --- a/src/rars/riscv/syscalls/SyscallPrintIntBinary.java +++ b/src/rars/riscv/syscalls/SyscallPrintIntBinary.java @@ -40,6 +40,9 @@ public SyscallPrintIntBinary() { } public void simulate(ProgramStatement statement) { - SystemIO.printString(Binary.intToBinaryString(RegisterFile.getValue("a0"))); + if(statement.getCurrentHart() == -1) + SystemIO.printString(Binary.intToBinaryString(RegisterFile.getValue("a0"))); + else + SystemIO.printString(Binary.intToBinaryString(RegisterFile.getValue("a0", statement.getCurrentHart()))); } } \ No newline at end of file diff --git a/src/rars/riscv/syscalls/SyscallPrintIntHex.java b/src/rars/riscv/syscalls/SyscallPrintIntHex.java index eb3853a8..27f16da0 100644 --- a/src/rars/riscv/syscalls/SyscallPrintIntHex.java +++ b/src/rars/riscv/syscalls/SyscallPrintIntHex.java @@ -40,6 +40,9 @@ public SyscallPrintIntHex() { } public void simulate(ProgramStatement statement) { - SystemIO.printString(Binary.intToHexString(RegisterFile.getValue("a0"))); + if(statement.getCurrentHart() == -1) + SystemIO.printString(Binary.intToHexString(RegisterFile.getValue("a0"))); + else + SystemIO.printString(Binary.intToHexString(RegisterFile.getValue("a0", statement.getCurrentHart()))); } } \ No newline at end of file diff --git a/src/rars/riscv/syscalls/SyscallPrintIntUnsigned.java b/src/rars/riscv/syscalls/SyscallPrintIntUnsigned.java index e0c72948..84af1264 100644 --- a/src/rars/riscv/syscalls/SyscallPrintIntUnsigned.java +++ b/src/rars/riscv/syscalls/SyscallPrintIntUnsigned.java @@ -40,7 +40,11 @@ public SyscallPrintIntUnsigned() { } public void simulate(ProgramStatement statement) { - SystemIO.printString( - Binary.unsignedIntToIntString(RegisterFile.getValue("a0"))); + if(statement.getCurrentHart() == -1) + SystemIO.printString( + Binary.unsignedIntToIntString(RegisterFile.getValue("a0"))); + else + SystemIO.printString( + Binary.unsignedIntToIntString(RegisterFile.getValue("a0", statement.getCurrentHart()))); } } \ No newline at end of file diff --git a/src/rars/riscv/syscalls/SyscallRandDouble.java b/src/rars/riscv/syscalls/SyscallRandDouble.java index 396ef692..40540bba 100644 --- a/src/rars/riscv/syscalls/SyscallRandDouble.java +++ b/src/rars/riscv/syscalls/SyscallRandDouble.java @@ -50,12 +50,19 @@ public SyscallRandDouble() { "a0 = index of pseudorandom number generator","fa0 = the next pseudorandom"); } public void simulate(ProgramStatement statement) throws ExitingException { - Integer index = RegisterFile.getValue("a0"); + Integer index; + if(statement.getCurrentHart() == -1) + index = RegisterFile.getValue("a0"); + else + index = RegisterFile.getValue("a0", statement.getCurrentHart()); Random stream = RandomStreams.randomStreams.get(index); if (stream == null) { stream = new Random(); // create a non-seeded stream RandomStreams.randomStreams.put(index, stream); } - FloatingPointRegisterFile.updateRegisterLong(10, Double.doubleToRawLongBits(stream.nextDouble())); + if(statement.getCurrentHart() == -1) + FloatingPointRegisterFile.updateRegisterLong(10, Double.doubleToRawLongBits(stream.nextDouble())); + else + FloatingPointRegisterFile.updateRegisterLong(10, Double.doubleToRawLongBits(stream.nextDouble()), statement.getCurrentHart()); } } diff --git a/src/rars/riscv/syscalls/SyscallRandFloat.java b/src/rars/riscv/syscalls/SyscallRandFloat.java index def7ab43..2d5c0525 100644 --- a/src/rars/riscv/syscalls/SyscallRandFloat.java +++ b/src/rars/riscv/syscalls/SyscallRandFloat.java @@ -41,7 +41,14 @@ public SyscallRandFloat() { } public void simulate(ProgramStatement statement) { - Random stream = RandomStreams.get("a0"); - FloatingPointRegisterFile.setRegisterToFloat(10, stream.nextFloat());// TODO: make this a string method fa0 + int hart = statement.getCurrentHart(); + if(hart == -1){ + Random stream = RandomStreams.get("a0"); + FloatingPointRegisterFile.setRegisterToFloat(10, stream.nextFloat());// TODO: make this a string method fa0 + } + else{ + Random stream = RandomStreams.get("a0", hart); + FloatingPointRegisterFile.setRegisterToFloat(10, stream.nextFloat(), hart);// TODO: make this a string method fa0 + } } } \ No newline at end of file diff --git a/src/rars/riscv/syscalls/SyscallRandInt.java b/src/rars/riscv/syscalls/SyscallRandInt.java index 0a15b848..f411f960 100644 --- a/src/rars/riscv/syscalls/SyscallRandInt.java +++ b/src/rars/riscv/syscalls/SyscallRandInt.java @@ -40,8 +40,15 @@ public SyscallRandInt() { } public void simulate(ProgramStatement statement) { - Random stream = RandomStreams.get("a0"); - RegisterFile.updateRegister("a0", stream.nextInt()); + int hart = statement.getCurrentHart(); + if(hart == -1){ + Random stream = RandomStreams.get("a0"); + RegisterFile.updateRegister("a0", stream.nextInt()); + } + else{ + Random stream = RandomStreams.get("a0", hart); + RegisterFile.updateRegister("a0", stream.nextInt(), hart); + } } } diff --git a/src/rars/riscv/syscalls/SyscallRandIntRange.java b/src/rars/riscv/syscalls/SyscallRandIntRange.java index e0fb8494..adb4237f 100644 --- a/src/rars/riscv/syscalls/SyscallRandIntRange.java +++ b/src/rars/riscv/syscalls/SyscallRandIntRange.java @@ -42,12 +42,25 @@ public SyscallRandIntRange() { } public void simulate(ProgramStatement statement) throws ExitingException { - Random stream = RandomStreams.get("a0"); - try { - RegisterFile.updateRegister("a0", stream.nextInt(RegisterFile.getValue("a1"))); - } catch (IllegalArgumentException iae) { - throw new ExitingException(statement, - "Upper bound of range cannot be negative (syscall " + this.getNumber() + ")"); + int hart = statement.getCurrentHart(); + Random stream; + if(hart == -1){ + stream = RandomStreams.get("a0"); + try { + RegisterFile.updateRegister("a0", stream.nextInt(RegisterFile.getValue("a1"))); + } catch (IllegalArgumentException iae) { + throw new ExitingException(statement, + "Upper bound of range cannot be negative (syscall " + this.getNumber() + ")"); + } + } + else{ + stream = RandomStreams.get("a0", hart); + try { + RegisterFile.updateRegister("a0", stream.nextInt(RegisterFile.getValue("a1", hart))); + } catch (IllegalArgumentException iae) { + throw new ExitingException(statement, + "Upper bound of range cannot be negative (syscall " + this.getNumber() + ")"); + } } } } diff --git a/src/rars/riscv/syscalls/SyscallRandSeed.java b/src/rars/riscv/syscalls/SyscallRandSeed.java index 77d0969d..309e5884 100644 --- a/src/rars/riscv/syscalls/SyscallRandSeed.java +++ b/src/rars/riscv/syscalls/SyscallRandSeed.java @@ -41,12 +41,23 @@ public SyscallRandSeed() { } public void simulate(ProgramStatement statement) { - Integer index = RegisterFile.getValue("a0"); + int hart = statement.getCurrentHart(); + Integer index; + if(hart == -1) + index = RegisterFile.getValue("a0"); + else + index = RegisterFile.getValue("a0", hart); Random stream = RandomStreams.randomStreams.get(index); if (stream == null) { - RandomStreams.randomStreams.put(index, new Random(RegisterFile.getValue("a1"))); - } else { - stream.setSeed(RegisterFile.getValue("a1")); + if(hart == -1) + RandomStreams.randomStreams.put(index, new Random(RegisterFile.getValue("a1"))); + else + RandomStreams.randomStreams.put(index, new Random(RegisterFile.getValue("a1", hart))); + } else { + if(hart == -1) + stream.setSeed(RegisterFile.getValue("a1")); + else + stream.setSeed(RegisterFile.getValue("a1", hart)); } } } diff --git a/src/rars/riscv/syscalls/SyscallRead.java b/src/rars/riscv/syscalls/SyscallRead.java index f2c97642..26d3471a 100644 --- a/src/rars/riscv/syscalls/SyscallRead.java +++ b/src/rars/riscv/syscalls/SyscallRead.java @@ -10,10 +10,8 @@ /* Copyright (c) 2003-2009, Pete Sanderson and Kenneth Vollmar - Developed by Pete Sanderson (psanderson@otterbein.edu) and Kenneth Vollmar (kenvollmar@missouristate.edu) - Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including @@ -21,10 +19,8 @@ a copy of this software and associated documentation files (the distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. @@ -32,7 +28,6 @@ a copy of this software and associated documentation files (the ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - (MIT license, http://www.opensource.org/licenses/mit-license.html) */ @@ -44,16 +39,28 @@ public SyscallRead() { } public void simulate(ProgramStatement statement) throws ExitingException { - int byteAddress = RegisterFile.getValue("a1"); // destination of characters read from file + int hart = statement.getCurrentHart(); + int byteAddress = hart == -1 + ? RegisterFile.getValue("a1") + : RegisterFile.getValue("a1", hart); // destination of characters read from file int index = 0; - int length = RegisterFile.getValue("a2"); + int length = hart == -1 + ? RegisterFile.getValue("a2") + : RegisterFile.getValue("a2", hart); byte myBuffer[] = new byte[length]; // specified length // Call to SystemIO.xxxx.read(xxx,xxx,xxx) returns actual length int retLength = SystemIO.readFromFile( - RegisterFile.getValue("a0"), // fd + hart == -1 // fd + ? RegisterFile.getValue("a0") + : RegisterFile.getValue("a0", hart), myBuffer, // buffer length); // length - RegisterFile.updateRegister("a0", retLength); // set returned value in register + // set returned value in register + if (hart == -1) { + RegisterFile.updateRegister("a0", retLength); + } else { + RegisterFile.updateRegister("a0", retLength, hart); + } // copy bytes from returned buffer into memory try { diff --git a/src/rars/riscv/syscalls/SyscallReadChar.java b/src/rars/riscv/syscalls/SyscallReadChar.java index 6e7bdd39..f0de54ab 100644 --- a/src/rars/riscv/syscalls/SyscallReadChar.java +++ b/src/rars/riscv/syscalls/SyscallReadChar.java @@ -41,7 +41,10 @@ public SyscallReadChar() { public void simulate(ProgramStatement statement) throws ExitingException { try { - RegisterFile.updateRegister("a0", SystemIO.readChar(this.getNumber())); + if(statement.getCurrentHart() == -1) + RegisterFile.updateRegister("a0", SystemIO.readChar(this.getNumber())); + else + RegisterFile.updateRegister("a0", SystemIO.readChar(this.getNumber()), statement.getCurrentHart()); } catch (IndexOutOfBoundsException e) // means null input { throw new ExitingException(statement, diff --git a/src/rars/riscv/syscalls/SyscallReadDouble.java b/src/rars/riscv/syscalls/SyscallReadDouble.java index d89603f3..8f3495cd 100644 --- a/src/rars/riscv/syscalls/SyscallReadDouble.java +++ b/src/rars/riscv/syscalls/SyscallReadDouble.java @@ -60,7 +60,9 @@ public void simulate(ProgramStatement statement) throws ExitingException { throw new ExitingException(statement, "invalid double input (syscall " + this.getNumber() + ")"); } - - FloatingPointRegisterFile.updateRegisterLong(10, Double.doubleToRawLongBits(doubleValue)); + if(statement.getCurrentHart() == -1) + FloatingPointRegisterFile.updateRegisterLong(10, Double.doubleToRawLongBits(doubleValue)); + else + FloatingPointRegisterFile.updateRegisterLong(10, Double.doubleToRawLongBits(doubleValue), statement.getCurrentHart()); } } \ No newline at end of file diff --git a/src/rars/riscv/syscalls/SyscallReadFloat.java b/src/rars/riscv/syscalls/SyscallReadFloat.java index b73f022b..64a9e040 100644 --- a/src/rars/riscv/syscalls/SyscallReadFloat.java +++ b/src/rars/riscv/syscalls/SyscallReadFloat.java @@ -47,6 +47,9 @@ public void simulate(ProgramStatement statement) throws ExitingException { throw new ExitingException(statement, "invalid float input (syscall " + this.getNumber() + ")"); } - FloatingPointRegisterFile.updateRegister(10, Float.floatToRawIntBits(floatValue)); // TODO: update to string fa0 + if(statement.getCurrentHart() == -1) + FloatingPointRegisterFile.updateRegister(10, Float.floatToRawIntBits(floatValue)); // TODO: update to string fa0 + else + FloatingPointRegisterFile.updateRegister(10, Float.floatToRawIntBits(floatValue), statement.getCurrentHart()); } } \ No newline at end of file diff --git a/src/rars/riscv/syscalls/SyscallReadInt.java b/src/rars/riscv/syscalls/SyscallReadInt.java index 576533b6..76c2a02e 100644 --- a/src/rars/riscv/syscalls/SyscallReadInt.java +++ b/src/rars/riscv/syscalls/SyscallReadInt.java @@ -41,8 +41,11 @@ public SyscallReadInt() { } public void simulate(ProgramStatement statement) throws ExitingException { - try { - RegisterFile.updateRegister("a0", SystemIO.readInteger(this.getNumber())); + try{ + if(statement.getCurrentHart() == -1) + RegisterFile.updateRegister("a0", SystemIO.readInteger(this.getNumber())); + else + RegisterFile.updateRegister("a0", SystemIO.readInteger(this.getNumber()), statement.getCurrentHart()); } catch (NumberFormatException e) { throw new ExitingException(statement, "invalid integer input (syscall " + this.getNumber() + ")"); diff --git a/src/rars/riscv/syscalls/SyscallReadString.java b/src/rars/riscv/syscalls/SyscallReadString.java index 39acfd3a..9ed44b1f 100644 --- a/src/rars/riscv/syscalls/SyscallReadString.java +++ b/src/rars/riscv/syscalls/SyscallReadString.java @@ -54,9 +54,39 @@ public SyscallReadString() { } public void simulate(ProgramStatement statement) throws ExitingException { + if(statement.getCurrentHart() == -1){ + String inputString = ""; + int buf = RegisterFile.getValue("a0"); // buf addr + int maxLength = RegisterFile.getValue("a1") - 1; + boolean addNullByte = true; + // Guard against negative maxLength. DPS 13-July-2011 + if (maxLength < 0) { + maxLength = 0; + addNullByte = false; + } + inputString = SystemIO.readString(this.getNumber(), maxLength); + + byte[] utf8BytesList = inputString.getBytes(StandardCharsets.UTF_8); + // TODO: allow for utf-8 encoded strings + int stringLength = Math.min(maxLength, utf8BytesList.length); + try { + for (int index = 0; index < stringLength; index++) { + Globals.memory.setByte(buf + index, + utf8BytesList[index]); + } + if (stringLength < maxLength) { + Globals.memory.setByte(buf + stringLength, '\n'); + stringLength++; + } + if (addNullByte) Globals.memory.setByte(buf + stringLength, 0); + } catch (AddressErrorException e) { + throw new ExitingException(statement, e); + } + return; + } String inputString = ""; - int buf = RegisterFile.getValue("a0"); // buf addr - int maxLength = RegisterFile.getValue("a1") - 1; + int buf = RegisterFile.getValue("a0", statement.getCurrentHart());// buf addr + int maxLength = RegisterFile.getValue("a1", statement.getCurrentHart()) - 1; boolean addNullByte = true; // Guard against negative maxLength. DPS 13-July-2011 if (maxLength < 0) { diff --git a/src/rars/riscv/syscalls/SyscallSbrk.java b/src/rars/riscv/syscalls/SyscallSbrk.java index 117274f0..98c81281 100644 --- a/src/rars/riscv/syscalls/SyscallSbrk.java +++ b/src/rars/riscv/syscalls/SyscallSbrk.java @@ -42,7 +42,10 @@ public SyscallSbrk() { public void simulate(ProgramStatement statement) throws ExitingException { try { - RegisterFile.updateRegister("a0", Globals.memory.allocateBytesFromHeap(RegisterFile.getValue("a0"))); + if(statement.getCurrentHart() == -1) + RegisterFile.updateRegister("a0", Globals.memory.allocateBytesFromHeap(RegisterFile.getValue("a0"))); + else + RegisterFile.updateRegister("a0", Globals.memory.allocateBytesFromHeap(RegisterFile.getValue("a0", statement.getCurrentHart())), statement.getCurrentHart()); } catch (IllegalArgumentException iae) { throw new ExitingException(statement, iae.getMessage() + " (syscall " + this.getNumber() + ")"); diff --git a/src/rars/riscv/syscalls/SyscallSleep.java b/src/rars/riscv/syscalls/SyscallSleep.java index 05254aa3..871c2f8f 100644 --- a/src/rars/riscv/syscalls/SyscallSleep.java +++ b/src/rars/riscv/syscalls/SyscallSleep.java @@ -39,7 +39,9 @@ public SyscallSleep() { public void simulate(ProgramStatement statement) { try { - Thread.sleep(RegisterFile.getValue("a0")); // units of milliseconds 1000 millisec = 1 sec. + if(statement.getCurrentHart() == -1) + Thread.sleep(RegisterFile.getValue("a0")); // units of milliseconds 1000 millisec = 1 sec. + Thread.sleep(RegisterFile.getValue("a0", statement.getCurrentHart())); } catch (InterruptedException e) { } } diff --git a/src/rars/riscv/syscalls/SyscallTime.java b/src/rars/riscv/syscalls/SyscallTime.java index 02ed400e..c73e4b1f 100644 --- a/src/rars/riscv/syscalls/SyscallTime.java +++ b/src/rars/riscv/syscalls/SyscallTime.java @@ -39,9 +39,15 @@ public SyscallTime() { } public void simulate(ProgramStatement statement) { + if(statement.getCurrentHart() == -1){ + long value = new java.util.Date().getTime(); + RegisterFile.updateRegister("a0", Binary.lowOrderLongToInt(value)); + RegisterFile.updateRegister("a1", Binary.highOrderLongToInt(value)); + return; + } long value = new java.util.Date().getTime(); - RegisterFile.updateRegister("a0", Binary.lowOrderLongToInt(value)); - RegisterFile.updateRegister("a1", Binary.highOrderLongToInt(value)); + RegisterFile.updateRegister("a0", Binary.lowOrderLongToInt(value), statement.getCurrentHart()); + RegisterFile.updateRegister("a1", Binary.highOrderLongToInt(value), statement.getCurrentHart()); } } \ No newline at end of file diff --git a/src/rars/riscv/syscalls/SyscallWrite.java b/src/rars/riscv/syscalls/SyscallWrite.java index 29fc528f..230cac29 100644 --- a/src/rars/riscv/syscalls/SyscallWrite.java +++ b/src/rars/riscv/syscalls/SyscallWrite.java @@ -50,10 +50,37 @@ public SyscallWrite() { } public void simulate(ProgramStatement statement) throws ExitingException { - int byteAddress = RegisterFile.getValue("a1"); // source of characters to write to file - int reqLength = RegisterFile.getValue("a2"); // user-requested length + if(statement.getCurrentHart() == -1){ + int byteAddress = RegisterFile.getValue("a1"); // source of characters to write to file + int reqLength = RegisterFile.getValue("a2"); // user-requested length + if (reqLength < 0) { + RegisterFile.updateRegister("a0", -1); + return; + } + int index = 0; + byte myBuffer[] = new byte[reqLength]; + try { + byte b = (byte) Globals.memory.getByte(byteAddress); + while (index < reqLength) // Stop at requested length. Null bytes are included. + { + myBuffer[index++] = b; + byteAddress++; + b = (byte) Globals.memory.getByte(byteAddress); + } + } catch (AddressErrorException e) { + throw new ExitingException(statement, e); + } + int retValue = SystemIO.writeToFile( + RegisterFile.getValue("a0"), // fd + myBuffer, // buffer + RegisterFile.getValue("a2")); // length + RegisterFile.updateRegister("a0", retValue); // set returned value in register + return; + } + int byteAddress = RegisterFile.getValue("a1", statement.getCurrentHart()); // source of characters to write to file + int reqLength = RegisterFile.getValue("a2", statement.getCurrentHart()); // user-requested length if (reqLength < 0) { - RegisterFile.updateRegister("a0", -1); + RegisterFile.updateRegister("a0", -1, statement.getCurrentHart()); return; } int index = 0; @@ -70,9 +97,9 @@ public void simulate(ProgramStatement statement) throws ExitingException { throw new ExitingException(statement, e); } int retValue = SystemIO.writeToFile( - RegisterFile.getValue("a0"), // fd + RegisterFile.getValue("a0", statement.getCurrentHart()), // fd myBuffer, // buffer - RegisterFile.getValue("a2")); // length - RegisterFile.updateRegister("a0", retValue); // set returned value in register + RegisterFile.getValue("a2", statement.getCurrentHart())); // length + RegisterFile.updateRegister("a0", retValue, statement.getCurrentHart()); // set returned value in register } } \ No newline at end of file diff --git a/src/rars/simulator/Simulator.java b/src/rars/simulator/Simulator.java index 27a99323..8529e5c2 100644 --- a/src/rars/simulator/Simulator.java +++ b/src/rars/simulator/Simulator.java @@ -49,10 +49,11 @@ a copy of this software and associated documentation files (the **/ public class Simulator extends Observable { - private SimThread simulatorThread; + private SimThread simulatorThread = null; + private static ArrayList gSimulatorThread; private static Simulator simulator = null; // Singleton object + private static ArrayList gSimulator; private static Runnable interactiveGUIUpdater = null; - /** * various reasons for simulate to end... */ @@ -81,6 +82,24 @@ public static Simulator getInstance() { } return simulator; } + public static Simulator getInstance(int tempHart) { + // Do NOT change this to create the Simulator at load time (in declaration above)! + // Its constructor looks for the GUI, which at load time is not created yet, + // and incorrectly leaves interactiveGUIUpdater null! This causes runtime + // exceptions while running in timed mode. + if(tempHart < 0){ + return null; + } + if (gSimulator == null) { + gSimulator = new ArrayList<>(); + gSimulatorThread = new ArrayList<>(); + for(int i = 0; i < Globals.getHarts(); i++){ + gSimulatorThread.add(null); + gSimulator.add(new Simulator(i)); + } + } + return gSimulator.get(tempHart); + } private Simulator() { simulatorThread = null; @@ -89,6 +108,12 @@ private Simulator() { } } + private Simulator(int tempHart) { + if (Globals.getGui() != null) { + interactiveGUIUpdater = new UpdateGUI(); + } + } + /** * Simulate execution of given source program (in this thread). It must have already been assembled. * @@ -126,6 +151,11 @@ public void startSimulation(int pc, int maxSteps, int[] breakPoints) { new Thread(simulatorThread, "RISCV").start(); } + public void startSimulation(int pc, int maxSteps, int[] breakPoints, int hart) { + gSimulatorThread.add(hart, new SimThread(pc, maxSteps, breakPoints, hart)); + String s = String.format("Hart %d", hart); + new Thread(gSimulatorThread.get(hart), s).start(); + } /** * Set the volatile stop boolean variable checked by the execution @@ -202,6 +232,7 @@ class SimThread implements Runnable { private SimulationException pe; private volatile boolean stop = false; private Reason constructReturnReason; + private int hart; /** * SimThread constructor. Receives all the information it needs to simulate execution. @@ -216,8 +247,16 @@ class SimThread implements Runnable { this.breakPoints = breakPoints; this.done = false; this.pe = null; + this.hart = -1; + } + SimThread(int pc, int maxSteps, int[] breakPoints, int hart) { + this.pc = pc; + this.maxSteps = maxSteps; + this.breakPoints = breakPoints; + this.done = false; + this.pe = null; + this.hart = hart; } - /** * Sets to "true" the volatile boolean variable that is tested after each * instruction is executed. After calling this method, the next test @@ -236,15 +275,25 @@ private void startExecution() { maxSteps,(Globals.getGui() != null || Globals.runSpeedPanelExists)?RunSpeedPanel.getInstance().getRunSpeed():RunSpeedPanel.UNLIMITED_SPEED, pc, null, pe, done)); } - + private void startExecution(int hart) { + Simulator.getInstance(hart).notifyObserversOfExecution(new SimulatorNotice(SimulatorNotice.SIMULATOR_START, + maxSteps,(Globals.getGui() != null || Globals.runSpeedPanelExists)?RunSpeedPanel.getInstance().getRunSpeed():RunSpeedPanel.UNLIMITED_SPEED, + pc, null, pe, done)); + } private void stopExecution(boolean done, Reason reason) { this.done = done; this.constructReturnReason = reason; SystemIO.flush(true); if (done) SystemIO.resetFiles(); // close any files opened in the process of simulating - Simulator.getInstance().notifyObserversOfExecution(new SimulatorNotice(SimulatorNotice.SIMULATOR_STOP, - maxSteps, (Globals.getGui() != null || Globals.runSpeedPanelExists)?RunSpeedPanel.getInstance().getRunSpeed():RunSpeedPanel.UNLIMITED_SPEED, - pc, reason, pe, done)); + double runSpeed = (Globals.getGui() != null || Globals.runSpeedPanelExists) + ? RunSpeedPanel.getInstance().getRunSpeed() + : RunSpeedPanel.UNLIMITED_SPEED; + if (hart == -1) + Simulator.getInstance().notifyObserversOfExecution(new SimulatorNotice(SimulatorNotice.SIMULATOR_STOP, + maxSteps, runSpeed, pc, reason, pe, done)); + else + Simulator.getInstance(hart).notifyObserversOfExecution(new SimulatorNotice(SimulatorNotice.SIMULATOR_STOP, + maxSteps, runSpeed, pc, reason, pe, done)); } private synchronized void interrupt() { @@ -256,30 +305,51 @@ private boolean handleTrap(SimulationException se, int pc) { assert se.cause() >= 0 : "Interrupts cannot be handled by the trap handler"; // set the relevant CSRs - ControlAndStatusRegisterFile.updateRegister("ucause", se.cause()); - ControlAndStatusRegisterFile.updateRegister("uepc", pc); - ControlAndStatusRegisterFile.updateRegister("utval", se.value()); + if (hart == -1) { + ControlAndStatusRegisterFile.updateRegister("ucause", se.cause()); + ControlAndStatusRegisterFile.updateRegister("uepc", pc); + ControlAndStatusRegisterFile.updateRegister("utval", se.value()); + } else { + ControlAndStatusRegisterFile.updateRegister("ucause", se.cause(), hart); + ControlAndStatusRegisterFile.updateRegister("uepc", pc, hart); + ControlAndStatusRegisterFile.updateRegister("utval", se.value(), hart); + } // Get the interrupt handler if it exists - int utvec = ControlAndStatusRegisterFile.getValue("utvec"); + int utvec = (hart == -1) + ? ControlAndStatusRegisterFile.getValue("utvec") + : ControlAndStatusRegisterFile.getValue("utvec", hart); // Mode can be ignored because we are only handling traps int base = utvec & 0xFFFFFFFC; ProgramStatement exceptionHandler = null; - if ((ControlAndStatusRegisterFile.getValue("ustatus") & 0x1) != 0) { // test user-interrupt enable (UIE) - try { - exceptionHandler = Globals.memory.getStatement(base); - } catch (AddressErrorException aee) { - // Handled below + try { + if (hart == -1) { + if ((ControlAndStatusRegisterFile.getValue("ustatus") & 0x1) != 0) { // test user-interrupt enable (UIE) + exceptionHandler = Globals.memory.getStatement(base); + } + } else { + if ((ControlAndStatusRegisterFile.getValue("ustatus", hart) & 0x1) != 0) { // test user-interrupt enable (UIE) + exceptionHandler = Globals.memory.getStatement(base); + } } + } catch (AddressErrorException aee) { + // Handled below } if (exceptionHandler != null) { - ControlAndStatusRegisterFile.orRegister("ustatus", 0x10); // Set UPIE - ControlAndStatusRegisterFile.clearRegister("ustatus", 0x1); // Clear UIE - RegisterFile.setProgramCounter(base); - return true; + if (hart == -1) { + ControlAndStatusRegisterFile.orRegister("ustatus", 0x10); // Set UPIE + ControlAndStatusRegisterFile.clearRegister("ustatus", 0x1); // Clear UIE + RegisterFile.setProgramCounter(base); + return true; + } else { + ControlAndStatusRegisterFile.orRegister("ustatus", 0x10, hart); // Set UPIE + ControlAndStatusRegisterFile.clearRegister("ustatus", 0x1, hart); // Clear UIE + RegisterFile.setProgramCounter(base, hart); + return true; + } } else { // If we don't have an error handler or exceptions are disabled terminate the process this.pe = se; @@ -294,15 +364,30 @@ private boolean handleInterrupt(int value, int cause, int pc) { int code = cause & 0x7FFFFFFF; // Don't handle cases where that interrupt isn't enabled - assert ((ControlAndStatusRegisterFile.getValue("ustatus") & 0x1) != 0 && (ControlAndStatusRegisterFile.getValue("uie") & (1 << code)) != 0) : "The interrupt handler must be enabled"; + if (hart == -1) + assert ((ControlAndStatusRegisterFile.getValue("ustatus") & 0x1) != 0 + && (ControlAndStatusRegisterFile.getValue("uie") & (1 << code)) != 0) + : "The interrupt handler must be enabled"; + else + assert ((ControlAndStatusRegisterFile.getValue("ustatus", hart) & 0x1) != 0 + && (ControlAndStatusRegisterFile.getValue("uie", hart) & (1 << code)) != 0) + : "The interrupt handler must be enabled"; // set the relevant CSRs - ControlAndStatusRegisterFile.updateRegister("ucause", cause); - ControlAndStatusRegisterFile.updateRegister("uepc", pc); - ControlAndStatusRegisterFile.updateRegister("utval", value); + if (hart == -1) { + ControlAndStatusRegisterFile.updateRegister("ucause", cause); + ControlAndStatusRegisterFile.updateRegister("uepc", pc); + ControlAndStatusRegisterFile.updateRegister("utval", value); + } else { + ControlAndStatusRegisterFile.updateRegister("ucause", cause, hart); + ControlAndStatusRegisterFile.updateRegister("uepc", pc, hart); + ControlAndStatusRegisterFile.updateRegister("utval", value, hart); + } // Get the interrupt handler if it exists - int utvec = ControlAndStatusRegisterFile.getValue("utvec"); + int utvec = (hart == -1) + ? ControlAndStatusRegisterFile.getValue("utvec") + : ControlAndStatusRegisterFile.getValue("utvec", hart); // Handle vectored mode int base = utvec & 0xFFFFFFFC, mode = utvec & 0x3; @@ -317,10 +402,19 @@ private boolean handleInterrupt(int value, int cause, int pc) { // handled below } if (exceptionHandler != null) { - ControlAndStatusRegisterFile.orRegister("ustatus", 0x10); // Set UPIE - ControlAndStatusRegisterFile.clearRegister("ustatus", ControlAndStatusRegisterFile.INTERRUPT_ENABLE); - RegisterFile.setProgramCounter(base); - return true; + if (hart == -1) { + ControlAndStatusRegisterFile.orRegister("ustatus", 0x10); // Set UPIE + ControlAndStatusRegisterFile.clearRegister("ustatus", + ControlAndStatusRegisterFile.INTERRUPT_ENABLE); + RegisterFile.setProgramCounter(base); + return true; + } else { + ControlAndStatusRegisterFile.orRegister("ustatus", 0x10, hart); // Set UPIE + ControlAndStatusRegisterFile.clearRegister("ustatus", ControlAndStatusRegisterFile.INTERRUPT_ENABLE, + hart); + RegisterFile.setProgramCounter(base, hart); + return true; + } } else { // If we don't have an error handler or exceptions are disabled terminate the process this.pe = new SimulationException("Interrupt handler was not supplied, but interrupt enable was high"); @@ -346,8 +440,10 @@ public void run() { } else { Arrays.sort(breakPoints); // must be pre-sorted for binary search } - - startExecution(); + if(hart == -1) + startExecution(); + else + startExecution(hart); // ******************* PS addition 26 July 2006 ********************** // A couple statements below were added for the purpose of assuring that when @@ -378,8 +474,10 @@ public void run() { // the backstep button is not enabled until a "real" instruction is executed. // This is noticeable in stepped mode. // ********************************************************************* - - RegisterFile.initializeProgramCounter(pc); + if(hart == -1) + RegisterFile.initializeProgramCounter(pc); + else + RegisterFile.initializeProgramCounter(pc, hart); ProgramStatement statement = null; int steps = 0; boolean ebreak = false, waiting = false; @@ -395,10 +493,21 @@ public void run() { Globals.memoryAndRegistersLock.lock(); try { // Handle pending interupts and traps first - long uip = ControlAndStatusRegisterFile.getValueNoNotify("uip"), uie = ControlAndStatusRegisterFile.getValueNoNotify("uie"); - boolean IE = (ControlAndStatusRegisterFile.getValueNoNotify("ustatus") & ControlAndStatusRegisterFile.INTERRUPT_ENABLE) != 0; + long uip = (hart == -1) + ? ControlAndStatusRegisterFile.getValueNoNotify("uip") + : ControlAndStatusRegisterFile.getValueNoNotify("uip", hart); + long uie = (hart == -1) + ? ControlAndStatusRegisterFile.getValueNoNotify("uie") + : ControlAndStatusRegisterFile.getValueNoNotify("uie", hart); + boolean IE = (hart == -1) + ? (ControlAndStatusRegisterFile.getValueNoNotify("ustatus") + & ControlAndStatusRegisterFile.INTERRUPT_ENABLE) != 0 + : (ControlAndStatusRegisterFile.getValueNoNotify("ustatus", hart) + & ControlAndStatusRegisterFile.INTERRUPT_ENABLE) != 0; // make sure no interrupts sneak in while we are processing them - pc = RegisterFile.getProgramCounter(); + pc = (hart == -1) + ? RegisterFile.getProgramCounter() + : RegisterFile.getProgramCounter(hart); synchronized (InterruptController.lock) { boolean pendingExternal = InterruptController.externalPending(), pendingTimer = InterruptController.timerPending(), @@ -432,8 +541,10 @@ public void run() { } uip |= (pendingExternal ? ControlAndStatusRegisterFile.EXTERNAL_INTERRUPT : 0) | (pendingTimer ? ControlAndStatusRegisterFile.TIMER_INTERRUPT : 0); } - if (uip != ControlAndStatusRegisterFile.getValueNoNotify("uip")) { + if (hart == -1 && uip != ControlAndStatusRegisterFile.getValueNoNotify("uip")) { ControlAndStatusRegisterFile.updateRegister("uip", uip); + } else if (hart >= 0 && uip != ControlAndStatusRegisterFile.getValueNoNotify("uip", hart)) { + ControlAndStatusRegisterFile.updateRegister("uip", uip, hart); } // always handle interrupts and traps before quiting @@ -446,21 +557,30 @@ public void run() { } } - pc = RegisterFile.getProgramCounter(); - RegisterFile.incrementPC(); + if (hart == -1) { + pc = RegisterFile.getProgramCounter(); + RegisterFile.incrementPC(); + } else { + pc = RegisterFile.getProgramCounter(hart); + RegisterFile.incrementPC(hart); + } + // Get instuction try { statement = Globals.memory.getStatement(pc); + if (statement != null) + statement.setCurrentHart(hart); } catch (AddressErrorException e) { - SimulationException tmp; - if (e.getType() == SimulationException.LOAD_ACCESS_FAULT) { - tmp = new SimulationException("Instruction load access error", SimulationException.INSTRUCTION_ACCESS_FAULT); - } else { - tmp = new SimulationException("Instruction load alignment error", SimulationException.INSTRUCTION_ADDR_MISALIGNED); - } + SimulationException tmp = (e.getType() == SimulationException.LOAD_ACCESS_FAULT) + ? new SimulationException("Instruction load access error", SimulationException.INSTRUCTION_ACCESS_FAULT) + : new SimulationException("Instruction load alignment error", SimulationException.INSTRUCTION_ADDR_MISALIGNED); if (!InterruptController.registerSynchronousTrap(tmp, pc)) { this.pe = tmp; - ControlAndStatusRegisterFile.updateRegister("uepc", pc); + if (hart == -1) { + ControlAndStatusRegisterFile.updateRegister("uepc", pc); + } else { + ControlAndStatusRegisterFile.updateRegister("uepc", pc, hart); + } stopExecution(true, Reason.EXCEPTION); return; } else { @@ -481,8 +601,8 @@ public void run() { SimulationException.ILLEGAL_INSTRUCTION); } // THIS IS WHERE THE INSTRUCTION EXECUTION IS ACTUALLY SIMULATED! - instruction.simulate(statement); + instruction.simulate(statement); // IF statement added 7/26/06 (explanation above) if (Globals.getSettings().getBackSteppingEnabled()) { Globals.program.getBackStepper().addDoNothing(pc); @@ -524,10 +644,17 @@ public void run() { // Update cycle(h) and instret(h) long cycle = ControlAndStatusRegisterFile.getValueNoNotify("cycle"), instret = ControlAndStatusRegisterFile.getValueNoNotify("instret"), - time = System.currentTimeMillis();; - ControlAndStatusRegisterFile.updateRegisterBackdoor("cycle",cycle+1); - ControlAndStatusRegisterFile.updateRegisterBackdoor("instret",instret+1); - ControlAndStatusRegisterFile.updateRegisterBackdoor("time",time); + time = System.currentTimeMillis(); + ControlAndStatusRegisterFile.updateRegisterBackdoor("cycle", cycle + 1); + ControlAndStatusRegisterFile.updateRegisterBackdoor("instret", instret + 1); + ControlAndStatusRegisterFile.updateRegisterBackdoor("time", time); + for (int i = 0; i < Globals.getHarts() - 1; i++) { + cycle = ControlAndStatusRegisterFile.getValueNoNotify("cycle", i); + instret = ControlAndStatusRegisterFile.getValueNoNotify("instret", i); + ControlAndStatusRegisterFile.updateRegisterBackdoor("cycle", cycle + 1, i); + ControlAndStatusRegisterFile.updateRegisterBackdoor("instret", instret + 1, i); + ControlAndStatusRegisterFile.updateRegisterBackdoor("time", time, i); + } // Return if we've reached a breakpoint. if (ebreak || (breakPoints != null) && @@ -585,4 +712,18 @@ public void run() { Globals.getGui().getMainPane().getExecutePane().getTextSegmentWindow().highlightStepAtPC(); } } + + /* private class GeneralUpdateGUI implements Runnable { + public void run() { + if (Globals.getGui().getRegistersPane().getSelectedComponent() == + Globals.getGui().getMainPane().getExecutePane().getRegistersWindow()) { + Globals.getGui().getMainPane().getExecutePane().getRegistersWindow().updateRegisters(); + } else { + Globals.getGui().getMainPane().getExecutePane().getFloatingPointWindow().updateRegisters(); + } + Globals.getGui().getMainPane().getExecutePane().getDataSegmentWindow().updateValues(); + Globals.getGui().getMainPane().getExecutePane().getTextSegmentWindow().setCodeHighlighting(true); + Globals.getGui().getMainPane().getExecutePane().getTextSegmentWindow().highlightStepAtPC(); + } + }*/ } diff --git a/src/rars/tools/AbstractToolAndApplication.java b/src/rars/tools/AbstractToolAndApplication.java index 2ef1518c..11ea7566 100644 --- a/src/rars/tools/AbstractToolAndApplication.java +++ b/src/rars/tools/AbstractToolAndApplication.java @@ -66,9 +66,8 @@ a copy of this software and associated documentation files (the */ public abstract class AbstractToolAndApplication extends JFrame implements Tool, Observer { protected boolean isBeingUsedAsATool = false; // can use to determine whether invoked as Tool or stand-alone. - private JDialog dialog; // used only for Tool use. This is the pop-up dialog that appears when menu item selected. + protected JDialog dialog; // used only for Tool use. This is the pop-up dialog that appears when menu item selected. protected Window theWindow; // highest level GUI component (a JFrame for app, a JDialog for Tool) - // Major GUI components private JLabel headingLabel; private String title; // descriptive title for title bar provided to constructor. diff --git a/src/rars/tools/InstructionStatistics.java b/src/rars/tools/InstructionStatistics.java index ef96d88d..dde83937 100644 --- a/src/rars/tools/InstructionStatistics.java +++ b/src/rars/tools/InstructionStatistics.java @@ -226,7 +226,7 @@ protected void addAsObserver() { * decodes the instruction and determines the category of the instruction. *

* The instruction is decoded by checking the java instance of the instruction. - * Only the most relevant instructions are decoded and categorized. + * Supported instructions are RV32I, RV64I, M, and A extensions. * * @param instruction the instruction to decode * @return the category of the instruction @@ -259,6 +259,8 @@ protected int getInstructionCategory(Instruction instruction) { return InstructionStatistics.CATEGORY_MEM; // lb, lh, lwl, lw, lbu, lhu, lwr if (instruction instanceof Store) return InstructionStatistics.CATEGORY_MEM; // sb, sh, swl, sw, swr + if (instruction instanceof Atomic) + return InstructionStatistics.CATEGORY_MEM; // a extension return InstructionStatistics.CATEGORY_OTHER; } diff --git a/src/rars/tools/ReservationTablesTool.java b/src/rars/tools/ReservationTablesTool.java new file mode 100644 index 00000000..5f492d39 --- /dev/null +++ b/src/rars/tools/ReservationTablesTool.java @@ -0,0 +1,212 @@ +package rars.tools; + +import rars.Globals; +import rars.riscv.hardware.AddressErrorException; +import rars.riscv.hardware.ControlAndStatusRegisterFile; +import rars.riscv.hardware.FloatingPointRegisterFile; +import rars.riscv.hardware.RegisterFile; +import rars.riscv.hardware.ReservationTable.bitWidth; +import rars.venus.*; + +import javax.swing.*; +import java.awt.*; +import java.util.*; +import java.awt.event.*; +import javax.swing.border.TitledBorder; + +/* +Copyright (c) 2021, Giancarlo Pernudi Segura & Siva Chowdeswar Nandipati. + +Developed by Giancarlo Pernudi Segura (pernudi@ualberta.ca) & Siva Chowdeswar Nandipati (sivachow@ualberta.ca). + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject +to the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +(MIT license, http://www.opensource.org/licenses/mit-license.html) + */ + +public class ReservationTablesTool extends AbstractToolAndApplication { + private static String heading = "Reservation Table Tool"; + private static String version = "Version 1.0"; + private static String displayPanelTitle; + private JPanel hartPanel; + private JComboBox hartWindowSelector; + protected ArrayList hartWindows; + private JTable reservations; + + public ReservationTablesTool() { + super(heading + ", " + version, heading); + hartWindows = Globals.getHartWindows(); + Globals.reservationTables.addObserver(this); + } + + protected JComponent buildMainDisplayArea() { + JPanel panelTools = new JPanel(new BorderLayout()); + hartPanel = new JPanel(new BorderLayout()); + String[] columns = new String[Globals.reservationTables.harts * 2]; + for (int i = 0; i < Globals.reservationTables.harts; i++) { + columns[i * 2] = String.format("Hart %d", i); + columns[i * 2 + 1] = "Length"; + } + reservations = new JTable(Globals.reservationTables.getAllAddressesAsStrings(), columns) { + @Override + public boolean isCellEditable(int row, int column) { + return false; + } + }; + + hartPanel.add(reservations.getTableHeader(), BorderLayout.NORTH); + reservations.setCellSelectionEnabled(true); + reservations.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + reservations.getTableHeader().setReorderingAllowed(false); + hartPanel.add(reservations); + + TitledBorder tb = new TitledBorder(displayPanelTitle); + tb.setTitleJustification(TitledBorder.CENTER); + panelTools.setBorder(tb); + + Box displayOptions = Box.createHorizontalBox(); + hartWindowSelector = new JComboBox<>(SelectHartWindow()); + hartWindowSelector.setToolTipText("Technique for determining simulated transmitter device processing delay"); + hartWindowSelector.addActionListener( + new ActionListener() { + public void actionPerformed(ActionEvent e) { + int i = hartWindowSelector.getSelectedIndex(); + Globals.setHartWindows(); + hartWindows = Globals.getHartWindows(); + if (i == 0) + return; + else + hartWindows.get(i-1).setVisible(true); + } + }); + + JButton clearButton = new JButton("Clear Selected"); + clearButton.setToolTipText("Clear the Selected from the Reserve Table"); + clearButton.addActionListener(l -> { + if (connectButton.isConnected()) { + int row = reservations.getSelectedRow(); + int col = reservations.getSelectedColumn(); + if(row < 0 || col < 0) + return; + if (col % 2 == 1) + col--; + int address = Integer.parseInt(reservations.getValueAt(row, col) + .toString().substring(2), 16); + try { + Globals.reservationTables.unreserveAddress(col, address, bitWidth.word); + } catch (AddressErrorException e) { + e.printStackTrace(); + } + } + reservations.clearSelection(); + updateDisplay(); + }); + JButton btnPlus = new JButton("+"); + JButton btnMinus = new JButton("-"); + btnPlus.addActionListener(l -> { + Globals.setHarts(1); + super.dialog.dispose(); + RegisterFile.initGRegisterBlock(); + RegisterFile.initProgramCounter(); + ControlAndStatusRegisterFile.changeHarts(1); + FloatingPointRegisterFile.increaseHarts(); + action(); + }); + btnMinus.addActionListener(l -> { + Globals.setHarts(-1); + super.dialog.dispose(); + RegisterFile.initGRegisterBlock(); + RegisterFile.initProgramCounter(); + ControlAndStatusRegisterFile.changeHarts(-1); + FloatingPointRegisterFile.decreaseHarts(); + try { + Globals + .getHartWindows() + .remove(Globals.getHarts() - 1) + .dispose(); + } catch (IndexOutOfBoundsException e) {} + action(); + }); + displayOptions.add(Box.createHorizontalGlue()); + displayOptions.add(btnMinus); + displayOptions.add(hartWindowSelector); + displayOptions.add(btnPlus); + clearButton.addKeyListener(new EnterKeyListener(clearButton)); + displayOptions.add(Box.createHorizontalGlue()); + displayOptions.add(clearButton); + displayOptions.add(Box.createHorizontalGlue()); + + JSplitPane both = new JSplitPane(JSplitPane.VERTICAL_SPLIT, hartPanel, displayOptions); + both.setResizeWeight(0.5); + panelTools.add(both); + return panelTools; + } + + + @Override + public String getName() { + return heading; + } + + protected JComponent getHelpComponent() { + final String helpContent = "Use this tool to simulate atomic operations such as store conditional.\n" + + "While this tool is connected to the program, the table below shows the\n" + + "reservation table for each hart. Addresses reserved by a hart\n" + + "will appear under that hart's column. You can release an address,\n" + + "which will release that address across all the hart's tables in\n" + + "order to simulate some other hart performing a store conditional.\n" + + "(contributed by Giancarlo Pernudi Segura, pernudi@ualberta.ca) &" + + "\n Siva Chowdeswar Nandipati (sivachow@ualberta.ca)"; + JButton help = new JButton("Help"); + help.addActionListener(l -> { + JOptionPane.showMessageDialog(theWindow, helpContent); + }); + return help; + } + + @Override + protected void updateDisplay() { + String[][] addresses = Globals.reservationTables.getAllAddressesAsStrings(); + for (int i = 0; i < addresses.length; i++) { + for (int j = 0; j < addresses[i].length; j++) { + reservations.setValueAt(addresses[i][j], i, j); + } + } + } + + public void update() { + this.updateDisplay(); + } + + @Override + protected void reset() { + Globals.reservationTables.reset(); + updateDisplay(); + } + + private Integer[] SelectHartWindow() { + Integer hartChoser[]; + hartChoser = new Integer[(Integer) Globals.getHarts()]; + for (int i = 0; i < Globals.getHarts(); i++) { + hartChoser[i] = i; + } + return hartChoser; + } +} diff --git a/src/rars/venus/GeneralExecutePane.java b/src/rars/venus/GeneralExecutePane.java new file mode 100644 index 00000000..35376eb7 --- /dev/null +++ b/src/rars/venus/GeneralExecutePane.java @@ -0,0 +1,248 @@ +package rars.venus; + +import rars.Globals; +import rars.Settings; +import rars.venus.registers.ControlAndStatusWindow; +import rars.venus.registers.FloatingPointWindow; +import rars.venus.registers.RegistersWindow; + +import javax.swing.*; +import java.awt.*; + +/* +Copyright (c) 2003-2006, Siva Chowdeswar Nandipati + +Developed by Siva Chowdeswar Nandipati (sivachow@ualberta.ca) + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject +to the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +(MIT license, http://www.opensource.org/licenses/mit-license.html) + */ + +/** + * Container for the execution-related windows. Currently displayed as a tabbed pane. + * + * @author Sanderson and Team JSpim + **/ + +public class GeneralExecutePane extends JDesktopPane { + private RegistersWindow registerValues; + private FloatingPointWindow fpRegValues; + private ControlAndStatusWindow csrValues; + private TextSegmentWindow textSegment; + private LabelsWindow labelValues; + private GeneralVenusUI mainUI; + private NumberDisplayBaseChooser valueDisplayBase; + private NumberDisplayBaseChooser addressDisplayBase; + private boolean labelWindowVisible; + private int hart; + + /** + * initialize the Execute pane with major components + * + * @param mainUI the parent GUI + * @param regs window containing integer register set + * @param fpRegs window containing floating point register set + * @param csrRegs window containing the CSR set + */ + + public GeneralExecutePane(GeneralVenusUI mainUI, RegistersWindow regs, FloatingPointWindow fpRegs, ControlAndStatusWindow csrRegs, int hart) { + this.mainUI = mainUI; + // Although these are displayed in Data Segment, they apply to all three internal + // windows within the Execute pane. So they will be housed here. + addressDisplayBase = new NumberDisplayBaseChooser("Hexadecimal Addresses", + Globals.getSettings().getBooleanSetting(Settings.Bool.DISPLAY_ADDRESSES_IN_HEX)); + valueDisplayBase = new NumberDisplayBaseChooser("Hexadecimal Values", + Globals.getSettings().getBooleanSetting(Settings.Bool.DISPLAY_VALUES_IN_HEX));//VenusUI.DEFAULT_NUMBER_BASE); + this.hart = hart; + registerValues = regs; + fpRegValues = fpRegs; + csrValues = csrRegs; + textSegment = new TextSegmentWindow(); + labelValues = new LabelsWindow(); + labelWindowVisible = Globals.getSettings().getBooleanSetting(Settings.Bool.LABEL_WINDOW_VISIBILITY); + this.add(textSegment); // these 3 LOC moved up. DPS 3-Sept-2014 + textSegment.pack(); // these 3 LOC added. DPS 3-Sept-2014 + textSegment.setVisible(true); + labelValues.setVisible(labelWindowVisible); + + } + + /** + * This method will set the bounds of this JDesktopPane's internal windows + * relative to the current size of this JDesktopPane. Such an operation + * cannot be adequately done at constructor time because the actual + * size of the desktop pane window is not yet established. Layout manager + * is not a good option here because JDesktopPane does not work well with + * them (the whole idea of using JDesktopPane with internal frames is to + * have mini-frames that you can resize, move around, minimize, etc). This + * method should be invoked only once: the first time the Execute tab is + * selected (a change listener invokes it). We do not want it invoked + * on subsequent tab selections; otherwise, user manipulations of the + * internal frames would be lost the next time execute tab is selected. + */ + public void setWindowBounds() { + + int fullWidth = this.getSize().width - this.getInsets().left - this.getInsets().right; + int fullHeight = this.getSize().height; + int halfHeight = fullHeight / 2; + Dimension textDim = new Dimension((int) (fullWidth * .75), halfHeight); + Dimension lablDim = new Dimension((int) (fullWidth * .25), halfHeight); + Dimension textFullDim = new Dimension((int) (fullWidth), halfHeight); + + if (labelWindowVisible) { + textSegment.setBounds(0, 0, textDim.width, textDim.height); + labelValues.setBounds(textDim.width + 1, 0, lablDim.width, lablDim.height); + } else { + textSegment.setBounds(0, 0, textFullDim.width, textFullDim.height); + labelValues.setBounds(0, 0, 0, 0); + } + } + + /** + * Show or hide the label window (symbol table). If visible, it is displayed + * to the right of the text segment and the latter is shrunk accordingly. + * + * @param visibility set to true or false + */ + + public void setLabelWindowVisibility(boolean visibility) { + if (!visibility && labelWindowVisible) { + labelWindowVisible = false; + textSegment.setVisible(false); + labelValues.setVisible(false); + setWindowBounds(); + textSegment.setVisible(true); + } else if (visibility && !labelWindowVisible) { + labelWindowVisible = true; + textSegment.setVisible(false); + setWindowBounds(); + textSegment.setVisible(true); + labelValues.setVisible(false); + } + } + + /** + * Clears out all components of the Execute tab: text segment + * display, data segment display, label display and register display. + * This will typically be done upon File->Close, Open, New. + */ + + public void clearPane() { + this.getTextSegmentWindow().clearWindow(); + this.getRegistersWindow().clearWindow(); + this.getFloatingPointWindow().clearWindow(); + this.getControlAndStatusWindow().clearWindow(); + this.getLabelsWindow().clearWindow(); + // seems to be required, to display cleared Execute tab contents... + if (mainUI.getMainPane().getSelectedComponent() == this) { + mainUI.getMainPane().setSelectedComponent(this); + } + } + + /** + * Access the text segment window. + */ + public TextSegmentWindow getTextSegmentWindow() { + return textSegment; + } + + /** + * Access the register values window. + */ + public RegistersWindow getRegistersWindow() { + return registerValues; + } + + /** + * Access the floating point values window. + */ + public FloatingPointWindow getFloatingPointWindow() { + return fpRegValues; + } + + /** + * Access the Control and Status values window. + */ + public ControlAndStatusWindow getControlAndStatusWindow() { + return csrValues; + } + + /** + * Access the label values window. + */ + public LabelsWindow getLabelsWindow() { + return labelValues; + } + + /** + * Retrieve the number system base for displaying values (mem/register contents) + */ + public int getValueDisplayBase() { + return valueDisplayBase.getBase(); + } + + /** + * Retrieve the number system base for displaying memory addresses + */ + public int getAddressDisplayBase() { + return addressDisplayBase.getBase(); + } + + /** + * Retrieve component used to set numerical base (10 or 16) of data value display. + * + * @return the chooser + */ + public NumberDisplayBaseChooser getValueDisplayBaseChooser() { + return valueDisplayBase; + } + + /** + * Retrieve component used to set numerical base (10 or 16) of address display. + * + * @return the chooser + */ + public NumberDisplayBaseChooser getAddressDisplayBaseChooser() { + return addressDisplayBase; + } + + /** + * Update display of columns based on state of given chooser. Normally + * called only by the chooser's ItemListener. + * + * @param chooser the GUI object manipulated by the user to change number base + */ + public void numberDisplayBaseChanged(NumberDisplayBaseChooser chooser) { + if (chooser == valueDisplayBase) { + // Have all internal windows update their value columns + registerValues.updateRegisters(hart); + fpRegValues.updateRegisters(); + csrValues.updateRegisters(); + textSegment.updateBasicStatements(); + } else { // addressDisplayBase + // Have all internal windows update their address columns + labelValues.updateLabelAddresses(); + textSegment.updateCodeAddresses(); + textSegment.updateBasicStatements(); + } + } + +} \ No newline at end of file diff --git a/src/rars/venus/GeneralMainPane.java b/src/rars/venus/GeneralMainPane.java new file mode 100644 index 00000000..aa8b8461 --- /dev/null +++ b/src/rars/venus/GeneralMainPane.java @@ -0,0 +1,102 @@ +package rars.venus; + +import rars.Globals; +import rars.venus.registers.ControlAndStatusWindow; +import rars.venus.registers.FloatingPointWindow; +import rars.venus.registers.RegistersWindow; + +import javax.swing.*; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.plaf.basic.BasicTabbedPaneUI; +import java.awt.*; + + +/* +Copyright (c) 2003-2006, Siva Chowdeswar Nandipati + +Developed by Siva Chowdeswar Nandipati (sivachow@ualberta.ca) + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject +to the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +(MIT license, http://www.opensource.org/licenses/mit-license.html) + */ + +/** + * Creates the tabbed areas in the UI and also created the internal windows that + * exist in them. + * + * @author Sanderson and Bumgarner + **/ + +public class GeneralMainPane extends JTabbedPane { + GeneralExecutePane executeTab; + private int hart; + private GeneralVenusUI mainUI; + + /** + * Constructor for the MainPane class. + **/ + + public GeneralMainPane(GeneralVenusUI appFrame, RegistersWindow regs, + FloatingPointWindow cop1Regs, ControlAndStatusWindow cop0Regs, int hart) { + super(); + this.hart = hart; + this.mainUI = appFrame; + this.setTabPlacement(JTabbedPane.TOP); //LEFT); + if (this.getUI() instanceof BasicTabbedPaneUI) { + BasicTabbedPaneUI ui = (BasicTabbedPaneUI) this.getUI(); + } + + executeTab = new GeneralExecutePane(appFrame, regs, cop1Regs, cop0Regs, hart); + String executeTabTitle = "Execute"; //"

 
E
x
e
c
u
t
e
 
"; + Icon executeTabIcon = null;//new ImageIcon(Toolkit.getDefaultToolkit().getImage(this.getClass().getResource(Globals.imagesPath+"Execute_tab.jpg"))); + + // this.addTab("
 
P
r
o
j
 
1", null, new JTabbedPane()); + // this.addTab("
 
P
r
o
j
 
2", null, new JTabbedPane()); + // this.addTab("
 
P
r
o
j
 
3", null, new JTabbedPane()); + // this.addTab("
 
P
r
o
j
 
4", null, new JTabbedPane()); + + this.addTab(executeTabTitle, executeTabIcon, executeTab); + + this.setToolTipTextAt(0, "View and control assembly language program execution. Enabled upon successful assemble."); + + } + + /** + * returns component containing execution-time display + * + * @return the execute pane + */ + public GeneralExecutePane getExecutePane() { + return executeTab; + } + + /** + * returns component containing execution-time display. + * Same as getExecutePane(). + * + * @return the execute pane + */ + public GeneralExecutePane getExecuteTab() { + return executeTab; + } + +} \ No newline at end of file diff --git a/src/rars/venus/GeneralVenusUI.java b/src/rars/venus/GeneralVenusUI.java new file mode 100644 index 00000000..572a838c --- /dev/null +++ b/src/rars/venus/GeneralVenusUI.java @@ -0,0 +1,428 @@ +package rars.venus; + +import rars.Globals; +import rars.Settings; +import rars.simulator.Simulator; +import rars.venus.registers.*; +import rars.venus.run.*; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.*; +import java.beans.PropertyVetoException; +import java.net.URL; + +/* +Copyright (c) 2003-2006, Siva Chowdeswar Nandipati & Giancarlo Pernudi Segura + +Developed by Siva Chowdeswar Nandipati (sivachow@ualberta.ca) and Giancarlo (pernudi@ualberta.ca) + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject +to the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +(MIT license, http://www.opensource.org/licenses/mit-license.html) + */ + +/** + * Top level container for General Venus GUI. + * + * @author Siva, Giancarlo, Sanderson, and Team JSpim + **/ +public class GeneralVenusUI extends JFrame { + GeneralVenusUI mainUI; + + private JToolBar toolbar; + private GeneralMainPane mainPane; + private GeneralRegistersPane registersPane; + private RegistersWindow registersTab; + private FloatingPointWindow fpTab; + private ControlAndStatusWindow csrTab; + private JSplitPane horizonSplitter; + JPanel north; + + private JButton Run, Reset, Step, Backstep, Stop, Pause; + private Action runGoAction, runStepAction, runBackstepAction, + runResetAction, runStopAction, runPauseAction; + private final int hart; + + // PLEASE PUT THESE TWO (& THEIR METHODS) SOMEWHERE THEY BELONG, NOT HERE + private boolean reset = true; // registers/memory reset for execution + private boolean started = false; // started execution + + /** + * Constructor for the Class. Sets up a window object for the UI + * + * @param s Name of the window to be created. + **/ + + // TODO check for mem observer + public GeneralVenusUI(int hart) { + super(String.format("Hart %d", hart + 1)); + mainUI = this; + this.hart = hart; + this.createActionObjects(); + VenusUI.observers.add(this); + double screenWidth = Toolkit.getDefaultToolkit().getScreenSize().getWidth(); + double screenHeight = Toolkit.getDefaultToolkit().getScreenSize().getHeight(); + double mainWidthPct = (screenWidth < 1000.0) ? 0.67 : 0.73; + double mainHeightPct = (screenWidth < 1000.0) ? 0.60 : 0.65; + double registersWidthPct = (screenWidth < 1000.0) ? 0.18 : 0.22; + double registersHeightPct = (screenWidth < 1000.0) ? 0.72 : 0.80; + Dimension mainPanePreferredSize = new Dimension((int) (screenWidth * mainWidthPct), (int) (screenHeight * mainHeightPct)); + Dimension registersPanePreferredSize = new Dimension((int) (screenWidth * registersWidthPct), (int) (screenHeight * registersHeightPct)); + Globals.initialize(true); + + // image courtesy of NASA/JPL. + URL im = this.getClass().getResource(Globals.imagesPath + "RISC-V.png"); + if (im == null) { + System.out.println("Internal Error: images folder or file not found"); + System.exit(0); + } + Image mars = Toolkit.getDefaultToolkit().getImage(im); + this.setIconImage(mars); + // Everything in frame will be arranged on JPanel "center", which is only frame component. + // "center" has BorderLayout and 2 major components: + // -- panel (jp) on North with 2 components + // 1. toolbar + // 2. run speed slider. + // -- split pane (horizonSplitter) in center with 2 components side-by-side + // 1. split pane (splitter) with 2 components stacked + // a. main pane, with 2 tabs (edit, execute) + // b. messages pane with 2 tabs (rars, run I/O) + // 2. registers pane with 3 tabs (register file, coproc 0, coproc 1) + // I should probably run this breakdown out to full detail. The components are created + // roughly in bottom-up order; some are created in component constructors and thus are + // not visible here. + + registersTab = new RegistersWindow(hart); + fpTab = new FloatingPointWindow(hart); + csrTab = new ControlAndStatusWindow(hart); + registersPane = new GeneralRegistersPane(mainUI, registersTab, fpTab, csrTab); + registersPane.setPreferredSize(registersPanePreferredSize); + + mainPane = new GeneralMainPane(mainUI, registersTab, fpTab, csrTab, hart); + mainPane.setPreferredSize(mainPanePreferredSize); + try { + mainPane.getExecutePane().getTextSegmentWindow().setMaximum(true); + } catch (PropertyVetoException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } + + horizonSplitter = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, mainPane, registersPane); + horizonSplitter.setOneTouchExpandable(true); + horizonSplitter.resetToPreferredSizes(); + + toolbar = this.setUpToolBar(); + + JPanel jp = new JPanel(new FlowLayout(FlowLayout.LEFT)); + jp.add(toolbar); + JPanel center = new JPanel(new BorderLayout()); + center.add(jp, BorderLayout.NORTH); + center.add(horizonSplitter); + this.add(center); + + this.addWindowListener( + new WindowAdapter() { + // This is invoked when opening the app. It will set the app to + // appear at full screen size. + public void windowOpened(WindowEvent e) { + mainUI.pack(); + mainUI.setMenuState(); + } + + // This is invoked when closing the app. + public void windowClosed(WindowEvent e) { + VenusUI.observers.remove(mainUI); + } + }); + } + + /** + * To set whether the register values are reset. + * + * @param b Boolean true if the register values have been reset. + **/ + + public void setReset(boolean b) { + reset = b; + } + + /** + * To set whether MIPS program execution has started. + * + * @param b true if the MIPS program execution has started. + **/ + + public void setStarted(boolean b) { + started = b; + } + + /** + * To find out whether the register values are reset. + * + * @return Boolean true if the register values have been reset. + **/ + + public boolean getReset() { + return reset; + } + + /** + * To find out whether MIPS program is currently executing. + * + * @return true if MIPS program is currently executing. + **/ + public boolean getStarted() { + return started; + } + + /** + * Get reference to messages pane associated with this GUI. + * + * @return MessagesPane object associated with the GUI. + **/ + + public GeneralMainPane getMainPane() { + return mainPane; + } + + /** + * Get reference to registers pane associated with this GUI. + * + * @return RegistersPane object associated with the GUI. + **/ + + public GeneralRegistersPane getRegistersPane() { + return registersPane; + } + + + private ImageIcon loadIcon(String name) { + return new ImageIcon(Toolkit.getDefaultToolkit().getImage(this.getClass().getResource(Globals.imagesPath + name))); + } + + private KeyStroke makeShortcut(int key) { + return KeyStroke.getKeyStroke(key, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()); + } + + /* + * Action objects are used instead of action listeners because one can be easily + * shared between a menu item and a toolbar button. Does nice things like + * disable both if the action is disabled, etc. + */ + private void createActionObjects() { + try { + runGoAction = new RunGoAction("Go", loadIcon("Play22.png"), "Run the current program", KeyEvent.VK_G, + KeyStroke.getKeyStroke(KeyEvent.VK_F5, 0), Globals.getGui()); + runStepAction = new RunStepAction("Step", loadIcon("StepForward22.png"), "Run one step at a time", + KeyEvent.VK_T, KeyStroke.getKeyStroke(KeyEvent.VK_F7, 0), Globals.getGui()); + runBackstepAction = new RunBackstepAction("Backstep", loadIcon("StepBack22.png"), "Undo the last step", + KeyEvent.VK_B, KeyStroke.getKeyStroke(KeyEvent.VK_F8, 0), Globals.getGui()); + runPauseAction = new GuiAction("Pause", loadIcon("Pause22.png"), "Pause the currently running program", + KeyEvent.VK_P, KeyStroke.getKeyStroke(KeyEvent.VK_F9, 0)) { + public void actionPerformed(ActionEvent e) { + Simulator.getInstance().pauseExecution(); + // RunGoAction's "paused" method will do the cleanup. + } + }; + runStopAction = new GuiAction("Stop", loadIcon("Stop22.png"), "Stop the currently running program", + KeyEvent.VK_S, KeyStroke.getKeyStroke(KeyEvent.VK_F11, 0)) { + public void actionPerformed(ActionEvent e) { + Simulator.getInstance().stopExecution(); + // RunGoAction's "stopped" method will take care of the cleanup. + } + }; + runResetAction = new RunResetAction("Reset", loadIcon("Reset22.png"), "Reset memory and registers", + KeyEvent.VK_R, KeyStroke.getKeyStroke(KeyEvent.VK_F12, 0), Globals.getGui()); + } catch (NullPointerException e) { + System.out.println( + "Internal Error: images folder not found, or other null pointer exception while creating Action objects"); + e.printStackTrace(); + System.exit(0); + } + } + + /* + * build the toolbar and connect items to action objects (which serve as action + * listeners shared between toolbar icon and corresponding menu item). + */ + + JToolBar setUpToolBar() { + JToolBar toolBar = new JToolBar(); + + Run = new JButton(runGoAction); + Run.setText(""); + Step = new JButton(runStepAction); + Step.setText(""); + Backstep = new JButton(runBackstepAction); + Backstep.setText(""); + Reset = new JButton(runResetAction); + Reset.setText(""); + Stop = new JButton(runStopAction); + Stop.setText(""); + Pause = new JButton(runPauseAction); + Pause.setText(""); + + toolBar.add(Run); + toolBar.add(Step); + toolBar.add(Backstep); + toolBar.add(Pause); + toolBar.add(Stop); + toolBar.add(Reset); + + return toolBar; + } + + /* + * Determine from FileStatus what the menu state (enabled/disabled)should be + * then call the appropriate method to set it. Current states are: + * + * setMenuStateInitial: set upon startup and after File->Close + * setMenuStateEditingNew: set upon File->New setMenuStateEditing: set upon + * File->Open or File->Save or erroneous Run->Assemble setMenuStateRunnable: set + * upon successful Run->Assemble setMenuStateRunning: set upon Run->Go + * setMenuStateTerminated: set upon completion of simulated execution + */ + protected void setMenuState() { + int status = VenusUI.getMenuState(); + switch (status) { + case FileStatus.NO_FILE: + setMenuStateInitial(); + break; + case FileStatus.NEW_NOT_EDITED: + setMenuStateEditingNew(); + break; + case FileStatus.NEW_EDITED: + setMenuStateEditingNew(); + break; + case FileStatus.NOT_EDITED: + setMenuStateNotEdited(); // was MenuStateEditing. DPS 9-Aug-2011 + break; + case FileStatus.EDITED: + setMenuStateEditing(); + break; + case FileStatus.RUNNABLE: + setMenuStateRunnable(); + break; + case FileStatus.RUNNING: + setMenuStateRunning(); + break; + case FileStatus.TERMINATED: + break; + case FileStatus.OPENING:// This is a temporary state. DPS 9-Aug-2011 + break; + default: + System.out.println("Invalid File Status: " + status); + break; + } + } + + private void setMenuStateInitial() { + runGoAction.setEnabled(false); + runStepAction.setEnabled(false); + runBackstepAction.setEnabled(false); + runResetAction.setEnabled(false); + runStopAction.setEnabled(false); + runPauseAction.setEnabled(false); + } + + /* + * Added DPS 9-Aug-2011, for newly-opened files. Retain existing Run menu state + * (except Assemble, which is always true). Thus if there was a valid assembly + * it is retained. + */ + private void setMenuStateNotEdited() { + /* Note: undo and redo are handled separately by the undo manager */ + // If assemble-all, allow previous Run menu settings to remain. + // Otherwise, clear them out. DPS 9-Aug-2011 + if (!Globals.getSettings().getBooleanSetting(Settings.Bool.ASSEMBLE_ALL)) { + runGoAction.setEnabled(false); + runStepAction.setEnabled(false); + runBackstepAction.setEnabled(false); + runResetAction.setEnabled(false); + runStopAction.setEnabled(false); + runPauseAction.setEnabled(false); + } + } + + private void setMenuStateEditing() { + /* Note: undo and redo are handled separately by the undo manager */ + runGoAction.setEnabled(false); + runStepAction.setEnabled(false); + runBackstepAction.setEnabled(false); + runResetAction.setEnabled(false); + runStopAction.setEnabled(false); + runPauseAction.setEnabled(false); + } + + /* + * Use this when "File -> New" is used + */ + private void setMenuStateEditingNew() { + /* Note: undo and redo are handled separately by the undo manager */ + runGoAction.setEnabled(false); + runStepAction.setEnabled(false); + runBackstepAction.setEnabled(false); + runResetAction.setEnabled(false); + runStopAction.setEnabled(false); + runPauseAction.setEnabled(false); + } + + /* + * Use this upon successful assemble or reset + */ + private void setMenuStateRunnable() { + /* Note: undo and redo are handled separately by the undo manager */ + runGoAction.setEnabled(true); + runStepAction.setEnabled(true); + runBackstepAction.setEnabled( + Globals.getSettings().getBackSteppingEnabled() && !Globals.program.getBackStepper().empty()); + runResetAction.setEnabled(true); + runStopAction.setEnabled(false); + runPauseAction.setEnabled(false); + } + + /* + * Use this while program is running + */ + private void setMenuStateRunning() { + /* Note: undo and redo are handled separately by the undo manager */ + runGoAction.setEnabled(false); + runStepAction.setEnabled(false); + runBackstepAction.setEnabled(false); + runResetAction.setEnabled(false); + runStopAction.setEnabled(true); + runPauseAction.setEnabled(true); + } + + /* + * Use this upon completion of execution + */ + public void setMenuStateTerminated() { + /* Note: undo and redo are handled separately by the undo manager */ + runGoAction.setEnabled(false); + runStepAction.setEnabled(false); + runBackstepAction.setEnabled( + Globals.getSettings().getBackSteppingEnabled() && !Globals.program.getBackStepper().empty()); + runResetAction.setEnabled(true); + runStopAction.setEnabled(false); + runPauseAction.setEnabled(false); + } +} diff --git a/src/rars/venus/TextSegmentWindow.java b/src/rars/venus/TextSegmentWindow.java index 59ef000e..04c940db 100644 --- a/src/rars/venus/TextSegmentWindow.java +++ b/src/rars/venus/TextSegmentWindow.java @@ -488,7 +488,9 @@ public void highlightStepAtPC() { highlightStepAtAddress(RegisterFile.getProgramCounter()); } - + public void highlightStepAtPC(int hart) { + highlightStepAtAddress(RegisterFile.getProgramCounter(hart)); + } /** * Highlights the source code line whose address matches the given * text segment address. @@ -804,7 +806,7 @@ public Component getTableCellRendererComponent(JTable table, Object value, Settings settings = Globals.getSettings(); boolean highlighting = textSegment.getCodeHighlighting(); - if (highlighting && textSegment.getIntCodeAddressAtRow(row) == highlightAddress) { + if (highlighting && intAddresses != null && textSegment.getIntCodeAddressAtRow(row) == highlightAddress) { cell.setBackground(settings.getColorSettingByPosition(Settings.TEXTSEGMENT_HIGHLIGHT_BACKGROUND)); cell.setForeground(settings.getColorSettingByPosition(Settings.TEXTSEGMENT_HIGHLIGHT_FOREGROUND)); cell.setFont(settings.getFontByPosition(Settings.TEXTSEGMENT_HIGHLIGHT_FONT)); diff --git a/src/rars/venus/VenusUI.java b/src/rars/venus/VenusUI.java index 9225d28f..0649d2ae 100644 --- a/src/rars/venus/VenusUI.java +++ b/src/rars/venus/VenusUI.java @@ -16,6 +16,7 @@ import java.awt.*; import java.awt.event.*; import java.net.URL; +import java.util.ArrayList; /* Copyright (c) 2003-2013, Pete Sanderson and Kenneth Vollmar @@ -84,7 +85,7 @@ public class VenusUI extends JFrame { private JMenuItem runGo, runStep, runBackstep, runReset, runAssemble, runStop, runPause, runClearBreakpoints, runToggleBreakpoints; private JCheckBoxMenuItem settingsLabel, settingsPopupInput, settingsValueDisplayBase, settingsAddressDisplayBase, settingsExtended, settingsAssembleOnOpen, settingsAssembleAll, settingsAssembleOpen, settingsWarningsAreErrors, - settingsStartAtMain, settingsProgramArguments, settingsSelfModifyingCode,settingsRV64; + settingsStartAtMain, settingsProgramArguments, settingsSelfModifyingCode, settingsRV64, settingsPerHartExecution; private JMenuItem settingsExceptionHandler, settingsEditor, settingsHighlighting, settingsMemoryConfiguration; private JMenuItem helpHelp, helpAbout; @@ -108,10 +109,11 @@ public class VenusUI extends JFrame { private Action settingsLabelAction, settingsPopupInputAction, settingsValueDisplayBaseAction, settingsAddressDisplayBaseAction, settingsExtendedAction, settingsAssembleOnOpenAction, settingsAssembleOpenAction, settingsAssembleAllAction, settingsWarningsAreErrorsAction, settingsStartAtMainAction, settingsProgramArgumentsAction, - settingsExceptionHandlerAction, settingsEditorAction, - settingsHighlightingAction, settingsMemoryConfigurationAction, settingsSelfModifyingCodeAction,settingsRV64Action; + settingsExceptionHandlerAction, settingsEditorAction, settingsHighlightingAction,settingsMemoryConfigurationAction, + settingsSelfModifyingCodeAction, settingsRV64Action, settingsPerHartExecutionAction; private Action helpHelpAction, helpAboutAction; + protected static ArrayList observers; /** * Constructor for the Class. Sets up a window object for the UI @@ -124,6 +126,7 @@ public VenusUI(String s) { mainUI = this; Globals.setGui(this); this.editor = new Editor(this); + observers = new ArrayList(); double screenWidth = Toolkit.getDefaultToolkit().getScreenSize().getWidth(); double screenHeight = Toolkit.getDefaultToolkit().getScreenSize().getHeight(); @@ -449,6 +452,9 @@ public void handler(boolean selected) { settingsSelfModifyingCodeAction = new SettingsAction("Self-modifying code", "If set, the program can write and branch to both text and data segments.", Settings.Bool.SELF_MODIFYING_CODE_ENABLED); + settingsPerHartExecutionAction = new SettingsAction("Each run steps button runs only assigned hart", + "If set, the run step, single step, and backward buttons will only affect the hart corelated to the window", + Settings.Bool.PER_HART_EXECUTION); // TODO: review this settingsRV64Action = new SettingsAction("64 bit", @@ -615,6 +621,8 @@ private JMenuBar setUpMenuBar() { settingsSelfModifyingCode.setSelected(Globals.getSettings().getBooleanSetting(Settings.Bool.SELF_MODIFYING_CODE_ENABLED)); settingsRV64 = new JCheckBoxMenuItem(settingsRV64Action); settingsRV64.setSelected(Globals.getSettings().getBooleanSetting(Settings.Bool.RV64_ENABLED)); + settingsPerHartExecution = new JCheckBoxMenuItem(settingsPerHartExecutionAction); + settingsPerHartExecution.setSelected(Globals.getSettings().getBooleanSetting(Settings.Bool.PER_HART_EXECUTION)); settingsAssembleOnOpen = new JCheckBoxMenuItem(settingsAssembleOnOpenAction); settingsAssembleOnOpen.setSelected(Globals.getSettings().getBooleanSetting(Settings.Bool.ASSEMBLE_ON_OPEN)); settingsAssembleAll = new JCheckBoxMenuItem(settingsAssembleAllAction); @@ -647,6 +655,7 @@ private JMenuBar setUpMenuBar() { settings.add(settingsExtended); settings.add(settingsSelfModifyingCode); settings.add(settingsRV64); + settings.add(settingsPerHartExecution); settings.addSeparator(); settings.add(settingsEditor); settings.add(settingsHighlighting); @@ -799,6 +808,7 @@ public void setMenuState(int status) { System.out.println("Invalid File Status: " + status); break; } + notifyObservers(); } @@ -1185,4 +1195,10 @@ private ImageIcon loadIcon(String name) { private KeyStroke makeShortcut(int key) { return KeyStroke.getKeyStroke(key, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()); } -} \ No newline at end of file + + public void notifyObservers() { + for (GeneralVenusUI ui : observers) { + ui.setMenuState(); + } + } +} diff --git a/src/rars/venus/registers/ControlAndStatusWindow.java b/src/rars/venus/registers/ControlAndStatusWindow.java index 3fb21358..da1aeae0 100644 --- a/src/rars/venus/registers/ControlAndStatusWindow.java +++ b/src/rars/venus/registers/ControlAndStatusWindow.java @@ -7,6 +7,7 @@ import rars.venus.NumberDisplayBaseChooser; public class ControlAndStatusWindow extends RegisterBlockWindow { + private int hart; /* * The tips to show when hovering over the names of the registers * TODO: Maintain order if any new CSRs are added @@ -28,11 +29,18 @@ public class ControlAndStatusWindow extends RegisterBlockWindow { /*instret*/"Instructions retired (same as cycle in RARS)", /*cycleh*/ "High 32 bits of cycle", /*timeh*/ "High 32 bits of time", - /*instreth*/ "High 32 bits of instret" + /*instreth*/ "High 32 bits of instret", + /*mhartid*/"ID of the hardware thread running the code" }; public ControlAndStatusWindow() { super(ControlAndStatusRegisterFile.getRegisters(), regToolTips, "Current 32 bit value"); + hart = -1; + } + + public ControlAndStatusWindow(int hart) { + super(ControlAndStatusRegisterFile.getRegisters(hart), regToolTips, "Current 32 bit value", hart); + this.hart = hart; } protected String formatRegister(Register value, int base) { @@ -47,6 +55,10 @@ protected void beginObserving() { ControlAndStatusRegisterFile.addRegistersObserver(this); } + protected void beginObserving(int hart) { + ControlAndStatusRegisterFile.addRegistersObserver(this); + } + protected void endObserving() { ControlAndStatusRegisterFile.deleteRegistersObserver(this); } @@ -54,4 +66,4 @@ protected void endObserving() { public void resetRegisters() { ControlAndStatusRegisterFile.resetRegisters(); } -} \ No newline at end of file +} diff --git a/src/rars/venus/registers/FloatingPointWindow.java b/src/rars/venus/registers/FloatingPointWindow.java index 713f8720..81282136 100644 --- a/src/rars/venus/registers/FloatingPointWindow.java +++ b/src/rars/venus/registers/FloatingPointWindow.java @@ -42,9 +42,16 @@ public class FloatingPointWindow extends RegisterBlockWindow { /* ft10 */ "floating point temporary", /* ft11 */ "floating point temporary" }; + private final int hart; public FloatingPointWindow() { super(FloatingPointRegisterFile.getRegisters(), regToolTips, "32-bit single precision IEEE 754 floating point"); + this.hart = -1; + } + + public FloatingPointWindow(int hart) { + super(FloatingPointRegisterFile.getRegisters(hart), regToolTips, "32-bit single precision IEEE 754 floating point", hart); + this.hart = hart; } protected String formatRegister(Register value, int base) { @@ -60,6 +67,10 @@ protected void beginObserving() { FloatingPointRegisterFile.addRegistersObserver(this); } + protected void beginObserving(int hart) { + FloatingPointRegisterFile.addRegistersObserver(this); + } + protected void endObserving() { FloatingPointRegisterFile.deleteRegistersObserver(this); } diff --git a/src/rars/venus/registers/GeneralRegistersPane.java b/src/rars/venus/registers/GeneralRegistersPane.java new file mode 100644 index 00000000..fe10dccb --- /dev/null +++ b/src/rars/venus/registers/GeneralRegistersPane.java @@ -0,0 +1,96 @@ +package rars.venus.registers; + +import rars.venus.GeneralVenusUI; + +import javax.swing.*; + +/* +Copyright (c) 2003-2006, Siva Chowdeswar Nandipati + +Developed by Siva Chowdeswar Nandipati (sivachow@ualberta.ca) + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject +to the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +(MIT license, http://www.opensource.org/licenses/mit-license.html) + */ + +/** + * Contains tabbed areas in the UI to display register contents + * + * @author Sanderson + * @version August 2005 + **/ + +public class GeneralRegistersPane extends JTabbedPane { + private RegistersWindow regsTab; + private FloatingPointWindow fpTab; + private ControlAndStatusWindow csrTab; + + private GeneralVenusUI mainUI; + + /** + * Constructor for the RegistersPane class. + **/ + + public GeneralRegistersPane(GeneralVenusUI appFrame, RegistersWindow regs, FloatingPointWindow cop1, + ControlAndStatusWindow cop0) { + super(); + this.mainUI = appFrame; + regsTab = regs; + fpTab = cop1; + csrTab = cop0; + regsTab.setVisible(true); + fpTab.setVisible(true); + csrTab.setVisible(true); + this.addTab("Registers", regsTab); + this.addTab("Floating Point", fpTab); + this.addTab("Control and Status", csrTab); + this.setToolTipTextAt(0, "CPU registers"); + this.setToolTipTextAt(1, "Floating point unit registers"); + this.setToolTipTextAt(2, "Control and Status registers"); + } + + /** + * Return component containing integer register set. + * + * @return integer register window + */ + public RegistersWindow getRegistersWindow() { + return regsTab; + } + + /** + * Return component containing floating point register set. + * + * @return floating point register window + */ + public FloatingPointWindow getFloatingPointWindow() { + return fpTab; + } + + /** + * Return component containing Control and Status register set. + * + * @return exceptions register window + */ + public ControlAndStatusWindow getControlAndStatusWindow() { + return csrTab; + } +} \ No newline at end of file diff --git a/src/rars/venus/registers/RegisterBlockWindow.java b/src/rars/venus/registers/RegisterBlockWindow.java index 7c94713e..8dfa405a 100644 --- a/src/rars/venus/registers/RegisterBlockWindow.java +++ b/src/rars/venus/registers/RegisterBlockWindow.java @@ -61,7 +61,8 @@ public abstract class RegisterBlockWindow extends JPanel implements Observer { private boolean highlighting; private int highlightRow; private Register[] registers; - + private boolean notMainUI = true; + private int hart; private static final int NAME_COLUMN = 0; private static final int NUMBER_COLUMN = 1; private static final int VALUE_COLUMN = 2; @@ -76,6 +77,7 @@ public RegisterBlockWindow(Register[] registers, String[] registerDescriptions, Simulator.getInstance().addObserver(this); settings = Globals.getSettings(); this.registers = registers; + this.hart = -1; clearHighlighting(); table = new MyTippedJTable(new RegTableModel(setupWindow()), registerDescriptions, new String[]{"Each register has a tool tip describing its usage convention", "Corresponding register number", valueTip}) { @@ -92,10 +94,32 @@ public RegisterBlockWindow(Register[] registers, String[] registerDescriptions, this.setLayout(new BorderLayout()); // table display will occupy entire width if widened this.add(new JScrollPane(table, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED)); } + + public RegisterBlockWindow(Register[] registers, String[] registerDescriptions, String valueTip, int hart) { + Simulator.getInstance(hart).addObserver(this); + settings = Globals.getSettings(); + this.registers = registers; + this.hart = hart; + clearHighlighting(); + table = new MyTippedJTable(new RegTableModel(setupWindow()), registerDescriptions, + new String[]{"Each register has a tool tip describing its usage convention", "Corresponding register number", valueTip}) { + }; + table.getColumnModel().getColumn(NAME_COLUMN).setPreferredWidth(50); + table.getColumnModel().getColumn(NUMBER_COLUMN).setPreferredWidth(25); + table.getColumnModel().getColumn(VALUE_COLUMN).setPreferredWidth(60); + // Display register values (String-ified) right-justified in mono font + table.getColumnModel().getColumn(NAME_COLUMN).setCellRenderer(new RegisterCellRenderer(MonoRightCellRenderer.MONOSPACED_PLAIN_12POINT, SwingConstants.LEFT)); + table.getColumnModel().getColumn(NUMBER_COLUMN).setCellRenderer(new RegisterCellRenderer(MonoRightCellRenderer.MONOSPACED_PLAIN_12POINT, SwingConstants.RIGHT)); + table.getColumnModel().getColumn(VALUE_COLUMN).setCellRenderer(new RegisterCellRenderer(MonoRightCellRenderer.MONOSPACED_PLAIN_12POINT, SwingConstants.RIGHT)); + table.setPreferredScrollableViewportSize(new Dimension(200, 700)); + this.setLayout(new BorderLayout()); // table display will occupy entire width if widened + this.add(new JScrollPane(table, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED)); + } protected abstract String formatRegister(Register value, int base); protected abstract void beginObserving(); + protected abstract void beginObserving(int hart); protected abstract void endObserving(); @@ -153,7 +177,12 @@ public void updateRegisters() { Globals.getGui().getMainPane().getExecutePane().getValueDisplayBase()), i, 2); } } - + public void updateRegisters(int hart) { + for (int i = 0; i < registers.length; i++) { + ((RegTableModel) table.getModel()).setDisplayAndModelValueAt(formatRegister(registers[i], + Globals.getHartWindows().get(hart).getMainPane().getExecutePane().getValueDisplayBase()), i, 2); + } + } /** * Highlight the row corresponding to the given register. * @@ -182,13 +211,16 @@ private void highlightCellForRegister(Register register) { * @param obj Auxiliary object with additional information. */ public void update(Observable observable, Object obj) { - if (observable == rars.simulator.Simulator.getInstance()) { + if (observable == rars.simulator.Simulator.getInstance() || observable == rars.simulator.Simulator.getInstance(hart)) { SimulatorNotice notice = (SimulatorNotice) obj; if (notice.getAction() == SimulatorNotice.SIMULATOR_START) { // Simulated MIPS execution starts. Respond to memory changes if running in timed // or stepped mode. if (notice.getRunSpeed() != RunSpeedPanel.UNLIMITED_SPEED || notice.getMaxSteps() == 1) { - beginObserving(); + if(this.hart == -1) + beginObserving(); + else + beginObserving(hart); this.highlighting = true; } } else { @@ -203,7 +235,6 @@ public void update(Observable observable, Object obj) { // AddressCellRenderer class in DataSegmentWindow.java. this.highlighting = true; this.highlightCellForRegister((Register) observable); - Globals.getGui().getRegistersPane().setSelectedComponent(this); } } } diff --git a/src/rars/venus/registers/RegistersWindow.java b/src/rars/venus/registers/RegistersWindow.java index 694cb4b4..f51671fd 100644 --- a/src/rars/venus/registers/RegistersWindow.java +++ b/src/rars/venus/registers/RegistersWindow.java @@ -12,6 +12,7 @@ public class RegistersWindow extends RegisterBlockWindow { /* * The tips to show when hovering over the names of the registers */ + private int hart; private static final String[] regToolTips = { /* zero */ "constant 0", /* ra */ "return address (used by function call)", @@ -50,6 +51,12 @@ public class RegistersWindow extends RegisterBlockWindow { public RegistersWindow() { super(getRegisters(), regToolTips, "Current 32 bit value"); + hart = -1; + } + + public RegistersWindow(int hart){ + super(getRegisters(hart), regToolTips, "Current 32 bit value", hart); + this.hart = hart; } /* @@ -61,6 +68,12 @@ private static Register[] getRegisters() { out[base.length] = RegisterFile.getProgramCounterRegister(); return out; } + private static Register[] getRegisters(int hart) { + Register[] base = RegisterFile.getRegisters(hart); + Register[] out = Arrays.copyOf(base, base.length + 1); + out[base.length] = RegisterFile.getProgramCounterRegister(hart); + return out; + } protected String formatRegister(Register value, int base) { if (Globals.getSettings().getBooleanSetting(Settings.Bool.RV64_ENABLED)){ @@ -73,7 +86,9 @@ protected String formatRegister(Register value, int base) { protected void beginObserving() { RegisterFile.addRegistersObserver(this); } - + protected void beginObserving(int hart){ + RegisterFile.addRegistersObserver(this, hart); + } protected void endObserving() { RegisterFile.deleteRegistersObserver(this); } diff --git a/src/rars/venus/run/RunAssembleAction.java b/src/rars/venus/run/RunAssembleAction.java index 5e5bec6c..406653a8 100644 --- a/src/rars/venus/run/RunAssembleAction.java +++ b/src/rars/venus/run/RunAssembleAction.java @@ -1,18 +1,20 @@ package rars.venus.run; import rars.*; +import rars.Globals; import rars.riscv.hardware.*; import rars.util.FilenameFinder; import rars.util.SystemIO; import rars.venus.*; import rars.venus.registers.RegistersPane; +import rars.venus.registers.GeneralRegistersPane; import javax.swing.*; import java.awt.event.ActionEvent; import java.io.File; import java.util.ArrayList; - - /* + +/* Copyright (c) 2003-2010, Pete Sanderson and Kenneth Vollmar Developed by Pete Sanderson (psanderson@otterbein.edu) @@ -38,7 +40,7 @@ a copy of this software and associated documentation files (the WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. (MIT license, http://www.opensource.org/licenses/mit-license.html) - */ +*/ /** * Action class for the Run -> Assemble menu item (and toolbar icon) @@ -46,19 +48,22 @@ a copy of this software and associated documentation files (the public class RunAssembleAction extends GuiAction { private static ArrayList programsToAssemble; + private static ArrayList> gProgramsToAssemble; private static boolean extendedAssemblerEnabled; private static boolean warningsAreErrors; // Threshold for adding filename to printed message of files being assembled. private static final int LINE_LENGTH_LIMIT = 60; private VenusUI mainUI; + protected ArrayList hartWindows; - public RunAssembleAction(String name, Icon icon, String descrip, - Integer mnemonic, KeyStroke accel, VenusUI gui) { + public RunAssembleAction(String name, Icon icon, String descrip, Integer mnemonic, KeyStroke accel, VenusUI gui) { super(name, icon, descrip, mnemonic, accel); + Globals.setHartWindows(); mainUI = gui; } - // These are both used by RunResetAction to re-assemble under identical conditions. + // These are both used by RunResetAction to re-assemble under identical + // conditions. public static ArrayList getProgramsToAssemble() { return programsToAssemble; } @@ -72,10 +77,19 @@ static boolean getWarningsAreErrors() { } public void actionPerformed(ActionEvent e) { + hartWindows = Globals.getHartWindows(); String name = this.getValue(Action.NAME).toString(); MessagesPane messagesPane = mainUI.getMessagesPane(); ExecutePane executePane = mainUI.getMainPane().getExecutePane(); RegistersPane registersPane = mainUI.getRegistersPane(); + ArrayList gexecutePanes = new ArrayList<>(); + ArrayList gregistersPanes = new ArrayList<>(); + + for (int i = 0; i < hartWindows.size(); i++) { + gexecutePanes.add(hartWindows.get(i).getMainPane().getExecutePane()); + gregistersPanes.add(hartWindows.get(i).getRegistersPane()); + } + extendedAssemblerEnabled = Globals.getSettings().getBooleanSetting(Settings.Bool.EXTENDED_ASSEMBLER_ENABLED); warningsAreErrors = Globals.getSettings().getBooleanSetting(Settings.Bool.WARNINGS_ARE_ERRORS); if (FileStatus.getFile() != null) { @@ -84,10 +98,15 @@ public void actionPerformed(ActionEvent e) { } try { Globals.program = new RISCVprogram(); + Globals.gPrograms = new ArrayList<>(); + for (int i = 0; i < hartWindows.size(); i++){ + Globals.gPrograms.add(new RISCVprogram()); + } ArrayList filesToAssemble; - if (Globals.getSettings().getBooleanSetting(Settings.Bool.ASSEMBLE_ALL)) {// setting calls for multiple file assembly - filesToAssemble = FilenameFinder.getFilenameList( - new File(FileStatus.getName()).getParent(), Globals.fileExtensions); + if (Globals.getSettings().getBooleanSetting(Settings.Bool.ASSEMBLE_ALL)) {// setting calls for multiple + // file assembly + filesToAssemble = FilenameFinder.getFilenameList(new File(FileStatus.getName()).getParent(), + Globals.fileExtensions); } else { filesToAssemble = new ArrayList<>(); filesToAssemble.add(FileStatus.getName()); @@ -102,12 +121,13 @@ public void actionPerformed(ActionEvent e) { } } String exceptionHandler = null; - if (Globals.getSettings().getBooleanSetting(Settings.Bool.EXCEPTION_HANDLER_ENABLED) && - Globals.getSettings().getExceptionHandler() != null && - Globals.getSettings().getExceptionHandler().length() > 0) { + if (Globals.getSettings().getBooleanSetting(Settings.Bool.EXCEPTION_HANDLER_ENABLED) + && Globals.getSettings().getExceptionHandler() != null + && Globals.getSettings().getExceptionHandler().length() > 0) { exceptionHandler = Globals.getSettings().getExceptionHandler(); } - programsToAssemble = Globals.program.prepareFilesForAssembly(filesToAssemble, FileStatus.getFile().getPath(), exceptionHandler); + programsToAssemble = Globals.program.prepareFilesForAssembly(filesToAssemble, + FileStatus.getFile().getPath(), exceptionHandler); messagesPane.postMessage(buildFileNameList(name + ": assembling ", programsToAssemble)); // added logic to receive any warnings and output them.... DPS 11/28/06 ErrorList warnings = Globals.program.assemble(programsToAssemble, extendedAssemblerEnabled, @@ -115,16 +135,21 @@ public void actionPerformed(ActionEvent e) { if (warnings.warningsOccurred()) { messagesPane.postMessage(warnings.generateWarningReport()); } - messagesPane.postMessage( - name + ": operation completed successfully.\n\n"); + messagesPane.postMessage(name + ": operation completed successfully.\n\n"); FileStatus.setAssembled(true); FileStatus.set(FileStatus.RUNNABLE); - + //TODO RegisterFile.resetRegisters(); FloatingPointRegisterFile.resetRegisters(); ControlAndStatusRegisterFile.resetRegisters(); InterruptController.reset(); - + Globals.reservationTables.reset(); + for (int i = 0; i < hartWindows.size(); i++) { + gexecutePanes.get(i).getTextSegmentWindow().setupTable(); + gexecutePanes.get(i).getLabelsWindow().setupTable(); + gexecutePanes.get(i).getTextSegmentWindow().setCodeHighlighting(true); + gexecutePanes.get(i).getTextSegmentWindow().highlightStepAtPC(i); + } executePane.getTextSegmentWindow().setupTable(); executePane.getDataSegmentWindow().setupTable(); executePane.getDataSegmentWindow().highlightCellForAddress(Memory.dataBaseAddress); @@ -135,34 +160,46 @@ public void actionPerformed(ActionEvent e) { registersPane.getRegistersWindow().clearWindow(); registersPane.getFloatingPointWindow().clearWindow(); registersPane.getControlAndStatusWindow().clearWindow(); + for(int i = 0; i < hartWindows.size(); i++){ + gregistersPanes.get(i).getRegistersWindow().clearWindow(); + gregistersPanes.get(i).getFloatingPointWindow().clearWindow(); + gregistersPanes.get(i).getControlAndStatusWindow().clearWindow(); + hartWindows.get(i).setReset(true); + hartWindows.get(i).setStarted(false); + } mainUI.setReset(true); mainUI.setStarted(false); mainUI.getMainPane().setSelectedComponent(executePane); // Aug. 24, 2005 Ken Vollmar - SystemIO.resetFiles(); // Ensure that I/O "file descriptors" are initialized for a new program run + SystemIO.resetFiles(); // Ensure that I/O "file descriptors" are initialized for a new program run } catch (AssemblyException pe) { String errorReport = pe.errors().generateErrorAndWarningReport(); messagesPane.postMessage(errorReport); - messagesPane.postMessage( - name + ": operation completed with errors.\n\n"); + messagesPane.postMessage(name + ": operation completed with errors.\n\n"); // Select editor line containing first error, and corresponding error message. ArrayList errorMessages = pe.errors().getErrorMessages(); for (ErrorMessage em : errorMessages) { - // No line or position may mean File Not Found (e.g. exception file). Don't try to open. DPS 3-Oct-2010 + // No line or position may mean File Not Found (e.g. exception file). Don't try + // to open. DPS 3-Oct-2010 if (em.getLine() == 0 && em.getPosition() == 0) { continue; } if (!em.isWarning() || warningsAreErrors) { - Globals.getGui().getMessagesPane().selectErrorMessage(em.getFilename(), em.getLine(), em.getPosition()); - // Bug workaround: Line selection does not work correctly for the JEditTextArea editor - // when the file is opened then automatically assembled (assemble-on-open setting). + Globals.getGui().getMessagesPane().selectErrorMessage(em.getFilename(), em.getLine(), + em.getPosition()); + // Bug workaround: Line selection does not work correctly for the JEditTextArea + // editor + // when the file is opened then automatically assembled (assemble-on-open + // setting). // Automatic assemble happens in EditTabbedPane's openFile() method, by invoking - // this method (actionPerformed) explicitly with null argument. Thus e!=null test. + // this method (actionPerformed) explicitly with null argument. Thus e!=null + // test. // DPS 9-Aug-2010 if (e != null) { - Globals.getGui().getMessagesPane().selectEditorTextLine(em.getFilename(), em.getLine(), em.getPosition()); + Globals.getGui().getMessagesPane().selectEditorTextLine(em.getFilename(), em.getLine(), + em.getPosition()); } break; } diff --git a/src/rars/venus/run/RunGoAction.java b/src/rars/venus/run/RunGoAction.java index d4c152dc..164caabc 100644 --- a/src/rars/venus/run/RunGoAction.java +++ b/src/rars/venus/run/RunGoAction.java @@ -10,12 +10,15 @@ import rars.util.SystemIO; import rars.venus.ExecutePane; import rars.venus.FileStatus; +import rars.venus.GeneralExecutePane; +import rars.venus.GeneralVenusUI; import rars.venus.GuiAction; import rars.venus.VenusUI; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; +import java.util.ArrayList; import java.util.Observable; import java.util.Observer; @@ -56,7 +59,9 @@ public class RunGoAction extends GuiAction { public static int maxSteps = defaultMaxSteps; private String name; private ExecutePane executePane; + private ArrayList gexecutePanes = new ArrayList<>(); private VenusUI mainUI; + protected ArrayList hartWindows = Globals.getHartWindows(); public RunGoAction(String name, Icon icon, String descrip, Integer mnemonic, KeyStroke accel, VenusUI gui) { @@ -70,6 +75,9 @@ public RunGoAction(String name, Icon icon, String descrip, public void actionPerformed(ActionEvent e) { name = this.getValue(Action.NAME).toString(); executePane = mainUI.getMainPane().getExecutePane(); + for(int i = 0; i < hartWindows.size(); i++){ + gexecutePanes.add(hartWindows.get(i).getMainPane().getExecutePane()); + } if (FileStatus.isAssembled()) { if (!mainUI.getStarted()) { processProgramArgumentsIfAny(); // DPS 17-July-2008 @@ -77,12 +85,18 @@ public void actionPerformed(ActionEvent e) { if (mainUI.getReset() || mainUI.getStarted()) { mainUI.setStarted(true); // added 8/27/05 - + for(int i = 0; i < hartWindows.size(); i++){ + hartWindows.get(i).setStarted(true); + } mainUI.getMessagesPane().postMessage( name + ": running " + FileStatus.getFile().getName() + "\n\n"); mainUI.getMessagesPane().selectRunMessageTab(); executePane.getTextSegmentWindow().setCodeHighlighting(false); executePane.getTextSegmentWindow().unhighlightAllSteps(); + for(int i = 0; i < hartWindows.size(); i++){ + gexecutePanes.get(i).getTextSegmentWindow().setCodeHighlighting(false); + gexecutePanes.get(i).getTextSegmentWindow().unhighlightAllSteps(); + } //FileStatus.set(FileStatus.RUNNING); mainUI.setMenuState(FileStatus.RUNNING); @@ -142,6 +156,15 @@ public void paused(boolean done, Simulator.Reason pauseReason, SimulationExcepti executePane.getFloatingPointWindow().updateRegisters(); executePane.getControlAndStatusWindow().updateRegisters(); executePane.getDataSegmentWindow().updateValues(); + for(int i = 0; i < hartWindows.size(); i++){ + gexecutePanes.get(i).getTextSegmentWindow().setCodeHighlighting(true); + gexecutePanes.get(i).getTextSegmentWindow().highlightStepAtPC(i); + gexecutePanes.get(i).getRegistersWindow().updateRegisters(); + gexecutePanes.get(i).getFloatingPointWindow().updateRegisters(); + gexecutePanes.get(i).getControlAndStatusWindow().updateRegisters(); + hartWindows.get(i).setReset(false); + + } FileStatus.set(FileStatus.RUNNABLE); mainUI.setReset(false); } @@ -159,14 +182,29 @@ public void stopped(SimulationException pe, Simulator.Reason reason) { executePane.getFloatingPointWindow().updateRegisters(); executePane.getControlAndStatusWindow().updateRegisters(); executePane.getDataSegmentWindow().updateValues(); + for(int i = 0; i < hartWindows.size(); i++){ + gexecutePanes.get(i).getRegistersWindow().updateRegisters(); + gexecutePanes.get(i).getFloatingPointWindow().updateRegisters(); + gexecutePanes.get(i).getControlAndStatusWindow().updateRegisters(); + } FileStatus.set(FileStatus.TERMINATED); + for (GeneralVenusUI hw : hartWindows) { + hw.setMenuStateTerminated(); + } SystemIO.resetFiles(); // close any files opened in MIPS program // Bring CSRs to the front if terminated due to exception. if (pe != null) { + mainUI.getRegistersPane().setSelectedComponent(executePane.getControlAndStatusWindow()); executePane.getTextSegmentWindow().setCodeHighlighting(true); executePane.getTextSegmentWindow().unhighlightAllSteps(); executePane.getTextSegmentWindow().highlightStepAtAddress(RegisterFile.getProgramCounter() - 4); + for(int i = 0; i < hartWindows.size(); i++){ + hartWindows.get(i).getRegistersPane().setSelectedComponent(executePane.getControlAndStatusWindow()); + gexecutePanes.get(i).getTextSegmentWindow().setCodeHighlighting(true); + gexecutePanes.get(i).getTextSegmentWindow().unhighlightAllSteps(); + gexecutePanes.get(i).getTextSegmentWindow().highlightStepAtAddress(RegisterFile.getProgramCounter() - 4); + } } switch (reason) { case NORMAL_TERMINATION: @@ -204,6 +242,11 @@ public void stopped(SimulationException pe, Simulator.Reason reason) { } RunGoAction.resetMaxSteps(); mainUI.setReset(false); + for(int i = 0; i < hartWindows.size(); i++){ + hartWindows.get(i).setReset(false); + } + + } /** @@ -229,4 +272,4 @@ private void processProgramArgumentsIfAny() { } -} \ No newline at end of file +} diff --git a/src/rars/venus/run/RunStepAction.java b/src/rars/venus/run/RunStepAction.java index 96b86bae..161bfbc8 100644 --- a/src/rars/venus/run/RunStepAction.java +++ b/src/rars/venus/run/RunStepAction.java @@ -11,10 +11,13 @@ import rars.venus.FileStatus; import rars.venus.GuiAction; import rars.venus.VenusUI; +import rars.venus.GeneralVenusUI; +import rars.venus.GeneralExecutePane; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; +import java.util.ArrayList; import java.util.Observable; import java.util.Observer; @@ -53,20 +56,27 @@ public class RunStepAction extends GuiAction { private String name; private ExecutePane executePane; + private ArrayList gExecutePanes; private VenusUI mainUI; - + private ArrayList hartWindows; public RunStepAction(String name, Icon icon, String descrip, Integer mnemonic, KeyStroke accel, VenusUI gui) { super(name, icon, descrip, mnemonic, accel); mainUI = gui; + hartWindows = Globals.getHartWindows(); } /** * perform next simulated instruction step. */ public void actionPerformed(ActionEvent e) { + hartWindows = Globals.getHartWindows(); name = this.getValue(Action.NAME).toString(); executePane = mainUI.getMainPane().getExecutePane(); + gExecutePanes = new ArrayList<>(); + for(int i = 0; i < hartWindows.size(); i++){ + gExecutePanes.add(hartWindows.get(i).getMainPane().getExecutePane()); + } if (FileStatus.isAssembled()) { if (!mainUI.getStarted()) { // DPS 17-July-2008 processProgramArgumentsIfAny(); @@ -74,6 +84,10 @@ public void actionPerformed(ActionEvent e) { mainUI.setStarted(true); mainUI.getMessagesPane().selectRunMessageTab(); executePane.getTextSegmentWindow().setCodeHighlighting(true); + for(int i = 0; i < hartWindows.size(); i++){ + hartWindows.get(i).setStarted(true); + gExecutePanes.get(i).getTextSegmentWindow().setCodeHighlighting(true); + } // Setup callback for after step finishes final Observer stopListener = @@ -88,6 +102,12 @@ public void update(Observable o, Object simulator) { Simulator.getInstance().addObserver(stopListener); Globals.program.startSimulation(1, null); + for(int i = 0; i < hartWindows.size(); i++){ + Simulator.getInstance(i).addObserver(stopListener); + Globals.gPrograms.get(i).startSimulation(1, null, i); + gExecutePanes.get(i).getRegistersWindow().updateRegisters(i); + //System.out.println("Hart " + i + " " + RegisterFile.gInstance.get(i).getRegister(6).getValue()); + } } else { // note: this should never occur since "Step" is only enabled after successful assembly. JOptionPane.showMessageDialog(mainUI, "The program must be assembled before it can be run."); @@ -101,14 +121,29 @@ public void stepped(boolean done, Simulator.Reason reason, SimulationException p executePane.getFloatingPointWindow().updateRegisters(); executePane.getControlAndStatusWindow().updateRegisters(); executePane.getDataSegmentWindow().updateValues(); + + for(int i = 0; i < hartWindows.size(); i++){ + gExecutePanes.get(i).getRegistersWindow().updateRegisters(i); + gExecutePanes.get(i).getFloatingPointWindow().updateRegisters(); + gExecutePanes.get(i).getControlAndStatusWindow().updateRegisters(); + } if (!done) { + for(int i = 0; i < hartWindows.size(); i++){ + gExecutePanes.get(i).getTextSegmentWindow().highlightStepAtPC(i); + } executePane.getTextSegmentWindow().highlightStepAtPC(); FileStatus.set(FileStatus.RUNNABLE); } if (done) { RunGoAction.resetMaxSteps(); executePane.getTextSegmentWindow().unhighlightAllSteps(); + for(int i = 0; i < hartWindows.size(); i++){ + gExecutePanes.get(i).getTextSegmentWindow().unhighlightAllSteps(); + } FileStatus.set(FileStatus.TERMINATED); + for (GeneralVenusUI hw : hartWindows) { + hw.setMenuStateTerminated(); + } } if (done && pe == null) { mainUI.getMessagesPane().postMessage( @@ -128,11 +163,23 @@ public void stepped(boolean done, Simulator.Reason reason, SimulationException p "\n" + name + ": execution terminated with errors.\n\n"); mainUI.getRegistersPane().setSelectedComponent(executePane.getControlAndStatusWindow()); FileStatus.set(FileStatus.TERMINATED); // should be redundant. + for (GeneralVenusUI hw : hartWindows) { + hw.setMenuStateTerminated(); + } executePane.getTextSegmentWindow().setCodeHighlighting(true); executePane.getTextSegmentWindow().unhighlightAllSteps(); executePane.getTextSegmentWindow().highlightStepAtAddress(RegisterFile.getProgramCounter() - 4); + for(int i = 0; i < hartWindows.size(); i++){ + hartWindows.get(i).getRegistersPane().setSelectedComponent(gExecutePanes.get(i).getControlAndStatusWindow()); + gExecutePanes.get(i).getTextSegmentWindow().setCodeHighlighting(true); + gExecutePanes.get(i).getTextSegmentWindow().unhighlightAllSteps(); + gExecutePanes.get(i).getTextSegmentWindow().highlightStepAtAddress(RegisterFile.getProgramCounter() - 4); + } } mainUI.setReset(false); + for(int i = 0; i < hartWindows.size(); i++){ + hartWindows.get(i).setReset(false); + } } //////////////////////////////////////////////////////////////////////////////////// @@ -142,10 +189,15 @@ public void stepped(boolean done, Simulator.Reason reason, SimulationException p // $a0 gets argument count (argc), $a1 gets stack address of first arg pointer (argv). private void processProgramArgumentsIfAny() { String programArguments = executePane.getTextSegmentWindow().getProgramArguments(); + ArrayList gProgramArgumentsArrayList = new ArrayList<>(); + for(int i = 0; i < hartWindows.size(); i++){ + gProgramArgumentsArrayList.add(gExecutePanes.get(i).getTextSegmentWindow().getProgramArguments()); + } + //TODO if (programArguments == null || programArguments.length() == 0 || !Globals.getSettings().getBooleanSetting(Settings.Bool.PROGRAM_ARGUMENTS)) { return; } new ProgramArgumentList(programArguments).storeProgramArguments(); } -} \ No newline at end of file +} diff --git a/test/riscv-tests-64/amoaddd.s b/test/riscv-tests-64/amoaddd.s new file mode 100644 index 00000000..bb6f25ab --- /dev/null +++ b/test/riscv-tests-64/amoaddd.s @@ -0,0 +1,53 @@ +.data +.align 3 +amo_operand: .dword 0 + +.text +main: + #------------------------------------------------------------- + # Atomic tests + #------------------------------------------------------------- + +test_2: + li a0, 0xffffffff80000000 + li a1, 0xfffffffffffff800 + la a3, amo_operand + sd a0, 0(a3) + amoadd.d a4, a1, (a3) + li t2, 0xffffffff80000000 + li gp, 2 + bne a4, t2, fail + +test_3: + ld a5, 0(a3) + li t2, 0xffffffff7ffff800 + li gp, 3 + bne a5, t2, fail + +test_4: + amoadd.d a4, a1, (a3) + li t2, 0xffffffff7ffff800 + li gp, 4 + bne a4, t2, fail + +test_5: + ld a5, 0(a3) + li t2, 0xffffffff7ffff000 + li gp, 5 + bne a5, t2, fail + bne zero, gp, pass + +fail: + fence 1, 1 + slli gp, gp, 0x1 + ori gp, gp, 1 + li a7, 93 + mv a0, gp + ecall + +pass: + fence 1, 1 + li gp, 1 + li a7, 93 + li a0, 42 + ecall diff --git a/test/riscv-tests-64/amoandd.s b/test/riscv-tests-64/amoandd.s new file mode 100644 index 00000000..b5182ce7 --- /dev/null +++ b/test/riscv-tests-64/amoandd.s @@ -0,0 +1,54 @@ +.data +.align 3 +amo_operand: .dword 0 + +.text +main: + #------------------------------------------------------------- + # Atomic tests + #------------------------------------------------------------- + +test_2: + li a0, 0xffffffff80000000 + li a1, 0xfffffffffffff800 + la a3, amo_operand + sd a0, 0(a3) + amoand.d a4, a1, (a3) + li t2, 0xffffffff80000000 + li gp, 2 + bne a4, t2, fail + +test_3: + ld a5, 0(a3) + li t2, 0xffffffff80000000 + li gp, 3 + bne a5, t2, fail + +test_4: + li a1, 0x0000000080000000 + amoand.d a4, a1, (a3) + li t2, 0xffffffff80000000 + li gp, 4 + bne a4, t2, fail + +test_5: + ld a5, 0(a3) + li t2, 0x0000000080000000 + li gp, 5 + bne a5, t2, fail + bne zero, gp, pass + +fail: + fence 1, 1 + slli gp, gp, 0x1 + ori gp, gp, 1 + li a7, 93 + mv a0, gp + ecall + +pass: + fence 1, 1 + li gp, 1 + li a7, 93 + li a0, 42 + ecall diff --git a/test/riscv-tests-64/amomaxd.s b/test/riscv-tests-64/amomaxd.s new file mode 100644 index 00000000..8ff48a4f --- /dev/null +++ b/test/riscv-tests-64/amomaxd.s @@ -0,0 +1,55 @@ +.data +.align 3 +amo_operand: .dword 0 + +.text +main: + #------------------------------------------------------------- + # Atomic tests + #------------------------------------------------------------- + +test_2: + li a0, 0xffffffff80000000 + li a1, 0xfffffffffffff800 + la a3, amo_operand + sd a0, 0(a3) + amomax.d a4, a1, (a3) + li t2, 0xffffffff80000000 + li gp, 2 + bne a4, t2, fail + +test_3: + ld a5, 0(a3) + li t2, 0xfffffffffffff800 + li gp, 3 + bne a5, t2, fail + +test_4: + li a1, 1 + sd x0, 0(a3) + amomax.d a4, a1, (a3) + li t2, 0 + li gp, 4 + bne a4, t2, fail + +test_5: + ld a5, 0(a3) + li t2, 1 + li gp, 5 + bne a5, t2, fail + bne zero, gp, pass + +fail: + fence 1, 1 + slli gp, gp, 0x1 + ori gp, gp, 1 + li a7, 93 + mv a0, gp + ecall + +pass: + fence 1, 1 + li gp, 1 + li a7, 93 + li a0, 42 + ecall diff --git a/test/riscv-tests-64/amomaxud.s b/test/riscv-tests-64/amomaxud.s new file mode 100644 index 00000000..a8a3281c --- /dev/null +++ b/test/riscv-tests-64/amomaxud.s @@ -0,0 +1,55 @@ +.data +.align 3 +amo_operand: .dword 0 + +.text +main: + #------------------------------------------------------------- + # Atomic tests + #------------------------------------------------------------- + +test_2: + li a0, 0xffffffff80000000 + li a1, 0xfffffffffffff800 + la a3, amo_operand + sd a0, 0(a3) + amomaxu.d a4, a1, (a3) + li t2, 0xffffffff80000000 + li gp, 2 + bne a4, t2, fail + +test_3: + ld a5, 0(a3) + li t2, 0xfffffffffffff800 + li gp, 3 + bne a5, t2, fail + +test_4: + li a1, 0xffffffffffffffff + sd x0, 0(a3) + amomaxu.d a4, a1, (a3) + li t2, 0 + li gp, 4 + bne a4, t2, fail + +test_5: + ld a5, 0(a3) + li t2, 0xffffffffffffffff + li gp, 5 + bne a5, t2, fail + bne zero, gp, pass + +fail: + fence 1, 1 + slli gp, gp, 0x1 + ori gp, gp, 1 + li a7, 93 + mv a0, gp + ecall + +pass: + fence 1, 1 + li gp, 1 + li a7, 93 + li a0, 42 + ecall diff --git a/test/riscv-tests-64/amomind.s b/test/riscv-tests-64/amomind.s new file mode 100644 index 00000000..142aa1ff --- /dev/null +++ b/test/riscv-tests-64/amomind.s @@ -0,0 +1,55 @@ +.data +.align 3 +amo_operand: .dword 0 + +.text +main: + #------------------------------------------------------------- + # Atomic tests + #------------------------------------------------------------- + +test_2: + li a0, 0xffffffff80000000 + li a1, 0xfffffffffffff800 + la a3, amo_operand + sd a0, 0(a3) + amomin.d a4, a1, (a3) + li t2, 0xffffffff80000000 + li gp, 2 + bne a4, t2, fail + +test_3: + ld a5, 0(a3) + li t2, 0xffffffff80000000 + li gp, 3 + bne a5, t2, fail + +test_4: + li a1, 0xffffffffffffffff + sd x0, 0(a3) + amomin.d a4, a1, (a3) + li t2, 0 + li gp, 4 + bne a4, t2, fail + +test_5: + ld a5, 0(a3) + li t2, 0xffffffffffffffff + li gp, 5 + bne a5, t2, fail + bne zero, gp, pass + +fail: + fence 1, 1 + slli gp, gp, 0x1 + ori gp, gp, 1 + li a7, 93 + mv a0, gp + ecall + +pass: + fence 1, 1 + li gp, 1 + li a7, 93 + li a0, 42 + ecall diff --git a/test/riscv-tests-64/amominud.s b/test/riscv-tests-64/amominud.s new file mode 100644 index 00000000..59e674b8 --- /dev/null +++ b/test/riscv-tests-64/amominud.s @@ -0,0 +1,55 @@ +.data +.align 3 +amo_operand: .dword 0 + +.text +main: + #------------------------------------------------------------- + # Atomic tests + #------------------------------------------------------------- + +test_2: + li a0, 0xffffffff80000000 + li a1, 0xfffffffffffff800 + la a3, amo_operand + sd a0, 0(a3) + amominu.d a4, a1, (a3) + li t2, 0xffffffff80000000 + li gp, 2 + bne a4, t2, fail + +test_3: + ld a5, 0(a3) + li t2, 0xffffffff80000000 + li gp, 3 + bne a5, t2, fail + +test_4: + li a1, 0xffffffffffffffff + sd x0, 0(a3) + amominu.d a4, a1, (a3) + li t2, 0 + li gp, 4 + bne a4, t2, fail + +test_5: + ld a5, 0(a3) + li t2, 0 + li gp, 5 + bne a5, t2, fail + bne zero, gp, pass + +fail: + fence 1, 1 + slli gp, gp, 0x1 + ori gp, gp, 1 + li a7, 93 + mv a0, gp + ecall + +pass: + fence 1, 1 + li gp, 1 + li a7, 93 + li a0, 42 + ecall diff --git a/test/riscv-tests-64/amoord.s b/test/riscv-tests-64/amoord.s new file mode 100644 index 00000000..cc376e46 --- /dev/null +++ b/test/riscv-tests-64/amoord.s @@ -0,0 +1,54 @@ +.data +.align 3 +amo_operand: .dword 0 + +.text +main: + #------------------------------------------------------------- + # Atomic tests + #------------------------------------------------------------- + +test_2: + li a0, 0xffffffff80000000 + li a1, 0xfffffffffffff800 + la a3, amo_operand + sd a0, 0(a3) + amoor.d a4, a1, (a3) + li t2, 0xffffffff80000000 + li gp, 2 + bne a4, t2, fail + +test_3: + ld a5, 0(a3) + li t2, 0xfffffffffffff800 + li gp, 3 + bne a5, t2, fail + +test_4: + li a1, 1 + amoor.d a4, a1, (a3) + li t2, 0xfffffffffffff800 + li gp, 4 + bne a4, t2, fail + +test_5: + ld a5, 0(a3) + li t2, 0xfffffffffffff801 + li gp, 5 + bne a5, t2, fail + bne zero, gp, pass + +fail: + fence 1, 1 + slli gp, gp, 0x1 + ori gp, gp, 1 + li a7, 93 + mv a0, gp + ecall + +pass: + fence 1, 1 + li gp, 1 + li a7, 93 + li a0, 42 + ecall diff --git a/test/riscv-tests-64/amoswapd.s b/test/riscv-tests-64/amoswapd.s new file mode 100644 index 00000000..d6060d99 --- /dev/null +++ b/test/riscv-tests-64/amoswapd.s @@ -0,0 +1,54 @@ +.data +.align 3 +amo_operand: .dword 0 + +.text +main: + #------------------------------------------------------------- + # Atomic tests + #------------------------------------------------------------- + +test_2: + li a0, 0xffffffff80000000 + li a1, 0xfffffffffffff800 + la a3, amo_operand + sd a0, 0(a3) + amoswap.d a4, a1, (a3) + li t2, 0xffffffff80000000 + li gp, 2 + bne a4, t2, fail + +test_3: + ld a5, 0(a3) + li t2, 0xfffffffffffff800 + li gp, 3 + bne a5, t2, fail + +test_4: + li a1, 0x0000000080000000 + amoswap.d a4, a1, (a3) + li t2, 0xfffffffffffff800 + li gp, 4 + bne a4, t2, fail + +test_5: + ld a5, 0(a3) + li t2, 0x0000000080000000 + li gp, 5 + bne a5, t2, fail + bne zero, gp, pass + +fail: + fence 1, 1 + slli gp, gp, 0x1 + ori gp, gp, 1 + li a7, 93 + mv a0, gp + ecall + +pass: + fence 1, 1 + li gp, 1 + li a7, 93 + li a0, 42 + ecall diff --git a/test/riscv-tests-64/amoxord.s b/test/riscv-tests-64/amoxord.s new file mode 100644 index 00000000..6dfc27d2 --- /dev/null +++ b/test/riscv-tests-64/amoxord.s @@ -0,0 +1,54 @@ +.data +.align 3 +amo_operand: .dword 0 + +.text +main: + #------------------------------------------------------------- + # Atomic tests + #------------------------------------------------------------- + +test_2: + li a0, 0xffffffff80000000 + li a1, 0xfffffffffffff800 + la a3, amo_operand + sd a0, 0(a3) + amoxor.d a4, a1, (a3) + li t2, 0xffffffff80000000 + li gp, 2 + bne a4, t2, fail + +test_3: + ld a5, 0(a3) + li t2, 0x000000007ffff800 + li gp, 3 + bne a5, t2, fail + +test_4: + li a1, 1 + amoxor.d a4, a1, (a3) + li t2, 0x000000007ffff800 + li gp, 4 + bne a4, t2, fail + +test_5: + ld a5, 0(a3) + li t2, 0x000000007ffff801 + li gp, 5 + bne a5, t2, fail + bne zero, gp, pass + +fail: + fence 1, 1 + slli gp, gp, 0x1 + ori gp, gp, 1 + li a7, 93 + mv a0, gp + ecall + +pass: + fence 1, 1 + li gp, 1 + li a7, 93 + li a0, 42 + ecall diff --git a/test/riscv-tests/amoaddw.s b/test/riscv-tests/amoaddw.s new file mode 100644 index 00000000..4bafdd15 --- /dev/null +++ b/test/riscv-tests/amoaddw.s @@ -0,0 +1,55 @@ +.data +.align 3 +amo_operand: .dword 0 + +.text +main: + #------------------------------------------------------------- + # Atomic tests + #------------------------------------------------------------- + +test_2: + li a0, 0xffffffff80000000 + li a1, 0xfffffffffffff800 + la a3, amo_operand + sw a0, 0(a3) + amoadd.w a4, a1, (a3) + li t2, 0xffffffff80000000 + li gp, 2 + bne a4, t2, fail + +test_3: + lw a5, 0(a3) + li t2, 0x000000007ffff800 + li gp, 3 + bne a5, t2, fail + +test_4: + lui a1, 0x80000 + amoadd.w a4, a1, (a3) + lui t2, 0x80000 + addi t2, t2, -2048 + li gp, 4 + bne a4, t2, fail + +test_5: + lw a5, 0(a3) + li t2, -2048 + li gp, 5 + bne a5, t2, fail + bne zero, gp, pass + +fail: + fence 1, 1 + slli gp, gp, 0x1 + ori gp, gp, 1 + li a7, 93 + mv a0, gp + ecall + +pass: + fence 1, 1 + li gp, 1 + li a7, 93 + li a0, 42 + ecall diff --git a/test/riscv-tests/amoandw.s b/test/riscv-tests/amoandw.s new file mode 100644 index 00000000..3ec5def6 --- /dev/null +++ b/test/riscv-tests/amoandw.s @@ -0,0 +1,54 @@ +.data +.align 3 +amo_operand: .dword 0 + +.text +main: + #------------------------------------------------------------- + # Atomic tests + #------------------------------------------------------------- + +test_2: + li a0, 0xffffffff80000000 + li a1, 0xfffffffffffff800 + la a3, amo_operand + sw a0, 0(a3) + amoand.w a4, a1, (a3) + li t2, 0xffffffff80000000 + li gp, 2 + bne a4, t2, fail + +test_3: + lw a5, 0(a3) + li t2, 0xffffffff80000000 + li gp, 3 + bne a5, t2, fail + +test_4: + li a1, 0x80000000 + amoand.w a4, a1, (a3) + li t2, 0xffffffff80000000 + li gp, 4 + bne a4, t2, fail + +test_5: + lw a5, 0(a3) + li t2, 0xffffffff80000000 + li gp, 5 + bne a5, t2, fail + bne zero, gp, pass + +fail: + fence 1, 1 + slli gp, gp, 0x1 + ori gp, gp, 1 + li a7, 93 + mv a0, gp + ecall + +pass: + fence 1, 1 + li gp, 1 + li a7, 93 + li a0, 42 + ecall diff --git a/test/riscv-tests/amomaxuw.s b/test/riscv-tests/amomaxuw.s new file mode 100644 index 00000000..d0df56e2 --- /dev/null +++ b/test/riscv-tests/amomaxuw.s @@ -0,0 +1,55 @@ +.data +.align 3 +amo_operand: .dword 0 + +.text +main: + #------------------------------------------------------------- + # Atomic tests + #------------------------------------------------------------- + +test_2: + li a0, 0xffffffff80000000 + li a1, 0xfffffffffffff800 + la a3, amo_operand + sw a0, 0(a3) + amomaxu.w a4, a1, (a3) + li t2, 0xffffffff80000000 + li gp, 2 + bne a4, t2, fail + +test_3: + lw a5, 0(a3) + li t2, 0xfffffffffffff800 + li gp, 3 + bne a5, t2, fail + +test_4: + li a1, 0xffffffffffffffff + sw zero, 0(a3) + amomaxu.w a4, a1, (a3) + li t2, 0 + li gp, 4 + bne a4, t2, fail + +test_5: + lw a5, 0(a3) + li t2, 0xffffffffffffffff + li gp, 5 + bne a5, t2, fail + bne zero, gp, pass + +fail: + fence 1, 1 + slli gp, gp, 0x1 + ori gp, gp, 1 + li a7, 93 + mv a0, gp + ecall + +pass: + fence 1, 1 + li gp, 1 + li a7, 93 + li a0, 42 + ecall diff --git a/test/riscv-tests/amomaxw.s b/test/riscv-tests/amomaxw.s new file mode 100644 index 00000000..5761a67d --- /dev/null +++ b/test/riscv-tests/amomaxw.s @@ -0,0 +1,55 @@ +.data +.align 3 +amo_operand: .dword 0 + +.text +main: + #------------------------------------------------------------- + # Atomic tests + #------------------------------------------------------------- + +test_2: + li a0, 0xffffffff80000000 + li a1, 0xfffffffffffff800 + la a3, amo_operand + sw a0, 0(a3) + amomax.w a4, a1, (a3) + li t2, 0xffffffff80000000 + li gp, 2 + bne a4, t2, fail + +test_3: + lw a5, 0(a3) + li t2, 0xfffffffffffff800 + li gp, 3 + bne a5, t2, fail + +test_4: + li a1, 1 + sw zero, 0(a3) + amomax.w a4, a1, (a3) + li t2, 0 + li gp, 4 + bne a4, t2, fail + +test_5: + lw a5, 0(a3) + li t2, 1 + li gp, 5 + bne a5, t2, fail + bne zero, gp, pass + +fail: + fence 1, 1 + slli gp, gp, 0x1 + ori gp, gp, 1 + li a7, 93 + mv a0, gp + ecall + +pass: + fence 1, 1 + li gp, 1 + li a7, 93 + li a0, 42 + ecall diff --git a/test/riscv-tests/amominuw.s b/test/riscv-tests/amominuw.s new file mode 100644 index 00000000..fdadf1a6 --- /dev/null +++ b/test/riscv-tests/amominuw.s @@ -0,0 +1,55 @@ +.data +.align 3 +amo_operand: .dword 0 + +.text +main: + #------------------------------------------------------------- + # Atomic tests + #------------------------------------------------------------- + +test_2: + li a0, 0xffffffff80000000 + li a1, 0xfffffffffffff800 + la a3, amo_operand + sw a0, 0(a3) + amominu.w a4, a1, (a3) + li t2, 0xffffffff80000000 + li gp, 2 + bne a4, t2, fail + +test_3: + lw a5, 0(a3) + li t2, 0xffffffff80000000 + li gp, 3 + bne a5, t2, fail + +test_4: + li a1, 0xffffffffffffffff + sw zero, 0(a3) + amominu.w a4, a1, (a3) + li t2, 0 + li gp, 4 + bne a4, t2, fail + +test_5: + lw a5, 0(a3) + li t2, 0 + li gp, 5 + bne a5, t2, fail + bne zero, gp, pass + +fail: + fence 1, 1 + slli gp, gp, 0x1 + ori gp, gp, 1 + li a7, 93 + mv a0, gp + ecall + +pass: + fence 1, 1 + li gp, 1 + li a7, 93 + li a0, 42 + ecall diff --git a/test/riscv-tests/amominw.s b/test/riscv-tests/amominw.s new file mode 100644 index 00000000..82f786a1 --- /dev/null +++ b/test/riscv-tests/amominw.s @@ -0,0 +1,55 @@ +.data +.align 3 +amo_operand: .dword 0 + +.text +main: + #------------------------------------------------------------- + # Atomic tests + #------------------------------------------------------------- + +test_2: + li a0, 0xffffffff80000000 + li a1, 0xfffffffffffff800 + la a3, amo_operand + sw a0, 0(a3) + amomin.w a4, a1, (a3) + li t2, 0xffffffff80000000 + li gp, 2 + bne a4, t2, fail + +test_3: + lw a5, 0(a3) + li t2, 0xffffffff80000000 + li gp, 3 + bne a5, t2, fail + +test_4: + li a1, 0xffffffffffffffff + sw zero, 0(a3) + amomin.w a4, a1, (a3) + li t2, 0 + li gp, 4 + bne a4, t2, fail + +test_5: + lw a5, 0(a3) + li t2, 0xffffffffffffffff + li gp, 5 + bne a5, t2, fail + bne zero, gp, pass + +fail: + fence 1, 1 + slli gp, gp, 0x1 + ori gp, gp, 1 + li a7, 93 + mv a0, gp + ecall + +pass: + fence 1, 1 + li gp, 1 + li a7, 93 + li a0, 42 + ecall diff --git a/test/riscv-tests/amoorw.s b/test/riscv-tests/amoorw.s new file mode 100644 index 00000000..8d8e0951 --- /dev/null +++ b/test/riscv-tests/amoorw.s @@ -0,0 +1,54 @@ +.data +.align 3 +amo_operand: .dword 0 + +.text +main: + #------------------------------------------------------------- + # Atomic tests + #------------------------------------------------------------- + +test_2: + li a0, 0xffffffff80000000 + li a1, 0xfffffffffffff800 + la a3, amo_operand + sw a0, 0(a3) + amoor.w a4, a1, (a3) + li t2, 0xffffffff80000000 + li gp, 2 + bne a4, t2, fail + +test_3: + lw a5, 0(a3) + li t2, 0xfffffffffffff800 + li gp, 3 + bne a5, t2, fail + +test_4: + li a1, 1 + amoor.w a4, a1, (a3) + li t2, 0xfffffffffffff800 + li gp, 4 + bne a4, t2, fail + +test_5: + lw a5, 0(a3) + li t2, 0xfffffffffffff801 + li gp, 5 + bne a5, t2, fail + bne zero, gp, pass + +fail: + fence 1, 1 + slli gp, gp, 0x1 + ori gp, gp, 1 + li a7, 93 + mv a0, gp + ecall + +pass: + fence 1, 1 + li gp, 1 + li a7, 93 + li a0, 42 + ecall diff --git a/test/riscv-tests/amoswapw.s b/test/riscv-tests/amoswapw.s new file mode 100644 index 00000000..8afbd968 --- /dev/null +++ b/test/riscv-tests/amoswapw.s @@ -0,0 +1,54 @@ +.data +.align 3 +amo_operand: .dword 0 + +.text +main: + #------------------------------------------------------------- + # Atomic tests + #------------------------------------------------------------- + +test_2: + li a0, 0xffffffff80000000 + li a1, 0xfffffffffffff800 + la a3, amo_operand + sw a0, 0(a3) + amoswap.w a4, a1, (a3) + li t2, 0xffffffff80000000 + li gp, 2 + bne a4, t2, fail + +test_3: + lw a5, 0(a3) + li t2, 0xfffffffffffff800 + li gp, 3 + bne a5, t2, fail + +test_4: + li a1, 0x80000000 + amoswap.w a4, a1, (a3) + li t2, 0xfffffffffffff800 + li gp, 4 + bne a4, t2, fail + +test_5: + lw a5, 0(a3) + li t2, 0xffffffff80000000 + li gp, 5 + bne a5, t2, fail + bne zero, gp, pass + +fail: + fence 1, 1 + slli gp, gp, 0x1 + ori gp, gp, 1 + li a7, 93 + mv a0, gp + ecall + +pass: + fence 1, 1 + li gp, 1 + li a7, 93 + li a0, 42 + ecall diff --git a/test/riscv-tests/amoxorw.s b/test/riscv-tests/amoxorw.s new file mode 100644 index 00000000..8078f06b --- /dev/null +++ b/test/riscv-tests/amoxorw.s @@ -0,0 +1,54 @@ +.data +.align 3 +amo_operand: .dword 0 + +.text +main: + #------------------------------------------------------------- + # Atomic tests + #------------------------------------------------------------- + +test_2: + li a0, 0xffffffff80000000 + li a1, 0xfffffffffffff800 + la a3, amo_operand + sw a0, 0(a3) + amoxor.w a4, a1, (a3) + li t2, 0xffffffff80000000 + li gp, 2 + bne a4, t2, fail + +test_3: + lw a5, 0(a3) + li t2, 0x7ffff800 + li gp, 3 + bne a5, t2, fail + +test_4: + li a1, 0xc0000001 + amoxor.w a4, a1, (a3) + li t2, 0x7ffff800 + li gp, 4 + bne a4, t2, fail + +test_5: + lw a5, 0(a3) + li t2, 0xffffffffbffff801 + li gp, 5 + bne a5, t2, fail + bne zero, gp, pass + +fail: + fence 1, 1 + slli gp, gp, 0x1 + ori gp, gp, 1 + li a7, 93 + mv a0, gp + ecall + +pass: + fence 1, 1 + li gp, 1 + li a7, 93 + li a0, 42 + ecall diff --git a/test/riscv-tests/lrsc.s b/test/riscv-tests/lrsc.s new file mode 100644 index 00000000..029af77b --- /dev/null +++ b/test/riscv-tests/lrsc.s @@ -0,0 +1,93 @@ +.data +coreid: .word 0 +barrier: .word 0 +foo: .word 0 + +.text +main: + #------------------------------------------------------------- + # Atomic tests + #------------------------------------------------------------- + +# get a unique core id +la a0, coreid +li a1, 1 +amoadd.w a2, a1, (a0) + +# for now, only run this on core 0 +lbl_1: +li a3, 1 +bgeu a2, a3, lbl_1 + +lbl_2: +lw a1, (a0) +bltu a1, a3, lbl_2 + +test_2: + la a0, foo + li a5, 0xdeadbeef + sc.w a4, a5, (a0) + li t2, 1 + li gp, 2 + bne a4, t2, fail + +test_3: + lw a4, foo + li t2, 0 + li gp, 3 + bne a4, t2, fail + +# have each core add its coreid+1 to foo 128 times +la a0, foo +li a1, 0x80 +addi a2, a2, 1 +lbl_3: lr.w a4, (a0) +add a4, a4, a2 +sc.w a4, a4, (a0) +bnez a4, lbl_3 +addi a1, a1, -1 +bnez a1, lbl_3 + +# wait for all cores to finish +la a0, barrier +li a1, 1 +amoadd.w x0, a1, (a0) +lbl_4: lw a1, (a0) +blt a1, a3, lbl_4 +fence 1, 1 + +test_5: + lw a0, foo + slli a1, a3, 6 + lbl_5: sub a0, a0, a1 + addi a3, a3, -1 + bgez a3, lbl_5 + li t2, 0 + li gp, 5 + bne a0, t2, fail + +test_6: + la a0, foo + lbl_6: lr.w a1, (a0) + sc.w a1, x0, (a0) + bnez a1, lbl_6 + sc.w a1, x0 (a0) + li t2, 1 + li gp, 6 + bne a1, t2, fail + +bne zero, gp, pass +fail: + fence 1, 1 + slli gp, gp, 0x1 + ori gp, gp, 1 + li a7, 93 + mv a0, gp + ecall + +pass: + fence 1, 1 + li gp, 1 + li a7, 93 + li a0, 42 + ecall