mirror of
https://github.com/hneemann/Digital.git
synced 2025-09-15 15:58:41 -04:00
allow toolchain config parameters
This commit is contained in:
parent
bdafd03aa4
commit
da72a50323
@ -7,10 +7,15 @@
|
||||
<arg>vivado/<?=shortname?>.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="<?=shortname?>_constraints.xdc" overwrite="true" filter="true">
|
||||
<file name="<?=shortname?>_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/<?=shortname?>.xpr" overwrite="false" filter="true">
|
||||
<file name="vivado/<?=shortname?>.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"/>
|
||||
|
@ -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/<?=shortname?>.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/<?=shortname?>.xpr" overwrite="false" filter="true" lookAt="BASYS3.config" ref="vivado"/>
|
||||
</files>
|
||||
</toolchain>
|
||||
|
@ -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());
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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()) {
|
||||
|
@ -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);
|
||||
|
@ -76,7 +76,7 @@ public class ConfigurationTest extends TestCase {
|
||||
" <content>deal with <?=path?></content>\n" +
|
||||
" </file>\n" +
|
||||
" <file name=\"file2\" overwrite=\"true\" filter=\"true\">\n" +
|
||||
" <content>deal with <?=path?>, Bits: <?=hdl.ports[0].bits?> (<?=hdl.ports[0].name?>)</content>\n" +
|
||||
" <content>deal with <?=path?>, Bits: <?=model.ports[0].bits?> (<?=model.ports[0].name?>)</content>\n" +
|
||||
" </file>\n" +
|
||||
" <file name=\"<?=shortname?>.z\" overwrite=\"true\" filter=\"false\">\n" +
|
||||
" <content>test</content>\n" +
|
||||
|
Loading…
x
Reference in New Issue
Block a user