allow toolchain config parameters

This commit is contained in:
hneemann 2019-05-20 07:42:12 +02:00
parent bdafd03aa4
commit da72a50323
7 changed files with 106 additions and 64 deletions

View File

@ -7,10 +7,15 @@
<arg>vivado/&lt;?=shortname?&gt;.xpr</arg>
</command>
</commands>
<params>
<!-- used by the Vivado project template -->
<param name="chip">xc7a35ticpg236-1L</param>
<param name="extension">.vhdl</param>
</params>
<files>
<file name="clockGenerator.vhdl" overwrite="true" filter="true" id="MMCME2_BASE">
<content><![CDATA[
<? if (hdl.frequency<4687500) { ?>
<? if (model.frequency<4687500) { ?>
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.numeric_std.all;
@ -22,7 +27,7 @@ entity clockGenerator is
cin: in std_logic );
end clockGenerator;
<? maxCounter:=100000000 / (2 * hdl.frequency);?>
<? maxCounter:=100000000 / (2 * model.frequency);?>
architecture Behavioral of clockGenerator is
-- Don't use a logic signal as clock source in a real world application!
@ -89,7 +94,7 @@ begin
M_IDEAL := D_MIN*VCO_MAX/F_IN;
F_DES := hdl.frequency/1000000.0;
F_DES := model.frequency/1000000.0;
bestError:=F_DES;
bestErrorM:=M_MAX;
@ -205,11 +210,11 @@ end Behavioral;
<? } ?>
]]></content>
</file>
<file name="&lt;?=shortname?&gt;_constraints.xdc" overwrite="true" filter="true">
<file name="&lt;?=shortname?&gt;_constraints.xdc" overwrite="true" filter="true" id="constraints.xdc">
<content><![CDATA[<?
for (i:=0; i<sizeOf(hdl.ports);i++) {
port:=hdl.ports[i];
for (i:=0; i<sizeOf(model.ports);i++) {
port:=model.ports[i];
if (port.bits=1) {
print("set_property PACKAGE_PIN "+port.pin+" [get_ports "+port.name+"]\n");
print("set_property IOSTANDARD LVCMOS33 [get_ports "+port.name+"]\n\n");
@ -225,30 +230,32 @@ print("set_property CONFIG_VOLTAGE 3.3 [current_design]\n");
?>]]></content>
</file>
<file name="vivado/&lt;?=shortname?&gt;.xpr" overwrite="false" filter="true">
<file name="vivado/&lt;?=shortname?&gt;.xpr" overwrite="false" filter="true" id="vivado">
<content><![CDATA[<?print("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");?>
<!-- Created by Digital -->
<Project Version="7" Minor="20" Path="<?=dir?>/vivado/<?=shortname?>.xpr">
<DefaultLaunch Dir="$PRUNDIR"/>
<Configuration>
<Option Name="Part" Val="xc7a35ticpg236-1L"/>
<Option Name="Part" Val="<?=chip?>"/>
</Configuration>
<FileSets Version="1" Minor="31">
<FileSet Name="sources_1" Type="DesignSrcs" RelSrcDir="$PSRCDIR/sources_1">
<Filter Type="Srcs"/>
<File Path="$PPRDIR/../<?=shortname?>.vhdl">
<File Path="$PPRDIR/../<?=shortname?><?=extension?>">
<FileInfo>
<Attr Name="UsedIn" Val="synthesis"/>
<Attr Name="UsedIn" Val="simulation"/>
</FileInfo>
</File>
<File Path="$PPRDIR/../clockGenerator.vhdl">
<? if (isPresent("clockGenerator")) { ?>
<File Path="$PPRDIR/../<?=clockGenerator?><?=extension?>">
<FileInfo>
<Attr Name="UsedIn" Val="synthesis"/>
<Attr Name="UsedIn" Val="simulation"/>
</FileInfo>
</File>
<? } ?>
<Config>
<Option Name="DesignMode" Val="RTL"/>
<Option Name="TopModule" Val="main"/>

View File

@ -1,20 +1,25 @@
<!-- if a clockGenerator is given, this config needs to create the required source code -->
<toolchain name="VerilogClockTest" clockGenerator="clockGenerator">
<toolchain name="VerilogClockExample" clockGenerator="clockGenerator">
<commands>
<command name="Export" requires="verilog"/>
</commands>
<params>
<!-- used by the Vivado project template -->
<param name="chip">xc7a35ticpg236-1L</param>
<param name="extension">.v</param>
</params>
<files>
<file name="clockGenerator.v" overwrite="true" filter="true">
<content><![CDATA[<?
// Add the board specific clock generation here!
// This example assumes a 100MHz clock and creates a simple clock divider to
// match the input clock frequency given in the circuit.
// The variable hdl.frequency holds the frequency selected in the circuits
// The variable model.frequency holds the frequency selected in the circuits
// clock component.
board_f := 100000000; // assuming a 100MHz clock
board_frequency := 100000000; // assuming a 100MHz clock
maxCounter := board_f/hdl.frequency/2;
maxCounter := board_frequency/model.frequency/2;
bits := bitsNeededFor(maxCounter);
?>module clockGenerator
@ -45,42 +50,6 @@ endmodule
]]></content>
</file>
<!-- creates a vivado project file which simplifies testing -->
<file name="vivado/&lt;?=shortname?&gt;.xpr" overwrite="false" filter="true">
<content><![CDATA[<?print("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");?>
<Project Version="7" Minor="20" Path="<?=dir?>/vivado/<?=shortname?>.xpr">
<DefaultLaunch Dir="$PRUNDIR"/>
<Configuration>
<Option Name="Part" Val="xc7a35ticpg236-1L"/>
</Configuration>
<FileSets Version="1" Minor="31">
<FileSet Name="sources_1" Type="DesignSrcs" RelSrcDir="$PSRCDIR/sources_1">
<Filter Type="Srcs"/>
<File Path="$PPRDIR/../<?=shortname?>.v">
<FileInfo>
<Attr Name="UsedIn" Val="synthesis"/>
<Attr Name="UsedIn" Val="simulation"/>
</FileInfo>
</File>
<File Path="$PPRDIR/../clockGenerator.v">
<FileInfo>
<Attr Name="UsedIn" Val="synthesis"/>
<Attr Name="UsedIn" Val="simulation"/>
</FileInfo>
</File>
<Config>
<Option Name="DesignMode" Val="RTL"/>
<Option Name="TopModule" Val="main"/>
<Option Name="TopAutoSet" Val="TRUE"/>
</Config>
</FileSet>
<FileSet Name="constrs_1" Type="Constrs" RelSrcDir="$PSRCDIR/constrs_1">
<Filter Type="Constrs"/>
<Config>
<Option Name="ConstrsType" Val="XDC"/>
</Config>
</FileSet>
</FileSets>
</Project>]]></content>
</file>
<file name="vivado/&lt;?=shortname?&gt;.xpr" overwrite="false" filter="true" lookAt="BASYS3.config" ref="vivado"/>
</files>
</toolchain>

View File

@ -24,6 +24,7 @@ import de.neemann.digital.hdl.verilog2.VerilogGenerator;
import de.neemann.digital.hdl.vhdl2.VHDLGenerator;
import de.neemann.digital.lang.Lang;
import de.neemann.gui.ErrorMessage;
import de.neemann.gui.language.Resources;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -32,6 +33,7 @@ import java.awt.event.ActionEvent;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* Used to create the IDE integration
@ -76,6 +78,8 @@ public final class Configuration {
xStream.aliasAttribute(Configuration.class, "name", "name");
xStream.aliasAttribute(Configuration.class, "frequency", "frequency");
xStream.aliasAttribute(Configuration.class, "clockGenerator", "clockGenerator");
xStream.aliasAttribute(Configuration.class, "params", "params");
xStream.registerConverter(new Resources.MapEntryConverter("param"));
xStream.alias("command", Command.class);
xStream.aliasAttribute(Command.class, "name", "name");
xStream.aliasAttribute(Command.class, "requires", "requires");
@ -97,6 +101,7 @@ public final class Configuration {
private String clockGenerator;
private ArrayList<Command> commands;
private ArrayList<FileToCreate> files;
private Map<String, String> params;
private transient FilenameProvider filenameProvider;
private transient CircuitProvider circuitProvider;
private transient LibraryProvider libraryProvider;
@ -173,17 +178,40 @@ public final class Configuration {
}
}
private Context createContext(File fileToExecute, HDLModel hdlModel) throws HGSEvalException {
private Context createContext(File fileToExecute, HDLModel hdlModel, Command command) throws HGSEvalException {
final Context context = new Context()
.declareVar("path", fileToExecute.getPath())
.declareVar("dir", fileToExecute.getParentFile())
.declareVar("name", fileToExecute.getName())
.declareVar("shortname", createShortname(fileToExecute.getName()));
if (params != null)
for (Map.Entry<String, String> e : params.entrySet())
context.declareVar(e.getKey(), toHGLValue(e.getValue()));
if (command.needsHDL())
context.declareVar("hdl", command.getHDL());
if (clockGenerator != null)
context.declareVar("clockGenerator", clockGenerator);
if (hdlModel != null)
context.declareVar("hdl", new ModelAccess(hdlModel.getMain()));
context.declareVar("model", new ModelAccess(hdlModel.getMain()));
return context;
}
private Object toHGLValue(String value) {
try {
return Long.parseLong(value);
} catch (NumberFormatException e1) {
try {
return Double.parseDouble(value);
} catch (NumberFormatException e2) {
return value;
}
}
}
private IOInterface getIoInterface() {
if (ioInterface == null)
ioInterface = new DefaultIOInterface();
@ -246,13 +274,13 @@ public final class Configuration {
action.setEnabled(false);
Thread t = new Thread(() -> {
try {
checkFilesToCreate(digFile, hdlModel);
checkFilesToCreate(digFile, hdlModel, command);
String[] args = command.getArgs();
if (args != null) {
if (command.isFilter()) {
final int argCount = command.getArgs().length;
Context context = createContext(digFile, hdlModel);
Context context = createContext(digFile, hdlModel, command);
for (int i = 0; i < argCount; i++) {
context.clearOutput();
new Parser(args[i]).parse().execute(context);
@ -278,14 +306,17 @@ public final class Configuration {
return null;
}
private void checkFilesToCreate(File fileToExecute, HDLModel hdlModel) throws HGSEvalException, IOException, ParserException {
Context context = createContext(fileToExecute, hdlModel);
private void checkFilesToCreate(File fileToExecute, HDLModel hdlModel, Command command) throws HGSEvalException, IOException, ParserException {
Context context = createContext(fileToExecute, hdlModel, command);
if (files != null) {
ConfigCache configCache = new ConfigCache(origin);
for (FileToCreate f : files) {
context.clearOutput();
Parser p = new Parser(f.getName());
final String name = f.getName();
if (name == null)
throw new IOException("no file name given!");
Parser p = new Parser(name);
p.parse().execute(context);
File filename = new File(fileToExecute.getParent(), context.toString());

View File

@ -22,7 +22,7 @@ public class Bundle {
private static XStream getxStream() {
XStream xStream = new XStream(new StaxDriver());
xStream.alias("languages", Map.class);
xStream.registerConverter(new Resources.MapEntryConverter());
xStream.registerConverter(new Resources.MapEntryConverter("string"));
return xStream;
}

View File

@ -19,13 +19,14 @@ import java.nio.charset.StandardCharsets;
import java.util.*;
/**
* Used to store the language keys.
*/
public class Resources {
private static XStream getxStream() {
XStream xStream = new XStream(new StaxDriver());
xStream.alias("resources", Map.class);
xStream.registerConverter(new MapEntryConverter());
xStream.registerConverter(new MapEntryConverter("string"));
return xStream;
}
@ -92,23 +93,57 @@ public class Resources {
return resourceMap.keySet();
}
static class MapEntryConverter implements Converter {
/**
* Simplified map converter
*/
public static class MapEntryConverter implements Converter {
private String keyName;
/**
* Creates a new Instance
*
* @param keyName the name of the xml entity
*/
public MapEntryConverter(String keyName) {
this.keyName = keyName;
}
/**
* Returns true if the given class can be converted by this converter.
*
* @param clazz the class to test.
* @return true if the given class can be converted by this converter.
*/
public boolean canConvert(Class clazz) {
return Map.class.isAssignableFrom(clazz);
}
/**
* Marshals the given object
*
* @param value the value to matshal
* @param writer the writer to write the xml to
* @param context the context of the marshaler
*/
public void marshal(Object value, HierarchicalStreamWriter writer, MarshallingContext context) {
Map map = (Map) value;
for (Object obj : map.entrySet()) {
Map.Entry entry = (Map.Entry) obj;
writer.startNode("string");
writer.startNode(keyName);
writer.addAttribute("name", entry.getKey().toString());
writer.setValue(entry.getValue().toString());
writer.endNode();
}
}
/**
* Unmarshals a object
*
* @param reader the reader to read the xml from
* @param context the context of the unmarshaler
* @return the read object
*/
public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
Map<String, String> map = new TreeMap<>();
while (reader.hasMoreChildren()) {

View File

@ -26,7 +26,7 @@ public class BASYS3Test extends TestCase {
String content = clock.getContent();
for (int f = 4688; f < 500000; f+=77) {
Context context = new Context().disableLogging();
context.declareVar("hdl",
context.declareVar("model",
new ElementAttributes()
.set(new Key<>("frequency", 10), f * 1000));
Parser p = new Parser(content);

View File

@ -76,7 +76,7 @@ public class ConfigurationTest extends TestCase {
" <content>deal with &lt;?=path?&gt;</content>\n" +
" </file>\n" +
" <file name=\"file2\" overwrite=\"true\" filter=\"true\">\n" +
" <content>deal with &lt;?=path?&gt;, Bits: &lt;?=hdl.ports[0].bits?&gt; (&lt;?=hdl.ports[0].name?&gt;)</content>\n" +
" <content>deal with &lt;?=path?&gt;, Bits: &lt;?=model.ports[0].bits?&gt; (&lt;?=model.ports[0].name?&gt;)</content>\n" +
" </file>\n" +
" <file name=\"&lt;?=shortname?&gt;.z\" overwrite=\"true\" filter=\"false\">\n" +
" <content>test</content>\n" +