diff --git a/src/main/java/de/neemann/digital/core/element/ElementAttributes.java b/src/main/java/de/neemann/digital/core/element/ElementAttributes.java index a7c02c8b4..0fc1ac0af 100644 --- a/src/main/java/de/neemann/digital/core/element/ElementAttributes.java +++ b/src/main/java/de/neemann/digital/core/element/ElementAttributes.java @@ -73,6 +73,13 @@ public class ElementAttributes implements HGSMap { value = (VALUE) value.toString(); attributes.put(key.getKey(), value); } + + // needed to fix files with int pin numbers! + if (key == Keys.LAST_DATA_FILE && value instanceof String) { + value = (VALUE) new File(value.toString()); + attributes.put(key.getKey(), value); + } + return value; } } 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 865e8cd83..ab4e37276 100644 --- a/src/main/java/de/neemann/digital/core/element/Keys.java +++ b/src/main/java/de/neemann/digital/core/element/Keys.java @@ -381,6 +381,12 @@ public final class Keys { public static final Key AUTO_RELOAD_ROM = new Key<>("autoReload", false).setSecondary(); + /** + * The last used ROM data file + */ + public static final Key LAST_DATA_FILE + = new Key.KeyFile("lastDataFile", new File("")).setDependsOn(AUTO_RELOAD_ROM).setSecondary(); + /** * flag to show the data table window */ 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 3efb0e5d9..85bcd1e84 100644 --- a/src/main/java/de/neemann/digital/core/memory/ROM.java +++ b/src/main/java/de/neemann/digital/core/memory/ROM.java @@ -5,7 +5,6 @@ */ package de.neemann.digital.core.memory; -import de.neemann.digital.FileLocator; import de.neemann.digital.core.*; import de.neemann.digital.core.element.Element; import de.neemann.digital.core.element.ElementAttributes; @@ -25,10 +24,6 @@ import static de.neemann.digital.core.element.PinInfo.input; * A ROM module. */ public class ROM extends Node implements Element, ROMInterface, ProgramMemory { - /** - * Key used to store the source file in the attribute set - */ - public final static String LAST_DATA_FILE_KEY = "lastDataFile"; /** * The ROMs {@link ElementTypeDescription} @@ -44,6 +39,7 @@ public class ROM extends Node implements Element, ROMInterface, ProgramMemory { .addAttribute(Keys.INT_FORMAT) .addAttribute(Keys.IS_PROGRAM_MEMORY) .addAttribute(Keys.AUTO_RELOAD_ROM) + .addAttribute(Keys.LAST_DATA_FILE) .supportsHDL(); private DataField data; @@ -51,14 +47,14 @@ public class ROM extends Node implements Element, ROMInterface, ProgramMemory { private final ObservableValue output; private final int addrBits; private final int dataBits; - private final File hexFile; private final boolean autoLoad; private final boolean isProgramMemory; + private final ElementAttributes attr; + private final String label; private ObservableValue addrIn; private ObservableValue selIn; private int addr; private boolean sel; - private String label; /** * Creates a new instance @@ -71,12 +67,12 @@ public class ROM extends Node implements Element, ROMInterface, ProgramMemory { data = attr.get(Keys.DATA); addrBits = attr.get(Keys.ADDR_BITS); autoLoad = attr.get(Keys.AUTO_RELOAD_ROM); + if (autoLoad) + this.attr = attr; + else + this.attr = null; label = attr.getLabel(); isProgramMemory = attr.isProgramMemory(); - if (autoLoad) { - hexFile = attr.getFile(LAST_DATA_FILE_KEY); - } else - hexFile = null; formatter = attr.getValueFormatter(); } @@ -118,10 +114,10 @@ public class ROM extends Node implements Element, ROMInterface, ProgramMemory { @Override public void init(Model model) throws NodeException { if (autoLoad) { - if (hexFile == null) + if (attr == null) throw new NodeException(Lang.get("err_ROM_noFileGivenToLoad"), this, -1, null); try { - File f = new FileLocator(hexFile).setLibraryRoot(model.getRootPath()).locate(); + File f = attr.getFile(Keys.LAST_DATA_FILE, model.getRootPath()); data = Importer.read(f, dataBits); } catch (IOException e) { throw new NodeException(e.getMessage(), this, -1, null); diff --git a/src/main/java/de/neemann/digital/gui/components/AttributeDialog.java b/src/main/java/de/neemann/digital/gui/components/AttributeDialog.java index 80a9eb7e6..854dbe2f7 100644 --- a/src/main/java/de/neemann/digital/gui/components/AttributeDialog.java +++ b/src/main/java/de/neemann/digital/gui/components/AttributeDialog.java @@ -20,6 +20,7 @@ import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; +import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -376,6 +377,17 @@ public class AttributeDialog extends JDialog { return null; } + /** + * @return the root file or null if not available + */ + public File getRootFile() { + File root = null; + Main main = getMain(); + if (main != null) + root = main.getLibrary().getRootFilePath(); + return root; + } + /** * @return the visual element of this dialog, maybe null */ diff --git a/src/main/java/de/neemann/digital/gui/components/DataEditor.java b/src/main/java/de/neemann/digital/gui/components/DataEditor.java index 57fd71dd3..8099f1d9c 100644 --- a/src/main/java/de/neemann/digital/gui/components/DataEditor.java +++ b/src/main/java/de/neemann/digital/gui/components/DataEditor.java @@ -40,6 +40,7 @@ import java.util.StringTokenizer; */ public class DataEditor extends JDialog { private static final Color MYGRAY = new Color(230, 230, 230); + private static File lastUsedFileName; private final ValueFormatter addrFormat; private final int addrBits; private final DataField localDataField; @@ -144,11 +145,10 @@ public class DataEditor extends JDialog { @Override public void actionPerformed(ActionEvent e) { JFileChooser fc = new MyFileChooser(); - if (fileName != null) - fc.setSelectedFile(fileName); + setFileNameTo(fc); fc.setFileFilter(new FileNameExtensionFilter("hex", "hex")); if (fc.showOpenDialog(DataEditor.this) == JFileChooser.APPROVE_OPTION) { - fileName = fc.getSelectedFile(); + setFileName(fc.getSelectedFile()); try { DataField dataRead = Importer.read(fc.getSelectedFile(), dataBits) .trimValues(addrBits, dataBits); @@ -164,12 +164,11 @@ public class DataEditor extends JDialog { @Override public void actionPerformed(ActionEvent e) { JFileChooser fc = new MyFileChooser(); - if (fileName != null) - fc.setSelectedFile(fileName); + setFileNameTo(fc); fc.setFileFilter(new FileNameExtensionFilter("hex", "hex")); new SaveAsHelper(DataEditor.this, fc, "hex").checkOverwrite( file -> { - fileName = fc.getSelectedFile(); + setFileName(file); localDataField.saveTo(file); } ); @@ -266,14 +265,17 @@ public class DataEditor extends JDialog { * @param fileName the filename */ public void setFileName(File fileName) { - this.fileName = fileName; + if (fileName.exists()) { + this.fileName = fileName; + lastUsedFileName = fileName; + } } - /** - * @return the file name last used - */ - public File getFileName() { - return fileName; + private void setFileNameTo(JFileChooser fc) { + if (fileName != null) + fc.setSelectedFile(fileName); + else if (lastUsedFileName != null) + fc.setSelectedFile(lastUsedFileName); } /** diff --git a/src/main/java/de/neemann/digital/gui/components/EditorFactory.java b/src/main/java/de/neemann/digital/gui/components/EditorFactory.java index 2ce518fee..00aa07277 100644 --- a/src/main/java/de/neemann/digital/gui/components/EditorFactory.java +++ b/src/main/java/de/neemann/digital/gui/components/EditorFactory.java @@ -5,7 +5,6 @@ */ package de.neemann.digital.gui.components; -import de.neemann.digital.FileLocator; import de.neemann.digital.core.Bits; import de.neemann.digital.core.*; import de.neemann.digital.core.element.*; @@ -14,8 +13,6 @@ import de.neemann.digital.core.extern.PortDefinition; import de.neemann.digital.core.io.InValue; import de.neemann.digital.core.io.MIDIHelper; import de.neemann.digital.core.memory.DataField; -import de.neemann.digital.core.memory.ROM; -import de.neemann.digital.core.memory.importer.Importer; import de.neemann.digital.core.memory.rom.ROMManger; import de.neemann.digital.draw.elements.PinException; import de.neemann.digital.draw.elements.VisualElement; @@ -25,7 +22,6 @@ import de.neemann.digital.draw.model.InverterConfig; import de.neemann.digital.draw.model.ModelCreator; import de.neemann.digital.draw.shapes.custom.CustomShapeDescription; import de.neemann.digital.gui.Main; -import de.neemann.digital.gui.SaveAsHelper; import de.neemann.digital.gui.components.table.ShowStringDialog; import de.neemann.digital.gui.components.testing.TestCaseDescriptionEditor; import de.neemann.digital.lang.Lang; @@ -640,62 +636,19 @@ public final class EditorFactory { int dataBits = attr.get(Keys.BITS); int addrBits = getAddrBits(attr); DataEditor de = new DataEditor(panel, data, dataBits, addrBits, false, SyncAccess.NOSYNC, attr.getValueFormatter()); - de.setFileName(new FileLocator(attr.getFile(ROM.LAST_DATA_FILE_KEY)) - .setupWithMain(getAttributeDialog().getMain()) - .locate()); + if (attr.get(Keys.AUTO_RELOAD_ROM)) + de.setFileName(attr.getFile(Keys.LAST_DATA_FILE, getAttributeDialog().getRootFile())); if (de.showDialog()) { DataField mod = de.getModifiedDataField(); if (!data.equals(mod)) majorModification = true; data = mod; - attr.setFile(ROM.LAST_DATA_FILE_KEY, de.getFileName()); } } catch (EditorParseException e1) { new ErrorMessage(Lang.get("msg_invalidEditorValue")).addCause(e1).show(panel); } } }.createJButton()); - panel.add(new ToolTipAction(Lang.get("btn_reload")) { - @Override - public void actionPerformed(ActionEvent e) { - try { - getAttributeDialog().storeEditedValues(); - int dataBits = attr.get(Keys.BITS); - data = Importer.read(new FileLocator(attr.getFile(ROM.LAST_DATA_FILE_KEY)) - .setupWithMain(getAttributeDialog().getMain()) - .locate(), dataBits) - .trimValues(getAddrBits(attr), dataBits); - } catch (IOException e1) { - new ErrorMessage(Lang.get("msg_errorReadingFile")).addCause(e1).show(panel); - } catch (EditorParseException e1) { - new ErrorMessage(Lang.get("msg_invalidEditorValue")).addCause(e1).show(panel); - } - } - } - .setEnabledChain(attr.getFile(ROM.LAST_DATA_FILE_KEY) != null) - .setToolTip(Lang.get("btn_reload_tt")) - .createJButton() - ); - panel.add(new ToolTipAction(Lang.get("btn_save")) { - @Override - public void actionPerformed(ActionEvent e) { - try { - getAttributeDialog().storeEditedValues(); - final File file = new FileLocator(attr.getFile(ROM.LAST_DATA_FILE_KEY)) - .setupWithMain(getAttributeDialog().getMain()) - .locate(); - data.saveTo(SaveAsHelper.checkSuffix(file, "hex")); - } catch (IOException e1) { - new ErrorMessage(Lang.get("msg_errorWritingFile")).addCause(e1).show(panel); - } catch (EditorParseException e1) { - new ErrorMessage(Lang.get("msg_invalidEditorValue")).addCause(e1).show(panel); - } - } - } - .setEnabledChain(attr.getFile(ROM.LAST_DATA_FILE_KEY) != null) - .setToolTip(Lang.get("btn_saveAsHex_tt")) - .createJButton() - ); return panel; } @@ -814,10 +767,7 @@ public final class EditorFactory { if (app != null) { try { getAttributeDialog().storeEditedValues(); - File root = null; - Main main = getAttributeDialog().getMain(); - if (main != null) - root = main.getLibrary().getRootFilePath(); + File root = getAttributeDialog().getRootFile(); final boolean consistent = app.ensureConsistency(elementAttributes, root); if (consistent) getAttributeDialog().updateEditedValues(); diff --git a/src/main/java/de/neemann/digital/hdl/hgs/Context.java b/src/main/java/de/neemann/digital/hdl/hgs/Context.java index 508655cdf..dc8fec597 100644 --- a/src/main/java/de/neemann/digital/hdl/hgs/Context.java +++ b/src/main/java/de/neemann/digital/hdl/hgs/Context.java @@ -681,14 +681,11 @@ public class Context implements HGSMap { @Override public Object call(Context c, ArrayList args) throws HGSEvalException { - String name = args.get(0).value(c).toString(); + File name = new File(args.get(0).value(c).toString()); int dataBits = Value.toInt(args.get(1).value(c)); - FileLocator fileLocator = new FileLocator(name); - if (c.contains(BASE_FILE_KEY)) - fileLocator.setBaseFile((File) c.getVar(BASE_FILE_KEY)); - File hexFile = fileLocator.locate(); + File hexFile = new FileLocator(name).setLibraryRoot(c.getRootPath()).locate(); - if (hexFile == null) + if (hexFile == null || !hexFile.exists()) throw new HGSEvalException("File " + name + " not found! Is circuit saved?"); try { @@ -709,9 +706,7 @@ public class Context implements HGSMap { @Override public Object call(Context c, ArrayList args) throws HGSEvalException { File f = new File(args.get(0).value(c).toString()); - File root = c.getRootPath(); - if (root != null) - f = new FileLocator(f).setLibraryRoot(root).locate(); + f = new FileLocator(f).setLibraryRoot(c.getRootPath()).locate(); try { return Application.readCode(f); } catch (IOException e) { diff --git a/src/main/resources/lang/lang_de.xml b/src/main/resources/lang/lang_de.xml index 839c6946b..cf7ae39e5 100644 --- a/src/main/resources/lang/lang_de.xml +++ b/src/main/resources/lang/lang_de.xml @@ -19,10 +19,7 @@ Bearbeiten Weiter bearbeiten Laden - Neu Laden - Letzte Datei noch einmal laden Speichern - Als HEX-Datei speichern. Erzeugen Erzeugt eine Schaltung in einem eigenen Fenster. Permanent Bearbeiten @@ -1323,6 +1320,8 @@ Sind evtl. die Namen der Variablen nicht eindeutig? Höhe des Symbols, wenn diese Schaltung in eine andere eingefügt wird. Bei jedem Start automatisch neu laden. Lädt das HEX-File bei jedem Modelstart neu. + Datei + Datei die in das ROM geladen wird! Tausche Selektorposition Mit dieser Option kann der Anschluss des Selektors auf die andere Seite des Multiplexers verschoben werden. Zahlenformat diff --git a/src/main/resources/lang/lang_en.xml b/src/main/resources/lang/lang_en.xml index 5002e1be1..db8c7bac9 100644 --- a/src/main/resources/lang/lang_en.xml +++ b/src/main/resources/lang/lang_en.xml @@ -19,10 +19,7 @@ Edit Continue editing Load - Reload - Reload last HEX file Save - Save as HEX file. Create Create a circuit in a separate window Edit detached @@ -1304,6 +1301,8 @@ Height of symbol if this circuit is used as an component in an other circuit. Reload at model start Reloads the HEX file every time the model is started. + File + File to be loaded into the ROM. Flip selector position This option allows you to move te selector pin to the opposite side of the diff --git a/src/main/resources/lang/lang_es.xml b/src/main/resources/lang/lang_es.xml index ebeda0ffb..122081588 100644 --- a/src/main/resources/lang/lang_es.xml +++ b/src/main/resources/lang/lang_es.xml @@ -25,10 +25,7 @@ In the file howTo.md you can find more details about translations. Editar Seguir editando Cargar - Recargar - Recargar último archivo HEX Guardar - Guardar como archivo HEX Crear Crear un circuito en otra ventana Editar por separado diff --git a/src/main/resources/lang/lang_es_ref.xml b/src/main/resources/lang/lang_es_ref.xml index 0d938d299..4f339fe84 100644 --- a/src/main/resources/lang/lang_es_ref.xml +++ b/src/main/resources/lang/lang_es_ref.xml @@ -24,10 +24,7 @@ In the file howTo.md you can find more details about translations. Edit Continue editing Load - Reload - Reload last HEX file Save - Save as HEX file. Create Create a circuit in a separate window Edit detached diff --git a/src/main/resources/lang/lang_fr.xml b/src/main/resources/lang/lang_fr.xml index 7702fed13..e152ab2fc 100644 --- a/src/main/resources/lang/lang_fr.xml +++ b/src/main/resources/lang/lang_fr.xml @@ -25,10 +25,7 @@ In the file howTo.md you can find more details about translations. Éditer Continuer l'édition Charger - Recharger - Recharger le dernier fichier HEX Enregistrer - Enregistrer en fichier HEX. Créer Créer un circuit dans une fenêtre séparée. Éditer séparément diff --git a/src/main/resources/lang/lang_fr_ref.xml b/src/main/resources/lang/lang_fr_ref.xml index ab88d6862..843432416 100644 --- a/src/main/resources/lang/lang_fr_ref.xml +++ b/src/main/resources/lang/lang_fr_ref.xml @@ -24,10 +24,7 @@ In the file howTo.md you can find more details about translations. Edit Continue editing Load - Reload - Reload last HEX file Save - Save as HEX file. Create Create a circuit in a separate window Edit detached diff --git a/src/main/resources/lang/lang_pt.xml b/src/main/resources/lang/lang_pt.xml index 97e8d363c..132659561 100644 --- a/src/main/resources/lang/lang_pt.xml +++ b/src/main/resources/lang/lang_pt.xml @@ -25,10 +25,7 @@ In the file howTo.md you can find more details about translations. Editar Continuar edição Carregar - Recarregar - Recarregar último arquivo em hexadecimal Salvar - Salvar como arquivo HEX. Criar Criar circuito em janela separada Editar em separado diff --git a/src/main/resources/lang/lang_pt_ref.xml b/src/main/resources/lang/lang_pt_ref.xml index b89cb5a13..9dfe18943 100644 --- a/src/main/resources/lang/lang_pt_ref.xml +++ b/src/main/resources/lang/lang_pt_ref.xml @@ -24,10 +24,7 @@ In the file howTo.md you can find more details about translations. Edit Continue editing Load - Reload - Reload last HEX file Save - Save as HEX file. Create Create a circuit in a separate window Edit detached diff --git a/src/main/resources/lang/lang_zh.xml b/src/main/resources/lang/lang_zh.xml index 2967ed9e4..c023c3c23 100644 --- a/src/main/resources/lang/lang_zh.xml +++ b/src/main/resources/lang/lang_zh.xml @@ -25,10 +25,7 @@ In the file howTo.md you can find more details about translations. 编辑 继续编辑 载入 - 重新载入 - 重新载入最后使用的十六进制文件 保存 - 另存为十六进制文件 创建 在新窗口中创建电路 分离编辑 diff --git a/src/main/resources/lang/lang_zh_ref.xml b/src/main/resources/lang/lang_zh_ref.xml index 6ed3d2f92..159d86dd8 100644 --- a/src/main/resources/lang/lang_zh_ref.xml +++ b/src/main/resources/lang/lang_zh_ref.xml @@ -24,10 +24,7 @@ In the file howTo.md you can find more details about translations. Edit Continue editing Load - Reload - Reload last HEX file Save - Save as HEX file. Create Create a circuit in a separate window Edit detached diff --git a/src/main/resources/verilog/DIG_ROM.v b/src/main/resources/verilog/DIG_ROM.v index 86a57543a..dea5441cb 100644 --- a/src/main/resources/verilog/DIG_ROM.v +++ b/src/main/resources/verilog/DIG_ROM.v @@ -3,7 +3,11 @@ panic("err_romNeedsALabelToBeExported"); romMaxSize := 1 << elem.AddrBits; - romSize := sizeOf(elem.Data); + data:=elem.Data; + if (elem.autoReload) { + data=loadHex(elem.lastDataFile, elem.Bits); + } + romSize := sizeOf(data); moduleName = format("%s_%dX%d_%s", moduleName, romMaxSize, elem.Bits, identifier(elem.Label)); dBitRange := format("[%d:0]", elem.Bits - 1); aBitRange := format("[%d:0]", elem.AddrBits - 1); @@ -30,7 +34,7 @@ initial begin - my_rom[] = ;] = ; end endmodule diff --git a/src/main/resources/vhdl/DIG_ROM.tem b/src/main/resources/vhdl/DIG_ROM.tem index d9400d603..938c61846 100644 --- a/src/main/resources/vhdl/DIG_ROM.tem +++ b/src/main/resources/vhdl/DIG_ROM.tem @@ -6,6 +6,13 @@ use IEEE.NUMERIC_STD.ALL; panic("err_romNeedsALabelToBeExported"); entityName:="DIG_ROM_"+identifier(elem.Label); + + data:=elem.Data; + if (elem.autoReload) { + data=loadHex(elem.lastDataFile, elem.Bits); + } + len:=sizeOf(data); + ?> entity is port ( @@ -15,16 +22,15 @@ entity is end ; architecture Behavioral of is - type mem is array ( 0 to ) of ; + type mem is array ( 0 to ) of ; constant my_Rom : mem := ( 1) {?>(others => 'Z')'Z'; - elsif A > then + elsif A > then D <= ; else D <= my_rom(to_integer(unsigned(A)));