From 29f0b88bbed53a20236e93d96034b80c09942a77 Mon Sep 17 00:00:00 2001 From: hneemann Date: Fri, 28 Jun 2019 17:45:19 +0200 Subject: [PATCH] allows simple generic circuits --- .../digital/analyse/SubstituteLibrary.java | 56 +++- .../de/neemann/digital/core/element/Keys.java | 4 +- .../de/neemann/digital/hdl/hgs/Parser.java | 28 +- src/main/resources/analyser/Counter.dig | 14 +- src/main/resources/analyser/CounterPreset.dig | 291 +++++++++++++----- src/main/resources/lang/lang_de.xml | 2 +- src/main/resources/lang/lang_en.xml | 2 +- .../neemann/digital/hdl/hgs/ParserTest.java | 8 +- 8 files changed, 293 insertions(+), 112 deletions(-) diff --git a/src/main/java/de/neemann/digital/analyse/SubstituteLibrary.java b/src/main/java/de/neemann/digital/analyse/SubstituteLibrary.java index 4bc08685d..c83cdcaa6 100644 --- a/src/main/java/de/neemann/digital/analyse/SubstituteLibrary.java +++ b/src/main/java/de/neemann/digital/analyse/SubstituteLibrary.java @@ -7,6 +7,7 @@ package de.neemann.digital.analyse; import de.neemann.digital.core.element.ElementAttributes; import de.neemann.digital.core.element.ElementTypeDescription; +import de.neemann.digital.core.element.Key; import de.neemann.digital.core.element.Keys; import de.neemann.digital.draw.elements.Circuit; import de.neemann.digital.draw.elements.PinException; @@ -15,6 +16,7 @@ import de.neemann.digital.draw.library.CustomElement; import de.neemann.digital.draw.library.ElementLibrary; import de.neemann.digital.draw.library.ElementNotFoundException; import de.neemann.digital.draw.library.LibraryInterface; +import de.neemann.digital.hdl.hgs.*; import de.neemann.digital.lang.Lang; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -40,7 +42,8 @@ public class SubstituteLibrary implements LibraryInterface { .add(attr -> attr.get(Keys.WITH_ENABLE), new Substitute("T_FF_EN.dig")) .add(attr -> true, new Substitute("T_FF.dig")) ); - MAP.put("Counter", new SubstituteGenericBits("Counter.dig")); + MAP.put("Counter", new SubstituteGenericHGSParser("Counter.dig")); + MAP.put("CounterPreset", new SubstituteGenericHGSParser("CounterPreset.dig")); } private final ElementLibrary parent; @@ -172,7 +175,7 @@ public class SubstituteLibrary implements LibraryInterface { c); } - private void generify(ElementAttributes attr, Circuit circuit) { + private void generify(ElementAttributes attr, Circuit circuit) throws IOException { for (VisualElement v : circuit.getElements()) { String gen = v.getElementAttributes().get(Keys.GENERIC).trim(); if (!gen.isEmpty()) @@ -180,19 +183,56 @@ public class SubstituteLibrary implements LibraryInterface { } } - abstract void generify(ElementAttributes sourceAttributes, String gen, ElementAttributes nodeAttributes); + abstract void generify(ElementAttributes sourceAttributes, String gen, ElementAttributes nodeAttributes) throws IOException; } - private static class SubstituteGenericBits extends SubstituteGeneric { + private static class SubstituteGenericHGSParser extends SubstituteGeneric { + private final HashMap map; - private SubstituteGenericBits(String filename) { + private SubstituteGenericHGSParser(String filename) { super(filename); + map = new HashMap<>(); } @Override - void generify(ElementAttributes sourceAttributes, String gen, ElementAttributes nodeAttributes) { - if (gen.equals("bits")) - nodeAttributes.setBits(sourceAttributes.getBits()); + void generify(ElementAttributes sourceAttributes, String gen, ElementAttributes nodeAttributes) throws IOException { + try { + Statement s = map.get(gen); + if (s == null) { + LOGGER.info("generic: " + gen); + s = new Parser(gen).parse(false); + map.put(gen, s); + } + Context context = new Context() + .declareVar("orig", sourceAttributes) + .declareVar("this", new AllowSetAttributes(nodeAttributes)); + s.execute(context); + } catch (ParserException | HGSEvalException e) { + throw new IOException(e); + } + } + + } + + private static final class AllowSetAttributes implements HGSMap { + private final ElementAttributes attr; + + private AllowSetAttributes(ElementAttributes attr) { + this.attr = attr; + } + + @Override + public void hgsMapPut(String key, Object val) throws HGSEvalException { + Key k = Keys.getKeyByName(key); + if (k == null) { + throw new HGSEvalException("key " + key + " is invalid"); + } else + attr.set(k, val); + } + + @Override + public Object hgsMapGet(String key) { + return attr.hgsMapGet(key); } } } 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 6cae93e16..5659a5779 100644 --- a/src/main/java/de/neemann/digital/core/element/Keys.java +++ b/src/main/java/de/neemann/digital/core/element/Keys.java @@ -785,9 +785,9 @@ public final class Keys { new Key.KeyFile("toolChainConfig", new File("")).setSecondary().setRequiresRestart(); /** - * Selects the midi channel + * Used to input statements to generify a circuit. */ public static final Key GENERIC = - new Key<>("generic", "").allowGroupEdit(); + new Key.LongString("generic").allowGroupEdit(); } diff --git a/src/main/java/de/neemann/digital/hdl/hgs/Parser.java b/src/main/java/de/neemann/digital/hdl/hgs/Parser.java index c6b012137..5c62c3599 100644 --- a/src/main/java/de/neemann/digital/hdl/hgs/Parser.java +++ b/src/main/java/de/neemann/digital/hdl/hgs/Parser.java @@ -100,14 +100,28 @@ public class Parser { * @throws ParserException ParserException */ public Statement parse() throws IOException, ParserException { - Statements s = new Statements(); - String text = tok.readText(); - if (nextIs(SUB)) - text = Value.trimRight(text); + return parse(true); + } - if (text.length() > 0) { - String t = text; - s.add(c -> c.print(t)); + /** + * Parses the given template source + * + * @param startsWithText true if code starts with text. + * @return the Statement to execute + * @throws IOException IOException + * @throws ParserException ParserException + */ + public Statement parse(boolean startsWithText) throws IOException, ParserException { + Statements s = new Statements(); + if (startsWithText) { + String text = tok.readText(); + if (nextIs(SUB)) + text = Value.trimRight(text); + + if (text.length() > 0) { + String t = text; + s.add(c -> c.print(t)); + } } while (!nextIs(EOF)) { if (nextIs(STATIC)) { diff --git a/src/main/resources/analyser/Counter.dig b/src/main/resources/analyser/Counter.dig index 4b6c7ae1a..807ae8b4c 100644 --- a/src/main/resources/analyser/Counter.dig +++ b/src/main/resources/analyser/Counter.dig @@ -46,7 +46,7 @@ generic - bits + this.Bits=orig.Bits; @@ -74,7 +74,7 @@ generic - bits + this.Bits=orig.Bits; @@ -88,7 +88,7 @@ generic - bits + this.Bits=orig.Bits; @@ -102,7 +102,7 @@ generic - bits + this.Bits=orig.Bits; @@ -116,7 +116,7 @@ generic - bits + this.Bits=orig.Bits; @@ -130,7 +130,7 @@ generic - bits + this.Bits=orig.Bits; @@ -149,7 +149,7 @@ generic - bits + this.Bits=orig.Bits; diff --git a/src/main/resources/analyser/CounterPreset.dig b/src/main/resources/analyser/CounterPreset.dig index 4fc9296bb..f619bc067 100644 --- a/src/main/resources/analyser/CounterPreset.dig +++ b/src/main/resources/analyser/CounterPreset.dig @@ -11,17 +11,25 @@ en - + Clock + + runRealTime + true + Label C + + Frequency + 2 + - + In @@ -31,7 +39,7 @@ dir - + Out @@ -44,6 +52,10 @@ Bits 4 + + generic + this.Bits=orig.Bits; + @@ -55,7 +67,7 @@ ovf - + D_FF @@ -68,6 +80,10 @@ Bits 4 + + generic + this.Bits=orig.Bits; + @@ -78,6 +94,10 @@ Bits 4 + + generic + this.Bits=orig.Bits; + @@ -88,6 +108,10 @@ Bits 4 + + generic + this.Bits=orig.Bits; + @@ -98,13 +122,17 @@ Bits 4 + + generic + this.Bits=orig.Bits; + - + Ground - + Const @@ -113,13 +141,17 @@ Bits 4 + + generic + this.Bits=orig.Bits; + - + And - + Multiplexer @@ -128,8 +160,12 @@ Bits 4 + + generic + this.Bits=orig.Bits; + - + Const @@ -142,8 +178,12 @@ Bits 4 + + generic + this.Bits=orig.Bits; + - + In @@ -160,6 +200,10 @@ Bits 4 + + generic + this.Bits=orig.Bits; + @@ -170,22 +214,35 @@ Bits 4 + + generic + this.Bits=orig.Bits; + - + Const Value - 9 + 15 Bits 4 + + generic + this.Bits=orig.Bits; +if (orig.maxValue=0) { + this.Value=(1<<orig.Bits)-1; +} else { + this.Value=orig.maxValue; +} + - + Or @@ -204,6 +261,10 @@ Bits 4 + + generic + this.Bits=orig.Bits; + @@ -218,6 +279,10 @@ Bits 4 + + generic + this.Bits=orig.Bits; + @@ -231,7 +296,7 @@ - + Multiplexer @@ -240,6 +305,10 @@ Bits 4 + + generic + this.Bits=orig.Bits; + @@ -265,7 +334,43 @@ clr - + + + + Multiplexer + + + Bits + 4 + + + flipSelPos + true + + + generic + this.Bits=orig.Bits; + + + + + + Const + + + Value + 0 + + + Bits + 4 + + + generic + this.Bits=orig.Bits; + + + @@ -274,48 +379,44 @@ - - + + - - + + - + - - - - - + - - + + - + - - + + - - + + - - + + - - + + @@ -329,20 +430,36 @@ + + + + + + + + - + - - + + - + + + + + + + + + @@ -350,12 +467,20 @@ - - + + - - + + + + + + + + + + @@ -366,8 +491,8 @@ - - + + @@ -378,32 +503,24 @@ - - - - - - - - - - - - - - + + - - + + - - + + + + + + @@ -418,12 +535,12 @@ - - + + - - + + @@ -438,16 +555,16 @@ - - + + - - + + - - + + @@ -455,19 +572,23 @@ - + + + + + + + + + + + + + - - - - - - - - - + @@ -475,7 +596,7 @@ - + diff --git a/src/main/resources/lang/lang_de.xml b/src/main/resources/lang/lang_de.xml index 0a62f33c0..005d9eab2 100644 --- a/src/main/resources/lang/lang_de.xml +++ b/src/main/resources/lang/lang_de.xml @@ -1342,7 +1342,7 @@ Sind evtl. die Namen der Variablen nicht eindeutig? Erlaubt den Start externer Tools, um z.B. einen FPGA zu programmieren o.ä. Generisch - String für das Erzeugen generischer Schaltungen. + Anweisung um eine generische Schaltung anzupassen. Leitung eingefügt. Aus Zwischenablage eingefügt. diff --git a/src/main/resources/lang/lang_en.xml b/src/main/resources/lang/lang_en.xml index 23e46c50f..12b4fa5d9 100644 --- a/src/main/resources/lang/lang_en.xml +++ b/src/main/resources/lang/lang_en.xml @@ -1330,7 +1330,7 @@ Allows the start of external tools, e.g. to program an FPGA or similar. Generic - String used to create generic circuits. + Statements used to generify a circuit. Inserted wire. Insert from clipboard. diff --git a/src/test/java/de/neemann/digital/hdl/hgs/ParserTest.java b/src/test/java/de/neemann/digital/hdl/hgs/ParserTest.java index 8f9b4bd99..bfe6abd61 100644 --- a/src/test/java/de/neemann/digital/hdl/hgs/ParserTest.java +++ b/src/test/java/de/neemann/digital/hdl/hgs/ParserTest.java @@ -189,12 +189,18 @@ public class ParserTest extends TestCase { assertEquals("Hello World!", exec("Hello World!", new Context()).toString()); } - public void testParseTemplateTextOnly() throws IOException, ParserException, HGSEvalException { assertEquals("Hello World!", exec("Hello World!").toString()); assertEquals("Hello < < World!", exec("Hello < < World!").toString()); } + public void testParseCommandsOnly() throws IOException, ParserException, HGSEvalException { + Statement s = new Parser("a:=2; b:=a*a;").parse(false); + Context context = new Context(); + s.execute(context); + assertEquals(4L, context.getVar("b")); + } + public void testParseTemplateVariable() throws IOException, ParserException, HGSEvalException { Context c = exec("Hello World!", new Context().declareVar("a", "My")); assertEquals("Hello My World!", c.toString());