From b3b778c79ac22a579bbea2543b2ad34df2fd711a Mon Sep 17 00:00:00 2001 From: hneemann Date: Sat, 20 Aug 2016 13:10:09 +0200 Subject: [PATCH] Improved debugging of processors. Now its more intuitive. Also updating of listings and value tables are disabled in fast run mode. --- src/main/dig/processor/Processor.dig | 4 ++ .../java/de/neemann/digital/core/Model.java | 1 + .../de/neemann/digital/core/ModelEvent.java | 5 ++ .../de/neemann/digital/core/element/Keys.java | 6 +++ .../de/neemann/digital/core/memory/ROM.java | 1 + .../digital/gui/DigitalRemoteInterface.java | 25 +++++++--- .../java/de/neemann/digital/gui/Main.java | 50 +++++++++++++++---- .../digital/gui/components/ProbeDialog.java | 14 +++++- .../components/listing/ROMListingDialog.java | 45 ++++++++++++++--- .../digital/gui/remote/DigitalHandler.java | 24 +++++---- .../digital/gui/remote/RemoteException.java | 10 ++++ src/main/resources/lang/lang_de.xml | 5 +- src/main/resources/lang/lang_en.xml | 5 +- 13 files changed, 156 insertions(+), 39 deletions(-) create mode 100644 src/main/java/de/neemann/digital/gui/remote/RemoteException.java diff --git a/src/main/dig/processor/Processor.dig b/src/main/dig/processor/Processor.dig index b969889e8..2ec8afe4a 100644 --- a/src/main/dig/processor/Processor.dig +++ b/src/main/dig/processor/Processor.dig @@ -144,6 +144,10 @@ ROM + + isProgramMemory + true + Bits 16 diff --git a/src/main/java/de/neemann/digital/core/Model.java b/src/main/java/de/neemann/digital/core/Model.java index b256e3650..4b8e2b9b8 100644 --- a/src/main/java/de/neemann/digital/core/Model.java +++ b/src/main/java/de/neemann/digital/core/Model.java @@ -231,6 +231,7 @@ public class Model implements Iterable { int count = aBreak.getCycles() * 2; boolean lastIn = brVal.getBool(); + fireEvent(ModelEvent.FASTRUN); for (int i = 0; i < count; i++) { clkVal.setBool(!clkVal.getBool()); doStep(); diff --git a/src/main/java/de/neemann/digital/core/ModelEvent.java b/src/main/java/de/neemann/digital/core/ModelEvent.java index f09a6ee9c..f506ca72f 100644 --- a/src/main/java/de/neemann/digital/core/ModelEvent.java +++ b/src/main/java/de/neemann/digital/core/ModelEvent.java @@ -24,6 +24,11 @@ public enum ModelEvent { */ STEP, + /** + * Fast run is started. + */ + FASTRUN, + /** * A break is detected. */ diff --git a/src/main/java/de/neemann/digital/core/element/Keys.java b/src/main/java/de/neemann/digital/core/element/Keys.java index 23e6069a8..30edb9307 100644 --- a/src/main/java/de/neemann/digital/core/element/Keys.java +++ b/src/main/java/de/neemann/digital/core/element/Keys.java @@ -157,6 +157,12 @@ public final class Keys { public static final Key SHOW_LISTING = new Key<>("showList", false); + /** + * flag to set a ROM as programm memory + */ + public static final Key IS_PROGRAM_MEMORY + = new Key<>("isProgramMemory", false); + /** * flag to enable the ROMs auto load function */ diff --git a/src/main/java/de/neemann/digital/core/memory/ROM.java b/src/main/java/de/neemann/digital/core/memory/ROM.java index b466a04f2..2ccc79922 100644 --- a/src/main/java/de/neemann/digital/core/memory/ROM.java +++ b/src/main/java/de/neemann/digital/core/memory/ROM.java @@ -34,6 +34,7 @@ public class ROM extends Node implements Element { .addAttribute(Keys.ADDR_BITS) .addAttribute(Keys.LABEL) .addAttribute(Keys.DATA) + .addAttribute(Keys.IS_PROGRAM_MEMORY) .addAttribute(Keys.AUTO_RELOAD_ROM) .addAttribute(Keys.SHOW_LISTING); diff --git a/src/main/java/de/neemann/digital/gui/DigitalRemoteInterface.java b/src/main/java/de/neemann/digital/gui/DigitalRemoteInterface.java index 7543543ec..f841482ad 100644 --- a/src/main/java/de/neemann/digital/gui/DigitalRemoteInterface.java +++ b/src/main/java/de/neemann/digital/gui/DigitalRemoteInterface.java @@ -1,5 +1,7 @@ package de.neemann.digital.gui; +import de.neemann.digital.gui.remote.RemoteException; + import java.io.File; /** @@ -13,28 +15,37 @@ public interface DigitalRemoteInterface { * Loads the given file to the data rom * * @param file the file to load - * @return true if loading was successful + * @throws RemoteException RemoteException */ - boolean loadRom(File file); + void loadRom(File file) throws RemoteException; /** * Starts the model - * @return true if start was successful + * @throws RemoteException RemoteException */ - boolean start(); + void start() throws RemoteException; + + /** + * Starts the model in debug mode + * @throws RemoteException RemoteException + */ + void debug() throws RemoteException; /** * performs a single step + * @throws RemoteException RemoteException */ - void doSingleStep(); + void doSingleStep() throws RemoteException; /** * runs model to the next BRK instruction + * @throws RemoteException RemoteException */ - void runToBreak(); + void runToBreak() throws RemoteException; /** * stops the model + * @throws RemoteException RemoteException */ - void stop(); + void stop() throws RemoteException; } diff --git a/src/main/java/de/neemann/digital/gui/Main.java b/src/main/java/de/neemann/digital/gui/Main.java index 4dc23b67c..961fb54e3 100644 --- a/src/main/java/de/neemann/digital/gui/Main.java +++ b/src/main/java/de/neemann/digital/gui/Main.java @@ -11,6 +11,7 @@ import de.neemann.digital.core.element.Key; import de.neemann.digital.core.element.Keys; import de.neemann.digital.core.io.In; import de.neemann.digital.core.io.Out; +import de.neemann.digital.core.memory.DataField; import de.neemann.digital.core.memory.ROM; import de.neemann.digital.core.wiring.Clock; import de.neemann.digital.draw.elements.Circuit; @@ -31,6 +32,7 @@ import de.neemann.digital.gui.components.test.DataException; import de.neemann.digital.gui.components.test.TestCaseElement; import de.neemann.digital.gui.components.test.TestResultDialog; import de.neemann.digital.gui.remote.DigitalHandler; +import de.neemann.digital.gui.remote.RemoteException; import de.neemann.digital.gui.remote.RemoteSever; import de.neemann.digital.gui.state.State; import de.neemann.digital.gui.state.StateManager; @@ -729,7 +731,7 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave, E for (ROM rom : model.findNode(ROM.class)) if (rom.showListing()) try { - windowPosManager.register("rom" + (i++), new ROMListingDialog(this, rom)).setVisible(true); + windowPosManager.register("rom" + (i++), new ROMListingDialog(this, rom, model, modelSync)).setVisible(true); } catch (IOException e) { new ErrorMessage(Lang.get("msg_errorReadingListing_N0", rom.getHexFile().toString())).addCause(e).show(this); } @@ -944,20 +946,36 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave, E // remote interface start //********************** - @Override - public boolean loadRom(File file) { - boolean found = false; + public VisualElement getProgramRomFromCircuit() throws RemoteException { + VisualElement rom = null; ArrayList el = circuitComponent.getCircuit().getElements(); for (VisualElement e : el) { if (e.equalsDescription(ROM.DESCRIPTION)) { ElementAttributes attr = e.getElementAttributes(); - if (attr.get(Keys.AUTO_RELOAD_ROM)) { - attr.setFile(ROM.LAST_DATA_FILE_KEY, file); - found = true; + if (attr.get(Keys.IS_PROGRAM_MEMORY)) { + if (rom != null) + throw new RemoteException(Lang.get("msg_moreThenOneRomFound")); + rom = e; } } } - return found; + if (rom == null) + throw new RemoteException(Lang.get("msg_noRomFound")); + + return rom; + } + + @Override + public void loadRom(File file) throws RemoteException { + VisualElement rom = getProgramRomFromCircuit(); + ElementAttributes attr = rom.getElementAttributes(); + try { + DataField df = new DataField(file); + attr.set(Keys.DATA, df); + attr.setFile(ROM.LAST_DATA_FILE_KEY, file); // needed in debug mode to load listing! + } catch (IOException e) { + throw new RemoteException(e.getMessage()); + } } @Override @@ -987,11 +1005,23 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave, E runToBreakAction.actionPerformed(null); } + private void setDebug(boolean debug) throws RemoteException { + VisualElement rom = getProgramRomFromCircuit(); + rom.getElementAttributes().set(Keys.SHOW_LISTING, debug); + } + @Override - public boolean start() { + public void debug() throws RemoteException { + setDebug(true); runModelState.enter(false); circuitComponent.hasChanged(); - return true; + } + + @Override + public void start() throws RemoteException { + setDebug(false); + runModelState.enter(true); + circuitComponent.hasChanged(); } @Override diff --git a/src/main/java/de/neemann/digital/gui/components/ProbeDialog.java b/src/main/java/de/neemann/digital/gui/components/ProbeDialog.java index 68e62e561..96348ff00 100644 --- a/src/main/java/de/neemann/digital/gui/components/ProbeDialog.java +++ b/src/main/java/de/neemann/digital/gui/components/ProbeDialog.java @@ -24,6 +24,7 @@ public class ProbeDialog extends JDialog implements ModelStateObserver { private final ModelEvent type; private final SignalTableModel tableModel; + private boolean tableUpdateEnable = true; /** * Creates a new instance @@ -73,7 +74,18 @@ public class ProbeDialog extends JDialog implements ModelStateObserver { @Override public void handleEvent(ModelEvent event) { if (event == type || event == ModelEvent.MANUALCHANGE) { - SwingUtilities.invokeLater(tableModel::fireChanged); + if (tableUpdateEnable) + SwingUtilities.invokeLater(tableModel::fireChanged); + } + switch (event) { + case FASTRUN: + tableUpdateEnable = false; + break; + case BREAK: + case STOPPED: + tableUpdateEnable = true; + SwingUtilities.invokeLater(tableModel::fireChanged); + break; } } diff --git a/src/main/java/de/neemann/digital/gui/components/listing/ROMListingDialog.java b/src/main/java/de/neemann/digital/gui/components/listing/ROMListingDialog.java index f4bfdaa22..f9000bd60 100644 --- a/src/main/java/de/neemann/digital/gui/components/listing/ROMListingDialog.java +++ b/src/main/java/de/neemann/digital/gui/components/listing/ROMListingDialog.java @@ -1,7 +1,11 @@ package de.neemann.digital.gui.components.listing; +import de.neemann.digital.core.Model; +import de.neemann.digital.core.ModelEvent; +import de.neemann.digital.core.ModelStateObserver; import de.neemann.digital.core.Observer; import de.neemann.digital.core.memory.ROM; +import de.neemann.digital.gui.sync.Sync; import de.neemann.digital.lang.Lang; import javax.swing.*; @@ -17,27 +21,27 @@ import java.io.IOException; * * @author hneemann */ -public class ROMListingDialog extends JDialog implements Observer { +public class ROMListingDialog extends JDialog implements Observer, ModelStateObserver { private final ROM rom; private final Listing listing; private final JList list; private int lastAddr = -1; + private boolean updateViewEnable = true; /** * Creates a new instance * * @param parent the parent frame * @param rom the rom element + * @param model the model * @throws IOException IOException */ - public ROMListingDialog(JFrame parent, ROM rom) throws IOException { + public ROMListingDialog(JFrame parent, ROM rom, Model model, Sync modelSync) throws IOException { super(parent, Lang.get("win_listing"), false); setDefaultCloseOperation(DISPOSE_ON_CLOSE); - - this.rom = rom; - setDefaultCloseOperation(DISPOSE_ON_CLOSE); setAlwaysOnTop(true); + this.rom = rom; File filename = rom.getHexFile(); String name = filename.getName(); @@ -55,12 +59,18 @@ public class ROMListingDialog extends JDialog implements Observer { addWindowListener(new WindowAdapter() { @Override public void windowOpened(WindowEvent e) { - rom.addObserver(ROMListingDialog.this); + modelSync.access(() -> { + rom.addObserver(ROMListingDialog.this); + model.addObserver(ROMListingDialog.this); + }); } @Override public void windowClosed(WindowEvent e) { - rom.removeObserver(ROMListingDialog.this); + modelSync.access(() -> { + rom.removeObserver(ROMListingDialog.this); + model.removeObserver(ROMListingDialog.this); + }); } }); @@ -76,6 +86,13 @@ public class ROMListingDialog extends JDialog implements Observer { public void hasChanged() { int addr = (int) rom.getRomAddress(); if (addr != lastAddr) { + updateView(addr); + lastAddr = addr; + } + } + + private void updateView(int addr) { + if (updateViewEnable) { Integer line = listing.getLine(addr); if (line != null) { SwingUtilities.invokeLater(() -> { @@ -83,8 +100,20 @@ public class ROMListingDialog extends JDialog implements Observer { list.setSelectedIndex(line); }); } - lastAddr = addr; } } + @Override + public void handleEvent(ModelEvent event) { + switch (event) { + case FASTRUN: + updateViewEnable = false; + break; + case BREAK: + case STOPPED: + updateViewEnable = true; + updateView(lastAddr); + break; + } + } } diff --git a/src/main/java/de/neemann/digital/gui/remote/DigitalHandler.java b/src/main/java/de/neemann/digital/gui/remote/DigitalHandler.java index c6cabce3a..2ceea3ce4 100644 --- a/src/main/java/de/neemann/digital/gui/remote/DigitalHandler.java +++ b/src/main/java/de/neemann/digital/gui/remote/DigitalHandler.java @@ -30,17 +30,24 @@ public class DigitalHandler implements HandlerInterface { args = request.substring(p + 1); } - return handle(command.toLowerCase(), args); + try { + handle(command.toLowerCase(), args); + return "ok"; + } catch (RemoteException e) { + return e.getMessage(); + } } - private String handle(String command, String args) { + private void handle(String command, String args) throws RemoteException { switch (command) { case "step": digitalRemoteInterface.doSingleStep(); break; case "start": - if (!digitalRemoteInterface.start()) - return Lang.get("msg_errorCreatingModel"); + digitalRemoteInterface.start(); + break; + case "debug": + digitalRemoteInterface.debug(); break; case "run": digitalRemoteInterface.runToBreak(); @@ -50,15 +57,10 @@ public class DigitalHandler implements HandlerInterface { break; case "load": File file = new File(args); - if (file.exists()) { - if (!digitalRemoteInterface.loadRom(file)) - return Lang.get("msg_noRomFound"); - } else - return Lang.get("msg_errorFileNotFound", args); + digitalRemoteInterface.loadRom(file); break; default: - return Lang.get("msg_remoteUnknownCommand", command); + throw new RemoteException(Lang.get("msg_remoteUnknownCommand", command)); } - return "ok"; } } diff --git a/src/main/java/de/neemann/digital/gui/remote/RemoteException.java b/src/main/java/de/neemann/digital/gui/remote/RemoteException.java new file mode 100644 index 000000000..d00f9b3c0 --- /dev/null +++ b/src/main/java/de/neemann/digital/gui/remote/RemoteException.java @@ -0,0 +1,10 @@ +package de.neemann.digital.gui.remote; + +/** + * Created by hneemann on 20.08.16. + */ +public class RemoteException extends Exception { + public RemoteException(String message) { + super(message); + } +} diff --git a/src/main/resources/lang/lang_de.xml b/src/main/resources/lang/lang_de.xml index 6a2e1208f..2950daa4c 100644 --- a/src/main/resources/lang/lang_de.xml +++ b/src/main/resources/lang/lang_de.xml @@ -238,6 +238,8 @@ Zur Analyse können Sie die Schaltung im Gatterschrittmodus ausführen. Testdaten Breite in Pixel Höhe in Pixel + Programmspeicher + Zeichnet dieses ROM als Programmspeicher aus. Es kann damit von einer externen IDE beschrieben werden. Logisch Arithmetik FlipFlops @@ -384,7 +386,8 @@ Die Icons stammen aus dem Tango Desktop Project. Ausgänge Pin {0}: {1} Die Änderung erfordert einen Neustart! - Kein ROM im Model gefunden! Im ROM muss Automatisches Laden eingeschaltet sein! + Kein ROM im Model gefunden! Ein ROM muss als Programmspeicher gewählt werden! + Mehr als einen Programmspeicher gefunden. Es darf nur einen Programmspeicher geben. Geben Sie einen Ausdruck ein: Fehler bei der Ausführung der Tests: Testergebnis diff --git a/src/main/resources/lang/lang_en.xml b/src/main/resources/lang/lang_en.xml index 16bf78dc8..708ed8b8c 100644 --- a/src/main/resources/lang/lang_en.xml +++ b/src/main/resources/lang/lang_en.xml @@ -238,6 +238,8 @@ To analyse you can run the circuit in single gate step mode. Testdata Width in pixels Height in pixels + Program Memory + Makes this ROM to program memory. So it can be accessed by an external IDE. Logic Arithmetic FlipFlops @@ -383,7 +385,8 @@ The icons are taken from the Tango Desktop Project. Onputs Pin {0}: {1} Change needs a restart to take effect! - No ROM found! ROM needs to be set to auto reload mode. + No ROM found! ROM needs to be set to be program memory. + More then one ROM found! Only one ROM must be set to be program memory. Could not find file: {0} Command {0} unknown! Enter an expression: