diff --git a/src/rars/venus/VenusUI.java b/src/rars/venus/VenusUI.java index 782048c1..74a70d9e 100644 --- a/src/rars/venus/VenusUI.java +++ b/src/rars/venus/VenusUI.java @@ -2,9 +2,11 @@ import rars.Globals; import rars.Settings; +import rars.SimulationException; import rars.riscv.InstructionSet; import rars.riscv.dump.DumpFormatLoader; import rars.simulator.Simulator; +import rars.simulator.SimulatorNotice; import rars.venus.registers.ControlAndStatusWindow; import rars.venus.registers.FloatingPointWindow; import rars.venus.registers.RegistersPane; @@ -1044,6 +1046,120 @@ public static int getMenuState() { return menuState; } + /** + * Method called when a simulation is started to update the UI. + * + * @return true if the ui was updated to start the simulation. + */ + public boolean onStartedSimulation(String name) { + ExecutePane executePane = getMainPane().getExecutePane(); + + if (!FileStatus.isAssembled()) { + // note: this should never occur since "Go" and "Step" are only enabled after successful assembly. + JOptionPane.showMessageDialog(this, "The program must be assembled before it can be run."); + return false; + } + + if (!getStarted()) { + getMessagesPane().processProgramArgumentsIfAny(); + } + + if (!getReset() && !getStarted()) { + // This should never occur because at termination the Go and Step buttons are disabled. + JOptionPane.showMessageDialog(this, "reset " + mainUI.getReset() + " started " + mainUI.getStarted());//"You must reset before you can execute the program again."); + return false; + } + + setStarted(true); // added 8/27/05 + + getMessagesPane().postMessage(name + ": running " + FileStatus.getFile().getName() + "\n\n"); + getMessagesPane().selectRunMessageTab(); + executePane.getTextSegmentWindow().setCodeHighlighting(false); + executePane.getTextSegmentWindow().unhighlightAllSteps(); + //clears highlight of registers and data segment if the run step was used before + executePane.getRegistersWindow().clearHighlighting(); + executePane.getDataSegmentWindow().clearHighlighting(); + //FileStatus.set(FileStatus.RUNNING); + setMenuState(FileStatus.RUNNING); + + return true; + } + + /** + * Method called when a simulation is stopped to update the UI. + */ + public void onStoppedSimulation(String name, SimulatorNotice notice) { + ExecutePane executePane = getMainPane().getExecutePane(); + executePane.getRegistersWindow().updateRegisters(); + executePane.getFloatingPointWindow().updateRegisters(); + executePane.getControlAndStatusWindow().updateRegisters(); + executePane.getDataSegmentWindow().updateValues(); + + if (notice.getDone()) { + RunGoAction.resetMaxSteps(); + executePane.getTextSegmentWindow().unhighlightAllSteps(); + executePane.getTextSegmentWindow().setCodeHighlighting(false); + FileStatus.set(FileStatus.TERMINATED); + } else { + executePane.getTextSegmentWindow().setCodeHighlighting(true); + executePane.getTextSegmentWindow().highlightStepAtPC(); + FileStatus.set(FileStatus.RUNNABLE); + } + + Simulator.Reason reason = notice.getReason(); + switch (reason) { + case NORMAL_TERMINATION: + mainUI.getMessagesPane().postMessage( + "\n" + name + ": execution completed successfully.\n\n"); + mainUI.getMessagesPane().postRunMessage( + "\n-- program is finished running (" + Globals.exitCode + ") --\n\n"); + mainUI.getMessagesPane().selectRunMessageTab(); + break; + case CLIFF_TERMINATION: + mainUI.getMessagesPane().postMessage( + "\n" + name + ": execution terminated by null instruction.\n\n"); + mainUI.getMessagesPane().postRunMessage( + "\n-- program is finished running (dropped off bottom) --\n\n"); + mainUI.getMessagesPane().selectRunMessageTab(); + break; + case EXCEPTION: + SimulationException pe = notice.getException(); + mainUI.getMessagesPane().postMessage( + pe.error().generateReport()); + mainUI.getMessagesPane().postMessage( + "\n" + name + ": execution terminated with errors.\n\n"); + mainUI.getMessagesPane().postRunMessage("\n"+pe.error().getMessage()); + break; + case STOP: + mainUI.getMessagesPane().postMessage( + "\n" + name + ": execution terminated by user.\n\n"); + mainUI.getMessagesPane().selectMessageTab(); + break; + case MAX_STEPS: + int maxSteps = notice.getMaxSteps(); + if (maxSteps != 1) { + // do not display something on Step Action + mainUI.getMessagesPane().postMessage( + "\n" + name + ": execution step limit of " + maxSteps + " exceeded.\n\n"); + mainUI.getMessagesPane().selectMessageTab(); + } + break; + case BREAKPOINT: + mainUI.getMessagesPane().postMessage( + "\n" + name + ": execution paused at breakpoint: " + FileStatus.getFile().getName() + "\n\n"); + break; + case PAUSE: + mainUI.getMessagesPane().postMessage( + "\n" + name + ": execution paused by user: " + FileStatus.getFile().getName() + "\n\n"); + break; + default: + // Ne devrait pas arriver + throw new IllegalStateException("Unexpected value: " + reason); + } + + mainUI.setReset(false); + } + /** * To set whether the register values are reset. * diff --git a/src/rars/venus/run/RunGoAction.java b/src/rars/venus/run/RunGoAction.java index 7aa58a67..0fdd2329 100644 --- a/src/rars/venus/run/RunGoAction.java +++ b/src/rars/venus/run/RunGoAction.java @@ -54,8 +54,6 @@ public class RunGoAction extends GuiAction { public static int defaultMaxSteps = -1; // "forever", formerly 10000000; // 10 million public static int maxSteps = defaultMaxSteps; - private String name; - private ExecutePane executePane; private VenusUI mainUI; public RunGoAction(String name, Icon icon, String descrip, @@ -68,146 +66,26 @@ public RunGoAction(String name, Icon icon, String descrip, * Action to take when GO is selected -- run the MIPS program! */ public void actionPerformed(ActionEvent e) { - name = this.getValue(Action.NAME).toString(); - executePane = mainUI.getMainPane().getExecutePane(); - if (FileStatus.isAssembled()) { - if (!mainUI.getStarted()) { - mainUI.getMessagesPane().processProgramArgumentsIfAny(); // DPS 17-July-2008 - } - if (mainUI.getReset() || mainUI.getStarted()) { - - mainUI.setStarted(true); // added 8/27/05 - - mainUI.getMessagesPane().postMessage( - name + ": running " + FileStatus.getFile().getName() + "\n\n"); - mainUI.getMessagesPane().selectRunMessageTab(); - executePane.getTextSegmentWindow().setCodeHighlighting(false); - executePane.getTextSegmentWindow().unhighlightAllSteps(); - //clears highlight of registers and data segment if the run step was used before - executePane.getRegistersWindow().clearHighlighting(); - executePane.getDataSegmentWindow().clearHighlighting(); - //FileStatus.set(FileStatus.RUNNING); - mainUI.setMenuState(FileStatus.RUNNING); - - // Setup cleanup procedures for the simulation - final Observer stopListener = - new Observer() { - public void update(Observable o, Object simulator) { - SimulatorNotice notice = ((SimulatorNotice) simulator); - if (notice.getAction() != SimulatorNotice.SIMULATOR_STOP) return; - Simulator.Reason reason = notice.getReason(); - if (reason == Simulator.Reason.PAUSE || reason == Simulator.Reason.BREAKPOINT) { - EventQueue.invokeLater(()->paused(notice.getDone(), reason, notice.getException())); - } else { - EventQueue.invokeLater(()->stopped(notice.getException(), reason)); - } - o.deleteObserver(this); - } - }; - Simulator.getInstance().addObserver(stopListener); - - int[] breakPoints = executePane.getTextSegmentWindow().getSortedBreakPointsArray(); - Globals.program.startSimulation(maxSteps, breakPoints); - } else { - // This should never occur because at termination the Go and Step buttons are disabled. - JOptionPane.showMessageDialog(mainUI, "reset " + mainUI.getReset() + " started " + mainUI.getStarted());//"You must reset before you can execute the program again."); - } - } else { - // note: this should never occur since "Go" is only enabled after successful assembly. - JOptionPane.showMessageDialog(mainUI, "The program must be assembled before it can be run."); - } - } - - /** - * Method to be called when Pause is selected through menu/toolbar/shortcut. This should only - * happen when MIPS program is running (FileStatus.RUNNING). See VenusUI.java for enabled - * status of menu items based on FileStatus. Set GUI as if at breakpoint or executing - * step by step. - */ - - public void paused(boolean done, Simulator.Reason pauseReason, SimulationException pe) { - // I doubt this can happen (pause when execution finished), but if so treat it as stopped. - if (done) { - stopped(pe, Simulator.Reason.NORMAL_TERMINATION); + String name = this.getValue(Action.NAME).toString(); + if (!mainUI.onStartedSimulation(name)) { return; } - if (pauseReason == Simulator.Reason.BREAKPOINT) { - mainUI.getMessagesPane().postMessage( - name + ": execution paused at breakpoint: " + FileStatus.getFile().getName() + "\n\n"); - } else { - mainUI.getMessagesPane().postMessage( - name + ": execution paused by user: " + FileStatus.getFile().getName() + "\n\n"); - } - mainUI.getMessagesPane().selectMessageTab(); - executePane.getTextSegmentWindow().setCodeHighlighting(true); - executePane.getTextSegmentWindow().highlightStepAtPC(); - executePane.getRegistersWindow().updateRegisters(); - executePane.getFloatingPointWindow().updateRegisters(); - executePane.getControlAndStatusWindow().updateRegisters(); - executePane.getDataSegmentWindow().updateValues(); - FileStatus.set(FileStatus.RUNNABLE); - mainUI.setReset(false); - } - - /** - * Method to be called when Stop is selected through menu/toolbar/shortcut. This should only - * happen when MIPS program is running (FileStatus.RUNNING). See VenusUI.java for enabled - * status of menu items based on FileStatus. Display finalized values as if execution - * terminated due to completion or exception. - */ - public void stopped(SimulationException pe, Simulator.Reason reason) { - // show final register and data segment values. - executePane.getRegistersWindow().updateRegisters(); - executePane.getFloatingPointWindow().updateRegisters(); - executePane.getControlAndStatusWindow().updateRegisters(); - executePane.getDataSegmentWindow().updateValues(); - FileStatus.set(FileStatus.TERMINATED); - SystemIO.resetFiles(); // close any files opened in MIPS program - if (pe != null) { - // Do not bring CSRs to the front if terminated due to exception. - // It's annoying, and confusing for the beginners - executePane.getTextSegmentWindow().setCodeHighlighting(true); - executePane.getTextSegmentWindow().unhighlightAllSteps(); - executePane.getTextSegmentWindow().highlightStepAtAddress(RegisterFile.getProgramCounter() - 4); - } - switch (reason) { - case NORMAL_TERMINATION: - mainUI.getMessagesPane().postMessage( - "\n" + name + ": execution completed successfully.\n\n"); - mainUI.getMessagesPane().postRunMessage( - "\n-- program is finished running (" + Globals.exitCode + ") --\n\n"); - mainUI.getMessagesPane().selectRunMessageTab(); - break; - case CLIFF_TERMINATION: - mainUI.getMessagesPane().postMessage( - "\n" + name + ": execution terminated by null instruction.\n\n"); - mainUI.getMessagesPane().postRunMessage( - "\n-- program is finished running (dropped off bottom) --\n\n"); - mainUI.getMessagesPane().selectRunMessageTab(); - break; - case EXCEPTION: - mainUI.getMessagesPane().postMessage( - pe.error().generateReport()); - mainUI.getMessagesPane().postMessage( - "\n" + name + ": execution terminated with errors.\n\n"); - mainUI.getMessagesPane().postRunMessage("\n"+pe.error().getMessage()); - break; - case STOP: - mainUI.getMessagesPane().postMessage( - "\n" + name + ": execution terminated by user.\n\n"); - mainUI.getMessagesPane().selectMessageTab(); - break; - case MAX_STEPS: - mainUI.getMessagesPane().postMessage( - "\n" + name + ": execution step limit of " + maxSteps + " exceeded.\n\n"); - mainUI.getMessagesPane().selectMessageTab(); - break; - default: - // should never get here, because the other two cases are covered by paused() - } - RunGoAction.resetMaxSteps(); - mainUI.setReset(false); + // Setup cleanup procedures for the simulation + final Observer stopListener = + new Observer() { + public void update(Observable o, Object simulator) { + SimulatorNotice notice = ((SimulatorNotice) simulator); + if (notice.getAction() != SimulatorNotice.SIMULATOR_STOP) return; + EventQueue.invokeLater(() -> mainUI.onStoppedSimulation(name, notice)); + o.deleteObserver(this); + } + }; + Simulator.getInstance().addObserver(stopListener); + + ExecutePane executePane = mainUI.getMainPane().getExecutePane(); + int[] breakPoints = executePane.getTextSegmentWindow().getSortedBreakPointsArray(); + Globals.program.startSimulation(maxSteps, breakPoints); } /** diff --git a/src/rars/venus/run/RunStepAction.java b/src/rars/venus/run/RunStepAction.java index 2166d1b3..15fcd1f1 100644 --- a/src/rars/venus/run/RunStepAction.java +++ b/src/rars/venus/run/RunStepAction.java @@ -51,8 +51,6 @@ a copy of this software and associated documentation files (the */ public class RunStepAction extends GuiAction { - private String name; - private ExecutePane executePane; private VenusUI mainUI; public RunStepAction(String name, Icon icon, String descrip, @@ -65,76 +63,22 @@ public RunStepAction(String name, Icon icon, String descrip, * perform next simulated instruction step. */ public void actionPerformed(ActionEvent e) { - name = this.getValue(Action.NAME).toString(); - executePane = mainUI.getMainPane().getExecutePane(); - if (FileStatus.isAssembled()) { - if (!mainUI.getStarted()) { // DPS 17-July-2008 - mainUI.getMessagesPane().processProgramArgumentsIfAny(); - } - mainUI.setStarted(true); - mainUI.getMessagesPane().selectRunMessageTab(); - executePane.getTextSegmentWindow().setCodeHighlighting(true); - - // Setup callback for after step finishes - final Observer stopListener = - new Observer() { - public void update(Observable o, Object simulator) { - SimulatorNotice notice = ((SimulatorNotice) simulator); - if (notice.getAction() != SimulatorNotice.SIMULATOR_STOP) return; - EventQueue.invokeLater(() -> stepped(notice.getDone(), notice.getReason(), notice.getException())); - o.deleteObserver(this); - } - }; - Simulator.getInstance().addObserver(stopListener); - executePane.getRegistersWindow().clearHighlighting(); //clears highlight of previous step - executePane.getDataSegmentWindow().clearHighlighting(); - - Globals.program.startSimulation(1, null); - } 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."); + String name = this.getValue(Action.NAME).toString(); + if (!mainUI.onStartedSimulation(name)) { + return; } - } - // When step is completed, control returns here (from execution thread, indirectly) - // to update the GUI. - public void stepped(boolean done, Simulator.Reason reason, SimulationException pe) { - executePane.getRegistersWindow().updateRegisters(); - executePane.getFloatingPointWindow().updateRegisters(); - executePane.getControlAndStatusWindow().updateRegisters(); - executePane.getDataSegmentWindow().updateValues(); - if (!done) { - executePane.getTextSegmentWindow().highlightStepAtPC(); - FileStatus.set(FileStatus.RUNNABLE); - } - if (done) { - RunGoAction.resetMaxSteps(); - executePane.getTextSegmentWindow().unhighlightAllSteps(); - executePane.getTextSegmentWindow().setCodeHighlighting(false); - FileStatus.set(FileStatus.TERMINATED); - } - if (done && pe == null) { - mainUI.getMessagesPane().postMessage( - "\n" + name + ": execution " + - ((reason == Simulator.Reason.CLIFF_TERMINATION) ? "terminated due to null instruction." - : "completed successfully.") + "\n\n"); - mainUI.getMessagesPane().postRunMessage( - "\n-- program is finished running" + - ((reason == Simulator.Reason.CLIFF_TERMINATION) ? "(dropped off bottom)" : " (" + Globals.exitCode + ")") + " --\n\n"); - mainUI.getMessagesPane().selectRunMessageTab(); - } - if (pe != null) { - RunGoAction.resetMaxSteps(); - mainUI.getMessagesPane().postMessage( - pe.error().generateReport()); - mainUI.getMessagesPane().postMessage( - "\n" + name + ": execution terminated with errors.\n\n"); - mainUI.getMessagesPane().postRunMessage("\n"+pe.error().getMessage()); - FileStatus.set(FileStatus.TERMINATED); // should be redundant. - executePane.getTextSegmentWindow().setCodeHighlighting(true); - executePane.getTextSegmentWindow().unhighlightAllSteps(); - executePane.getTextSegmentWindow().highlightStepAtAddress(RegisterFile.getProgramCounter() - 4); - } - mainUI.setReset(false); + // Setup callback for after step finishes + final Observer stopListener = + new Observer() { + public void update(Observable o, Object simulator) { + SimulatorNotice notice = ((SimulatorNotice) simulator); + if (notice.getAction() != SimulatorNotice.SIMULATOR_STOP) return; + EventQueue.invokeLater(() -> mainUI.onStoppedSimulation(name, notice)); + o.deleteObserver(this); + } + }; + Simulator.getInstance().addObserver(stopListener); + Globals.program.startSimulation(1, null); } } \ No newline at end of file