From 409bb3cac9ce433295835e69ae71b40d6575105b Mon Sep 17 00:00:00 2001 From: hneemann Date: Mon, 12 Mar 2018 21:21:36 +0100 Subject: [PATCH] added first VHDLTemplate, not working yet --- .../de/neemann/digital/hdl/hgs/Context.java | 35 +++++- .../neemann/digital/hdl/vhdl/VHDLLibrary.java | 2 +- .../digital/hdl/vhdl/lib/VHDLTemplate.java | 110 ++++++++++++++++++ .../neemann/digital/hdl/hgs/ParserTest.java | 5 + 4 files changed, 150 insertions(+), 2 deletions(-) create mode 100644 src/main/java/de/neemann/digital/hdl/vhdl/lib/VHDLTemplate.java 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 645931ca7..cd255982a 100644 --- a/src/main/java/de/neemann/digital/hdl/hgs/Context.java +++ b/src/main/java/de/neemann/digital/hdl/hgs/Context.java @@ -14,6 +14,7 @@ public class Context { private final Context parent; private final StringBuilder code; private HashMap map; + private int recordStart = 0; /** * Creates a new context @@ -37,6 +38,23 @@ public class Context { map = new HashMap<>(); } + /** + * Returns true if this context contains a mapping for the specified key. + * + * @param name the key + * @return true if value is present + */ + public boolean contains(String name) { + if (map.containsKey(name)) + return true; + else { + if (parent != null) + return parent.contains(name); + else + return false; + } + } + /** * Get a variable * @@ -47,6 +65,13 @@ public class Context { public Object getVar(String name) throws EvalException { Object v = map.get(name); if (v == null) { + + if (name.equals("output")) + return code.toString(); + + if (name.equals("fraction")) + return code.subSequence(recordStart, code.length()).toString(); + if (parent == null) throw new EvalException("variable not found: " + name); else @@ -76,8 +101,9 @@ public class Context { public Context print(String str) { if (parent != null) parent.print(str); - else + else { code.append(str); + } return this; } @@ -88,4 +114,11 @@ public class Context { else return map.toString(); } + + /** + * resets the record position + */ + public void resetRecorder() { + recordStart = code.length(); + } } diff --git a/src/main/java/de/neemann/digital/hdl/vhdl/VHDLLibrary.java b/src/main/java/de/neemann/digital/hdl/vhdl/VHDLLibrary.java index 48dc61d02..0559f72d3 100644 --- a/src/main/java/de/neemann/digital/hdl/vhdl/VHDLLibrary.java +++ b/src/main/java/de/neemann/digital/hdl/vhdl/VHDLLibrary.java @@ -127,7 +127,7 @@ public class VHDLLibrary { e.writeHeader(out, node); - if (e instanceof ExternalVHDL) + if (e instanceof ExternalVHDL || e instanceof VHDLTemplate) return; out.println(); diff --git a/src/main/java/de/neemann/digital/hdl/vhdl/lib/VHDLTemplate.java b/src/main/java/de/neemann/digital/hdl/vhdl/lib/VHDLTemplate.java new file mode 100644 index 000000000..034a44297 --- /dev/null +++ b/src/main/java/de/neemann/digital/hdl/vhdl/lib/VHDLTemplate.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2017 Helmut Neemann + * Use of this source code is governed by the GPL v3 license + * that can be found in the LICENSE file. + */ +package de.neemann.digital.hdl.vhdl.lib; + +import de.neemann.digital.hdl.hgs.*; +import de.neemann.digital.hdl.model.HDLException; +import de.neemann.digital.hdl.model.HDLNode; +import de.neemann.digital.hdl.printer.CodePrinter; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.util.HashSet; + +/** + * Reads a file with the vhdl code to create the entity + */ +public class VHDLTemplate implements VHDLEntity { + private final static String ENTITY_PREFIX = "DIG_"; + private final Context staticContext; + private final Statement statements; + private HashSet entitiesWritten; + private String entityName; + + /** + * Creates a new instance + * + * @param name the name of the entity + * @throws IOException IOException + */ + public VHDLTemplate(String name) throws IOException { + entityName = ENTITY_PREFIX + name; + InputStream inputStream = getClass().getClassLoader().getResourceAsStream(createFileName(entityName)); + if (inputStream == null) + throw new IOException("file not present: " + createFileName(entityName)); + try (Reader in = new InputStreamReader(inputStream, "utf-8")) { + Parser p = new Parser(in); + statements = p.parse(); + staticContext = p.getStaticContext(); + } catch (ParserException e) { + throw new IOException("error parsing template", e); + } + entitiesWritten = new HashSet<>(); + } + + private static String createFileName(String name) { + return "vhdl/" + name + ".tem"; + } + + @Override + public void writeHeader(CodePrinter out, HDLNode node) throws IOException { + try { + statements.execute(new Context().setVar("elem", node.getAttributes())); + entitiesWritten.add(getEntityName(node)); + } catch (EvalException e) { + throw new IOException("error evaluating the template", e); + } + } + + private String getEntityName(HDLNode node) throws EvalException { + String name = entityName; + if (staticContext.contains("name")) { + Object funcObj = staticContext.getVar("name"); + if (funcObj instanceof FirstClassFunction) + name = ((FirstClassFunction) funcObj).evaluate(node.getAttributes()).toString(); + } + return name; + } + + @Override + public String getName(HDLNode node) throws HDLException { + try { + return getEntityName(node); + } catch (EvalException e) { + throw new HDLException("error requesting the entities name", e); + } + } + + @Override + public boolean needsOutput(HDLNode node) throws HDLException { + try { + return !entitiesWritten.contains(getEntityName(node)); + } catch (EvalException e) { + throw new HDLException("error requesting the entities name", e); + } + } + + @Override + public void writeDeclaration(CodePrinter out, HDLNode node) throws IOException, HDLException { + + } + + @Override + public void writeArchitecture(CodePrinter out, HDLNode node) throws IOException, HDLException { + } + + @Override + public void writeGenericMap(CodePrinter out, HDLNode node) throws IOException, HDLException { + + } + + @Override + public String getDescription(HDLNode node) { + return null; + } +} 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 244b8695b..f50397535 100644 --- a/src/test/java/de/neemann/digital/hdl/hgs/ParserTest.java +++ b/src/test/java/de/neemann/digital/hdl/hgs/ParserTest.java @@ -255,6 +255,11 @@ public class ParserTest extends TestCase { new Context().setVar("a", 3)).toString()); } + public void testFirstClassFunctionOutput() throws IOException, ParserException, EvalException { + assertEquals("testtext12testtext15", + exec("testtext").toString()); + } + // public void testCode() throws IOException, ParserException { // File dir = new File("/home/hneemann/temp/Digital/ideras/Digital/src/main/resources/verilog");