mirror of
https://github.com/hneemann/Digital.git
synced 2025-09-14 15:26:52 -04:00
removed old board integration code
This commit is contained in:
parent
f50c50dd0b
commit
7151bc1cff
@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Ivan Deras
|
||||
* 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.boards;
|
||||
|
||||
/**
|
||||
* Board clock pin information
|
||||
*/
|
||||
public class BoardClockInfo {
|
||||
private final String pinNumber; // The pin number
|
||||
private final double clkPeriod; // Clock period in nanoseconds
|
||||
|
||||
/**
|
||||
* Initialize a new instance
|
||||
*
|
||||
* @param pinNumber The pin number
|
||||
* @param clkPeriod The clock period in nanoseconds
|
||||
*/
|
||||
public BoardClockInfo(String pinNumber, double clkPeriod) {
|
||||
this.pinNumber = pinNumber;
|
||||
this.clkPeriod = clkPeriod;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the pin number
|
||||
*
|
||||
* @return the pin number
|
||||
*/
|
||||
public String getPinNumber() {
|
||||
return pinNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the clock period
|
||||
*
|
||||
* @return the clock period
|
||||
*/
|
||||
public double getClkPeriod() {
|
||||
return clkPeriod;
|
||||
}
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
/*
|
||||
* 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.boards;
|
||||
|
||||
import de.neemann.digital.hdl.model2.clock.HDLClockIntegrator;
|
||||
import de.neemann.digital.hdl.model2.HDLModel;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Interface to write the additional files
|
||||
*/
|
||||
public interface BoardInterface {
|
||||
/**
|
||||
* Writes additional files
|
||||
*
|
||||
* @param path the full path of the created vhdl file
|
||||
* @param model the model
|
||||
* @throws IOException IOException
|
||||
*/
|
||||
void writeFiles(File path, HDLModel model) throws IOException;
|
||||
|
||||
/**
|
||||
* @return returns the board specific clock integrator
|
||||
*/
|
||||
HDLClockIntegrator getClockIntegrator();
|
||||
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
/*
|
||||
* 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.boards;
|
||||
|
||||
import de.neemann.digital.core.element.Keys;
|
||||
import de.neemann.digital.draw.elements.Circuit;
|
||||
import de.neemann.digital.draw.elements.VisualElement;
|
||||
import de.neemann.digital.gui.components.data.DummyElement;
|
||||
|
||||
/**
|
||||
* Provides additional information for a specific board
|
||||
*/
|
||||
public final class BoardProvider {
|
||||
|
||||
private static final class InstanceHolder {
|
||||
static final BoardProvider INSTANCE = new BoardProvider();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the BoardProvider instance
|
||||
*/
|
||||
public static BoardProvider getInstance() {
|
||||
return InstanceHolder.INSTANCE;
|
||||
}
|
||||
|
||||
private BoardProvider() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a specific board
|
||||
*
|
||||
* @param circuit the circuit
|
||||
* @return the board or null
|
||||
*/
|
||||
public BoardInterface getBoard(Circuit circuit) {
|
||||
String board = null;
|
||||
for (VisualElement element : circuit.getElements()) {
|
||||
if (element.equalsDescription(DummyElement.TEXTDESCRIPTION)) {
|
||||
String text = element.getElementAttributes().get(Keys.DESCRIPTION).toLowerCase();
|
||||
if (text.startsWith("board:")) {
|
||||
board = text.substring(6).trim();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (board == null)
|
||||
return null;
|
||||
|
||||
switch (board) {
|
||||
case "basys3":
|
||||
return new Vivado("LVCMOS33",
|
||||
"W5",
|
||||
10,
|
||||
new ClockIntegratorARTIX7(10),
|
||||
"xc7a35ticpg236-1L");
|
||||
case "mimasv1":
|
||||
return new MimasV1Board();
|
||||
case "mimasv2":
|
||||
return new MimasV2Board();
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,183 +0,0 @@
|
||||
/*
|
||||
* 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.boards;
|
||||
|
||||
import de.neemann.digital.core.element.ElementAttributes;
|
||||
import de.neemann.digital.core.element.Key;
|
||||
import de.neemann.digital.hdl.model2.*;
|
||||
import de.neemann.digital.hdl.model2.clock.ClockInfo;
|
||||
import de.neemann.digital.hdl.model2.clock.ClockIntegratorGeneric;
|
||||
import de.neemann.digital.hdl.model2.clock.HDLClockIntegrator;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Implements clocking on Artix 7
|
||||
*/
|
||||
public class ClockIntegratorARTIX7 implements HDLClockIntegrator {
|
||||
private static final int F_PFD_MIN_MHZ = 10;
|
||||
private static final int F_PFD_MAX_MHZ = 450;
|
||||
|
||||
private static final int F_VCO_MIN_MHZ = 600;
|
||||
private static final int F_VCO_MAX_MHZ = 1200;
|
||||
|
||||
private static final int MAX_CLOCK_DIVIDE = 128;
|
||||
|
||||
private final double clkInPeriod;
|
||||
|
||||
/**
|
||||
* Creates a new instance
|
||||
*
|
||||
* @param clkInPeriod clock in period in ns
|
||||
*/
|
||||
public ClockIntegratorARTIX7(double clkInPeriod) {
|
||||
this.clkInPeriod = clkInPeriod;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void integrateClocks(HDLCircuit model, ArrayList<ClockInfo> clocks) throws HDLException {
|
||||
if (clocks.size() > 1)
|
||||
throw new HDLException("up to now only a single clock is supported on ARTIX-7");
|
||||
|
||||
|
||||
Params p = new Parameters(clocks.get(0).getFrequency(), clkInPeriod).getBest();
|
||||
if (p == null)
|
||||
new ClockIntegratorGeneric(clkInPeriod).integrateClocks(model, clocks);
|
||||
else
|
||||
insertMMCMClock(model, p, clocks.get(0).getClockPort());
|
||||
}
|
||||
|
||||
private void insertMMCMClock(HDLCircuit model, Params p, HDLPort clock) throws HDLException {
|
||||
ElementAttributes attr = new ElementAttributes()
|
||||
.set(new Key<>("cascading", 0), p.isCascading())
|
||||
.set(new Key<>("D_PARAM", 0), p.d)
|
||||
.set(new Key<>("M_PARAM", 0), p.m)
|
||||
.set(new Key<>("DIV_PARAM", 0), p.divider)
|
||||
.set(new Key<>("DIV4_PARAM", 0), p.divider4)
|
||||
.set(new Key<>("PERIOD_PARAM", 0.0), clkInPeriod);
|
||||
|
||||
model.integrateClockNode(clock, new HDLNodeBuildIn("MMCME2_BASE", attr, name -> 1));
|
||||
}
|
||||
|
||||
static final class Parameters {
|
||||
|
||||
private final Params best;
|
||||
|
||||
Parameters(int frequency, double clkInPeriod) {
|
||||
double fInMHz = 1000 / clkInPeriod;
|
||||
double targetFreqInMHz = ((double) frequency) / 1000 / 1000;
|
||||
|
||||
int dMin = (int) Math.ceil(fInMHz / F_PFD_MAX_MHZ);
|
||||
int dMax = (int) Math.floor(fInMHz / F_PFD_MIN_MHZ);
|
||||
int mMin = (int) Math.ceil(F_VCO_MIN_MHZ / fInMHz * dMin);
|
||||
int mMax = (int) Math.floor(F_VCO_MIN_MHZ / fInMHz * dMax);
|
||||
|
||||
int mIdeal = (int) Math.floor(dMin * F_VCO_MAX_MHZ / fInMHz);
|
||||
|
||||
Params best = null;
|
||||
|
||||
for (int m = mMin; m <= mMax; m++)
|
||||
for (int d = dMin; d <= dMax; d++) {
|
||||
double fVco = fInMHz * m / d;
|
||||
double fpdf = fVco / m;
|
||||
|
||||
boolean valid = (F_VCO_MIN_MHZ <= fVco) && (fVco <= F_VCO_MAX_MHZ)
|
||||
&& (F_PFD_MIN_MHZ <= fpdf) && (fpdf <= F_PFD_MAX_MHZ);
|
||||
|
||||
if (valid) {
|
||||
int divider = (int) (fVco / targetFreqInMHz);
|
||||
if (divider >= 1 && divider <= MAX_CLOCK_DIVIDE) {
|
||||
double f = fVco / divider;
|
||||
|
||||
double error = (F_VCO_MAX_MHZ - fVco) + Math.abs(f - targetFreqInMHz) * 10 + (Math.abs(m - mIdeal) * 10);
|
||||
|
||||
if (best == null || best.error > error)
|
||||
best = new Params(m, d, divider, f, error);
|
||||
|
||||
} else {
|
||||
if (divider > MAX_CLOCK_DIVIDE && divider <= MAX_CLOCK_DIVIDE * MAX_CLOCK_DIVIDE) {
|
||||
int divider4 = 0;
|
||||
int divider6 = 0;
|
||||
|
||||
int bestErr = Integer.MAX_VALUE;
|
||||
for (int d6 = 1; d6 <= MAX_CLOCK_DIVIDE; d6++)
|
||||
for (int d4 = 1; d4 <= MAX_CLOCK_DIVIDE; d4++) {
|
||||
int dd = d4 * d6;
|
||||
int err = Math.abs(divider - dd);
|
||||
if (err < bestErr) {
|
||||
bestErr = err;
|
||||
divider4 = d4;
|
||||
divider6 = d6;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (divider4 > 0 && divider6 > 0) {
|
||||
double f = fVco / divider6 / divider4;
|
||||
|
||||
double error = (F_VCO_MAX_MHZ - fVco) + Math.abs(f - targetFreqInMHz) * 10 + (Math.abs(m - mIdeal) * 10);
|
||||
|
||||
if (best == null || best.error > error)
|
||||
best = new Params(m, d, divider6, divider4, f, error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.best = best;
|
||||
}
|
||||
|
||||
Params getBest() {
|
||||
return best;
|
||||
}
|
||||
}
|
||||
|
||||
static final class Params {
|
||||
private final int m;
|
||||
private final int d;
|
||||
private final int divider;
|
||||
private final double error;
|
||||
private final double f;
|
||||
private final int divider4;
|
||||
|
||||
private Params(int m, int d, int divider, double f, double error) {
|
||||
this.m = m;
|
||||
this.d = d;
|
||||
this.divider = divider;
|
||||
this.divider4 = 0;
|
||||
this.f = f;
|
||||
this.error = error;
|
||||
}
|
||||
|
||||
private Params(int m, int d, int divider, int divider4, double f, double error) {
|
||||
this.m = m;
|
||||
this.d = d;
|
||||
this.divider = divider;
|
||||
this.divider4 = divider4;
|
||||
this.f = f;
|
||||
this.error = error;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Params{"
|
||||
+ "m=" + m
|
||||
+ ", d=" + d
|
||||
+ ", divider=" + divider
|
||||
+ ", div4=" + divider4
|
||||
+ ", error=" + error
|
||||
+ ", f=" + f
|
||||
+ '}';
|
||||
}
|
||||
|
||||
private boolean isCascading() {
|
||||
return divider4 != 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,125 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Ivan Deras
|
||||
* 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.boards;
|
||||
|
||||
import de.neemann.digital.core.element.ElementAttributes;
|
||||
import de.neemann.digital.core.element.Key;
|
||||
import de.neemann.digital.hdl.model2.HDLCircuit;
|
||||
import de.neemann.digital.hdl.model2.HDLException;
|
||||
import de.neemann.digital.hdl.model2.HDLNodeBuildIn;
|
||||
import de.neemann.digital.hdl.model2.HDLPort;
|
||||
import de.neemann.digital.hdl.model2.clock.ClockInfo;
|
||||
import de.neemann.digital.hdl.model2.clock.ClockIntegratorGeneric;
|
||||
import de.neemann.digital.hdl.model2.clock.HDLClockIntegrator;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author ideras
|
||||
*/
|
||||
public class ClockIntegratorSpartan6 implements HDLClockIntegrator {
|
||||
private static final int MIN_FREQ = 5; // Minimum frequency in MHz
|
||||
private static final int MAX_FREQ = 333; // Maximum frequency in MHz
|
||||
private final BoardClockInfo[] boardClkInfo;
|
||||
|
||||
/**
|
||||
* Initialize a new instance
|
||||
*
|
||||
* @param boardClkInfo the board clock pins information
|
||||
*/
|
||||
public ClockIntegratorSpartan6(BoardClockInfo[] boardClkInfo) {
|
||||
this.boardClkInfo = boardClkInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void integrateClocks(HDLCircuit circuit, ArrayList<ClockInfo> clocks) throws HDLException {
|
||||
if (clocks.size() > 1)
|
||||
throw new HDLException("up to now only a single clock is supported on Spartan-6");
|
||||
|
||||
BoardClockInfo boardClockInfo = null;
|
||||
ClockInfo clkInfo = clocks.get(0);
|
||||
|
||||
for (BoardClockInfo bci : boardClkInfo) {
|
||||
if (bci.getPinNumber().equals(clkInfo.getClockPort().getPinNumber())) {
|
||||
boardClockInfo = bci;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (boardClockInfo == null) {
|
||||
throw new HDLException("Cannot find clock pin '" + clkInfo.getClockPort().getPinNumber() + "'");
|
||||
}
|
||||
|
||||
int freq = clkInfo.getFrequency();
|
||||
Params p = getParameters(freq, boardClockInfo.getClkPeriod());
|
||||
|
||||
if (p == null) {
|
||||
new ClockIntegratorGeneric(boardClockInfo.getClkPeriod()).integrateClocks(circuit, clocks);
|
||||
} else {
|
||||
insertDCM(circuit, p, clkInfo.getClockPort(), boardClockInfo.getClkPeriod());
|
||||
}
|
||||
}
|
||||
|
||||
private void insertDCM(HDLCircuit circuit, Params p, HDLPort clock, double clkInPeriod) throws HDLException {
|
||||
ElementAttributes attr = new ElementAttributes()
|
||||
.set(new Key<>("CLKFX_DIVIDE", 0), p.d)
|
||||
.set(new Key<>("CLKFX_MULTIPLY", 0), p.m)
|
||||
.set(new Key<>("CLKIN_PERIOD", 0.0), clkInPeriod);
|
||||
|
||||
circuit.integrateClockNode(clock, new HDLNodeBuildIn("DCM_SP", attr, name -> 1));
|
||||
}
|
||||
|
||||
Params getParameters(int targetFreq, double clkInPeriod) {
|
||||
double fInMHz = 1000 / clkInPeriod;
|
||||
double targetFreqInMHz = ((double) targetFreq) / 1000 / 1000;
|
||||
Params p = null;
|
||||
|
||||
if (!(targetFreqInMHz >= MIN_FREQ && targetFreqInMHz <= MAX_FREQ)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (int m=2; m<32; m++) {
|
||||
for (int d=1; d<=32; d++) {
|
||||
double fGen = fInMHz * (double) m / (double) d;
|
||||
double error = Math.abs(fGen - targetFreqInMHz);
|
||||
|
||||
if (p == null || p.error > error) {
|
||||
p = new Params(m, d, fGen, error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (p.error < 0.01) {
|
||||
return p;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static final class Params {
|
||||
private final int m;
|
||||
private final int d;
|
||||
private final double error;
|
||||
private final double f;
|
||||
|
||||
private Params(int m, int d, double f, double error) {
|
||||
this.m = m;
|
||||
this.d = d;
|
||||
this.f = f;
|
||||
this.error = error;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Params{"
|
||||
+ "m=" + m
|
||||
+ ", d=" + d
|
||||
+ ", error=" + error
|
||||
+ ", f=" + f
|
||||
+ '}';
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,141 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Ivan Deras. Adapted from the Vivado exporter.
|
||||
* 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.boards;
|
||||
|
||||
import de.neemann.digital.analyse.SplitPinString;
|
||||
import de.neemann.digital.hdl.model2.HDLModel;
|
||||
import de.neemann.digital.hdl.model2.HDLPort;
|
||||
import de.neemann.digital.hdl.printer.CodePrinter;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* Creates the needed ISE files.
|
||||
* Up to now only the constraints files containing the pin assignments and project file is created
|
||||
*/
|
||||
public abstract class ISE implements BoardInterface {
|
||||
private static final String ISE_PROJECT_TPLT =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>\n"
|
||||
+ "<project xmlns=\"http://www.xilinx.com/XMLSchema\" xmlns:xil_pn=\"http://www.xilinx.com/XMLSchema\">\n"
|
||||
+ " <header>\n"
|
||||
+ " </header>\n"
|
||||
+ " <version xil_pn:ise_version=\"14.7\" xil_pn:schema_version=\"2\"/>\n"
|
||||
+ " <files>\n"
|
||||
+ " <file xil_pn:name=\"%1$s\" xil_pn:type=\"FILE_VERILOG\">\n"
|
||||
+ " <association xil_pn:name=\"BehavioralSimulation\" xil_pn:seqID=\"2\"/>\n"
|
||||
+ " <association xil_pn:name=\"Implementation\" xil_pn:seqID=\"2\"/>\n"
|
||||
+ " </file>\n"
|
||||
+ " <file xil_pn:name=\"%2$s\" xil_pn:type=\"FILE_UCF\">\n"
|
||||
+ " <association xil_pn:name=\"Implementation\" xil_pn:seqID=\"0\"/>\n"
|
||||
+ " </file>\n"
|
||||
+ " </files>\n"
|
||||
+ " <autoManagedFiles>\n"
|
||||
+ " </autoManagedFiles>\n"
|
||||
+ " <properties>\n"
|
||||
+ " <property xil_pn:name=\"Create Binary Configuration File\" xil_pn:value=\"true\" xil_pn:valueState=\"non-default\"/>\n"
|
||||
+ " <property xil_pn:name=\"Create Bit File\" xil_pn:value=\"true\" xil_pn:valueState=\"default\"/>\n"
|
||||
+ " <property xil_pn:name=\"Device Family\" xil_pn:value=\"%3$s\" xil_pn:valueState=\"non-default\"/>\n"
|
||||
+ " <property xil_pn:name=\"Device\" xil_pn:value=\"%4$s\" xil_pn:valueState=\"non-default\"/>\n"
|
||||
+ " <property xil_pn:name=\"Package\" xil_pn:value=\"%5$s\" xil_pn:valueState=\"non-default\"/>\n"
|
||||
+ " <property xil_pn:name=\"Implementation Top File\" xil_pn:value=\"%1$s\" xil_pn:valueState=\"non-default\"/>\n"
|
||||
+ " <property xil_pn:name=\"Working Directory\" xil_pn:value=\".\" xil_pn:valueState=\"non-default\"/>\n"
|
||||
+ " </properties>\n"
|
||||
+ " <bindings/>\n"
|
||||
+ " <libraries/>\n"
|
||||
+ "</project>\n";
|
||||
|
||||
@Override
|
||||
public void writeFiles(File path, HDLModel model) throws IOException {
|
||||
String projectName = path.getName();
|
||||
if (projectName.endsWith(".v"))
|
||||
projectName = projectName.substring(0, projectName.length() - 2);
|
||||
else if (projectName.endsWith(".vhdl"))
|
||||
projectName = projectName.substring(0, projectName.length() - 5);
|
||||
File constraints = new File(path.getParentFile(), projectName.replace('.', '_') + "_constraints.ucf");
|
||||
try (CodePrinter out = new CodePrinter(new FileOutputStream(constraints))) {
|
||||
writeConstraints(out, model);
|
||||
}
|
||||
createISEProject(path.getParentFile(), projectName, path, constraints);
|
||||
}
|
||||
|
||||
private void writeConstraints(CodePrinter out, HDLModel model) throws IOException {
|
||||
for (HDLPort p : model.getMain().getPorts()) {
|
||||
if (p.getBits() == 1) {
|
||||
writePin(out, p.getName(), p.getPinNumber());
|
||||
} else {
|
||||
SplitPinString pins = SplitPinString.create(p.getPinNumber());
|
||||
for (int i = 0; i < p.getBits(); i++) {
|
||||
writePin(out, p.getName() + "[" + i + "]", pins.getPin(i));
|
||||
out.println();
|
||||
}
|
||||
}
|
||||
|
||||
out.println();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the pin information to a Xilinx UCF (User Constraints File)
|
||||
*
|
||||
* @param out the code printer
|
||||
* @param name the signal name
|
||||
* @param pinNumber the pin name
|
||||
* @throws IOException IOException
|
||||
*/
|
||||
abstract void writePin(CodePrinter out, String name, String pinNumber) throws IOException;
|
||||
|
||||
/**
|
||||
* Returns the FPGA board information (Family, Code and Package in that order)
|
||||
*
|
||||
* @return The board information
|
||||
*/
|
||||
abstract BoardInformation getBoardInfo();
|
||||
|
||||
private void createISEProject(File path, String projectName, File srcFile, File constraints) throws IOException {
|
||||
String projectDir = projectName + "_ise";
|
||||
File projectPath = new File(path, projectDir);
|
||||
// don't overwrite existing projects!
|
||||
if (!projectPath.exists()) {
|
||||
if (projectPath.mkdirs()) {
|
||||
File projectFile = new File(projectPath, projectName + ".xise");
|
||||
try (BufferedWriter w = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(projectFile), "utf-8"))) {
|
||||
writeISEProject(w, projectFile, srcFile, constraints);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void writeISEProject(BufferedWriter w, File project, File srcFile, File constraints) throws IOException {
|
||||
BoardInformation bi = getBoardInfo();
|
||||
|
||||
w.write(String.format(ISE_PROJECT_TPLT, "../" + srcFile.getName(),
|
||||
"../" + constraints.getName(), bi.getFamily(), bi.getCode(), bi.getPkg()));
|
||||
}
|
||||
|
||||
static class BoardInformation {
|
||||
private final String family;
|
||||
private final String code;
|
||||
private final String pkg;
|
||||
|
||||
BoardInformation(String family, String code, String pkg) {
|
||||
this.family = family;
|
||||
this.code = code;
|
||||
this.pkg = pkg;
|
||||
}
|
||||
|
||||
public String getFamily() {
|
||||
return family;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getPkg() {
|
||||
return pkg;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Ivan Deras
|
||||
* 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.boards;
|
||||
|
||||
import de.neemann.digital.hdl.model2.clock.HDLClockIntegrator;
|
||||
import de.neemann.digital.hdl.printer.CodePrinter;
|
||||
import de.neemann.digital.lang.Lang;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Mimas Board Version 1
|
||||
*/
|
||||
public class MimasV1Board extends ISE {
|
||||
private static final BoardInformation BOARD_INFO = new BoardInformation("Spartan6", "xc6slx9", "tqg144");
|
||||
private static final BoardClockInfo[] BOARD_CLOCKPINS = {
|
||||
new BoardClockInfo("P126", 10)
|
||||
};
|
||||
/**
|
||||
* Initialize a new instance
|
||||
*/
|
||||
public MimasV1Board() {
|
||||
}
|
||||
|
||||
@Override
|
||||
void writePin(CodePrinter out, String name, String pinNumber) throws IOException {
|
||||
if (pinNumber == null || pinNumber.length() == 0)
|
||||
throw new IOException(Lang.get("err_vhdlPin_N_hasNoNumber", name));
|
||||
|
||||
String line = String.format("NET \"%s\" LOC = \"%s\" | IOSTANDARD = LVCMOS33", name, pinNumber);
|
||||
|
||||
switch (pinNumber) {
|
||||
case "P126":
|
||||
line += String.format(";\nTIMESPEC TS_CLK = PERIOD \"%s\" 100 MHz HIGH 50%%;\n", name);
|
||||
break;
|
||||
/* Switch pins */
|
||||
case "P124":
|
||||
case "P123":
|
||||
case "P121":
|
||||
case "P120":
|
||||
line += " | DRIVE = 8 | SLEW = FAST | PULLUP";
|
||||
break;
|
||||
default:
|
||||
line += " | DRIVE = 8 | SLEW = FAST";
|
||||
}
|
||||
|
||||
line += ";";
|
||||
|
||||
out.print(line);
|
||||
}
|
||||
|
||||
@Override
|
||||
BoardInformation getBoardInfo() {
|
||||
return BOARD_INFO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HDLClockIntegrator getClockIntegrator() {
|
||||
return new ClockIntegratorSpartan6(BOARD_CLOCKPINS);
|
||||
}
|
||||
}
|
@ -1,76 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Ivan Deras
|
||||
* 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.boards;
|
||||
|
||||
import de.neemann.digital.hdl.model2.clock.HDLClockIntegrator;
|
||||
import de.neemann.digital.hdl.printer.CodePrinter;
|
||||
import de.neemann.digital.lang.Lang;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Mimas Board Version 2
|
||||
*/
|
||||
public class MimasV2Board extends ISE {
|
||||
private static final BoardInformation BOARD_INFO = new BoardInformation("Spartan6", "xc6slx9", "csg324");
|
||||
private static final BoardClockInfo[] BOARD_CLOCKPINS = {
|
||||
new BoardClockInfo("V10", 10),
|
||||
new BoardClockInfo("D9", 83.33)
|
||||
};
|
||||
/**
|
||||
* Initialize a new instance
|
||||
*/
|
||||
public MimasV2Board() {
|
||||
}
|
||||
|
||||
@Override
|
||||
void writePin(CodePrinter out, String name, String pinNumber) throws IOException {
|
||||
if (pinNumber == null || pinNumber.length() == 0)
|
||||
throw new IOException(Lang.get("err_vhdlPin_N_hasNoNumber", name));
|
||||
|
||||
String line = String.format("NET \"%s\" LOC = \"%s\" | IOSTANDARD = LVCMOS33", name, pinNumber);
|
||||
|
||||
switch (pinNumber) {
|
||||
case "V10":
|
||||
line += " | PERIOD = 100MHz";
|
||||
break;
|
||||
case "D9":
|
||||
line += " | PERIOD = 12MHz";
|
||||
break;
|
||||
case "C17":
|
||||
case "C18":
|
||||
case "D17":
|
||||
case "D18":
|
||||
case "E18":
|
||||
case "E16":
|
||||
case "F18":
|
||||
case "F17":
|
||||
case "M18":
|
||||
case "L18":
|
||||
case "M16":
|
||||
case "L17":
|
||||
case "K17":
|
||||
case "K18":
|
||||
line += " | DRIVE = 8 | SLEW = FAST | PULLUP";
|
||||
break;
|
||||
default:
|
||||
line += " | DRIVE = 8 | SLEW = FAST";
|
||||
}
|
||||
|
||||
line += ";";
|
||||
|
||||
out.print(line);
|
||||
}
|
||||
|
||||
@Override
|
||||
BoardInformation getBoardInfo() {
|
||||
return BOARD_INFO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HDLClockIntegrator getClockIntegrator() {
|
||||
return new ClockIntegratorSpartan6(BOARD_CLOCKPINS);
|
||||
}
|
||||
}
|
@ -1,150 +0,0 @@
|
||||
/*
|
||||
* 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.boards;
|
||||
|
||||
import de.neemann.digital.analyse.SplitPinString;
|
||||
import de.neemann.digital.hdl.model2.clock.HDLClockIntegrator;
|
||||
import de.neemann.digital.hdl.model2.HDLModel;
|
||||
import de.neemann.digital.hdl.model2.HDLPort;
|
||||
import de.neemann.digital.hdl.printer.CodePrinter;
|
||||
import de.neemann.digital.lang.Lang;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* Creates the needed vivado files.
|
||||
* Up to now only the constraints file containing the pin assignments is created
|
||||
*/
|
||||
public class Vivado implements BoardInterface {
|
||||
|
||||
private final String pinIoType;
|
||||
private final String clockPin;
|
||||
private final int periodns;
|
||||
private final HDLClockIntegrator clockIntegrator;
|
||||
private final String device;
|
||||
|
||||
/**
|
||||
* Creates a new instance
|
||||
*
|
||||
* @param pinIoType the pin output type
|
||||
* @param clockPin the pin the clock is connected to
|
||||
* @param periodns the clock period in nano seconds
|
||||
* @param clockIntegrator the clock integrator to use
|
||||
* @param device the xilinx device code
|
||||
*/
|
||||
public Vivado(String pinIoType, String clockPin, int periodns, HDLClockIntegrator clockIntegrator, String device) {
|
||||
this.pinIoType = pinIoType;
|
||||
this.clockPin = clockPin;
|
||||
this.periodns = periodns;
|
||||
this.clockIntegrator = clockIntegrator;
|
||||
this.device = device;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeFiles(File path, HDLModel model) throws IOException {
|
||||
String projectName = path.getName();
|
||||
if (projectName.endsWith(".vhdl"))
|
||||
projectName = projectName.substring(0, projectName.length() - 5);
|
||||
File constraints = new File(path.getParentFile(), projectName.replace('.', '_') + "_constraints.xdc");
|
||||
try (CodePrinter out = new CodePrinter(new FileOutputStream(constraints))) {
|
||||
writeConstraints(out, model);
|
||||
}
|
||||
createVivadoProject(path.getParentFile(), projectName, path, constraints);
|
||||
}
|
||||
|
||||
private void writeConstraints(CodePrinter out, HDLModel model) throws IOException {
|
||||
for (HDLPort p : model.getMain().getPorts()) {
|
||||
if (p.getBits() == 1) {
|
||||
writePin(out, p.getName(), p.getPinNumber());
|
||||
if (p.getPinNumber().equals(clockPin))
|
||||
out
|
||||
.print("create_clock -add -name sys_clk_pin -period ")
|
||||
.print(periodns)
|
||||
.print(" -waveform {0 5} [get_ports ")
|
||||
.print(p.getName())
|
||||
.println("]");
|
||||
} else {
|
||||
SplitPinString pins = SplitPinString.create(p.getPinNumber());
|
||||
for (int i = 0; i < p.getBits(); i++)
|
||||
writePin(out, p.getName() + "[" + i + "]", pins.getPin(i));
|
||||
}
|
||||
|
||||
|
||||
out.println();
|
||||
}
|
||||
|
||||
out.println("set_property CFGBVS VCCO [current_design]");
|
||||
out.println("set_property CONFIG_VOLTAGE 3.3 [current_design]");
|
||||
}
|
||||
|
||||
private void writePin(CodePrinter out, String name, String pinNumber) throws IOException {
|
||||
if (pinNumber == null || pinNumber.length() == 0)
|
||||
throw new IOException(Lang.get("err_vhdlPin_N_hasNoNumber", name));
|
||||
|
||||
out.print("set_property PACKAGE_PIN ").print(pinNumber).print(" [get_ports ").print(name).println("]");
|
||||
out.print("set_property IOSTANDARD ").print(pinIoType).print(" [get_ports ").print(name).println("]");
|
||||
}
|
||||
|
||||
@Override
|
||||
public HDLClockIntegrator getClockIntegrator() {
|
||||
return clockIntegrator;
|
||||
}
|
||||
|
||||
private void createVivadoProject(File path, String projectName, File vhdl, File constraints) throws IOException {
|
||||
String projectDir = projectName + "_vivado";
|
||||
File projectPath = new File(path, projectDir);
|
||||
// don't overwrite existing projects!
|
||||
if (!projectPath.exists()) {
|
||||
if (projectPath.mkdirs()) {
|
||||
File projectFile = new File(projectPath, projectName + ".xpr");
|
||||
try (BufferedWriter w = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(projectFile), "utf-8"))) {
|
||||
writeVivadoProject(w, projectFile, vhdl, constraints);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void writeVivadoProject(BufferedWriter w, File project, File vhdl, File constraints) throws IOException {
|
||||
w.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||
+ "<!-- Created by Digital -->\n"
|
||||
+ "\n"
|
||||
+ "<Project Version=\"7\" Minor=\"20\" Path=\"" + project.getPath() + "\">\n"
|
||||
+ " <DefaultLaunch Dir=\"$PRUNDIR\"/>\n"
|
||||
+ " <Configuration>\n"
|
||||
+ " <Option Name=\"Part\" Val=\"" + device + "\"/>\n"
|
||||
+ " </Configuration>\n"
|
||||
+ " <FileSets Version=\"1\" Minor=\"31\">\n"
|
||||
+ " <FileSet Name=\"sources_1\" Type=\"DesignSrcs\" RelSrcDir=\"$PSRCDIR/sources_1\">\n"
|
||||
+ " <Filter Type=\"Srcs\"/>\n"
|
||||
+ " <File Path=\"$PPRDIR/../" + vhdl.getName() + "\">\n"
|
||||
+ " <FileInfo>\n"
|
||||
+ " <Attr Name=\"UsedIn\" Val=\"synthesis\"/>\n"
|
||||
+ " <Attr Name=\"UsedIn\" Val=\"simulation\"/>\n"
|
||||
+ " </FileInfo>\n"
|
||||
+ " </File>\n"
|
||||
+ " <Config>\n"
|
||||
+ " <Option Name=\"DesignMode\" Val=\"RTL\"/>\n"
|
||||
+ " <Option Name=\"TopModule\" Val=\"main\"/>\n"
|
||||
+ " <Option Name=\"TopAutoSet\" Val=\"TRUE\"/>\n"
|
||||
+ " </Config>\n"
|
||||
+ " </FileSet>\n"
|
||||
+ " <FileSet Name=\"constrs_1\" Type=\"Constrs\" RelSrcDir=\"$PSRCDIR/constrs_1\">\n"
|
||||
+ " <Filter Type=\"Constrs\"/>\n"
|
||||
+ " <File Path=\"$PPRDIR/../" + constraints.getName() + "\">\n"
|
||||
+ " <FileInfo>\n"
|
||||
+ " <Attr Name=\"UsedIn\" Val=\"synthesis\"/>\n"
|
||||
+ " <Attr Name=\"UsedIn\" Val=\"implementation\"/>\n"
|
||||
+ " </FileInfo>\n"
|
||||
+ " </File>\n"
|
||||
+ " <Config>\n"
|
||||
+ " <Option Name=\"ConstrsType\" Val=\"XDC\"/>\n"
|
||||
+ " </Config>\n"
|
||||
+ " </FileSet>\n"
|
||||
+ " </FileSets>\n"
|
||||
+ "</Project>");
|
||||
}
|
||||
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Support for different boards.
|
||||
* The classes in this package are able to create the files needed
|
||||
* to run a vhdl or verilog file on a board.
|
||||
*/
|
||||
package de.neemann.digital.hdl.boards;
|
@ -17,8 +17,6 @@ import de.neemann.digital.hdl.model2.HDLModel;
|
||||
import de.neemann.digital.hdl.model2.HDLNet;
|
||||
import de.neemann.digital.hdl.model2.clock.HDLClockIntegrator;
|
||||
import de.neemann.digital.hdl.printer.CodePrinter;
|
||||
import de.neemann.digital.hdl.boards.BoardInterface;
|
||||
import de.neemann.digital.hdl.boards.BoardProvider;
|
||||
import de.neemann.digital.lang.Lang;
|
||||
|
||||
import java.io.Closeable;
|
||||
@ -34,7 +32,6 @@ public class VerilogGenerator implements Closeable {
|
||||
private final ElementLibrary library;
|
||||
private final CodePrinter out;
|
||||
private ArrayList<File> testBenches;
|
||||
private boolean useClockIntegration = true;
|
||||
private HDLModel model;
|
||||
private HDLClockIntegrator clockIntegrator;
|
||||
|
||||
@ -71,11 +68,6 @@ public class VerilogGenerator implements Closeable {
|
||||
if (!circuit.getAttributes().get(Keys.ROMMANAGER).isEmpty())
|
||||
throw new HDLException(Lang.get("err_centralDefinedRomsAreNotSupported"));
|
||||
|
||||
BoardInterface board = BoardProvider.getInstance().getBoard(circuit);
|
||||
|
||||
if (board != null && useClockIntegration)
|
||||
clockIntegrator = board.getClockIntegrator();
|
||||
|
||||
model = new HDLModel(library).create(circuit, clockIntegrator);
|
||||
for (HDLCircuit hdlCircuit : model)
|
||||
hdlCircuit.applyDefaultOptimizations();
|
||||
@ -103,9 +95,6 @@ public class VerilogGenerator implements Closeable {
|
||||
testBenches = new VerilogTestBenchCreator(circuit, model, topModuleName)
|
||||
.write(outFile)
|
||||
.getTestFileWritten();
|
||||
|
||||
if (board != null)
|
||||
board.writeFiles(outFile, model);
|
||||
}
|
||||
|
||||
return this;
|
||||
@ -171,15 +160,4 @@ public class VerilogGenerator implements Closeable {
|
||||
public HDLModel getModel() {
|
||||
return model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables the clock integration.
|
||||
* Used only for the tests.
|
||||
*
|
||||
* @return this for chained calls
|
||||
*/
|
||||
public VerilogGenerator disableClockIntegration() {
|
||||
useClockIntegration = false;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
@ -17,8 +17,6 @@ import de.neemann.digital.hdl.model2.HDLModel;
|
||||
import de.neemann.digital.hdl.model2.HDLNet;
|
||||
import de.neemann.digital.hdl.model2.clock.HDLClockIntegrator;
|
||||
import de.neemann.digital.hdl.printer.CodePrinter;
|
||||
import de.neemann.digital.hdl.boards.BoardInterface;
|
||||
import de.neemann.digital.hdl.boards.BoardProvider;
|
||||
import de.neemann.digital.lang.Lang;
|
||||
|
||||
import java.io.Closeable;
|
||||
@ -38,7 +36,6 @@ public class VHDLGenerator implements Closeable {
|
||||
private final ElementLibrary library;
|
||||
private final CodePrinter out;
|
||||
private ArrayList<File> testBenches;
|
||||
private boolean useClockIntegration = true;
|
||||
private HDLModel model;
|
||||
private HDLClockIntegrator clockIntegrator;
|
||||
|
||||
@ -66,11 +63,6 @@ public class VHDLGenerator implements Closeable {
|
||||
if (!circuit.getAttributes().get(Keys.ROMMANAGER).isEmpty())
|
||||
throw new HDLException(Lang.get("err_centralDefinedRomsAreNotSupported"));
|
||||
|
||||
BoardInterface board = BoardProvider.getInstance().getBoard(circuit);
|
||||
|
||||
if (board != null && useClockIntegration)
|
||||
clockIntegrator = board.getClockIntegrator();
|
||||
|
||||
model = new HDLModel(library).create(circuit, clockIntegrator);
|
||||
for (HDLCircuit hdlCircuit : model)
|
||||
hdlCircuit.applyDefaultOptimizations();
|
||||
@ -90,9 +82,6 @@ public class VHDLGenerator implements Closeable {
|
||||
testBenches = new VHDLTestBenchCreator(circuit, model)
|
||||
.write(outFile)
|
||||
.getTestFileWritten();
|
||||
|
||||
if (board != null)
|
||||
board.writeFiles(outFile, model);
|
||||
}
|
||||
|
||||
return this;
|
||||
@ -161,17 +150,6 @@ public class VHDLGenerator implements Closeable {
|
||||
out.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables the clock integration.
|
||||
* Used only for the tests.
|
||||
*
|
||||
* @return this for chained calls
|
||||
*/
|
||||
public VHDLGenerator disableClockIntegration() {
|
||||
useClockIntegration = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the hdl model
|
||||
*/
|
||||
|
@ -946,7 +946,6 @@ Sind evtl. die Namen der Variablen nicht eindeutig?</string>
|
||||
<string name="err_vhdlExporting">Fehler beim Export zu VHDL.</string>
|
||||
<string name="err_vhdlNoEntity_N">Kein VHDL Code für {0} verfügbar!</string>
|
||||
<string name="err_verilogNoElement_N">Kein Verilog Code für {0} verfügbar!</string>
|
||||
<string name="err_vhdlPin_N_hasNoNumber">Der Pin {0} hat keine Nummer!</string>
|
||||
<string name="err_vhdlErrorWritingTestBench">Fehler beim erzeugen des Testfalls!</string>
|
||||
<string name="err_vhdlValuesOfType_N_notAllowed">Werte vom Typ {0} sind nicht erlaubt!</string>
|
||||
<string name="err_vhdlANameIsMissing">Es fehlt ein Name. Sind z.B. alle Pins benannt?</string>
|
||||
|
@ -938,7 +938,6 @@
|
||||
<string name="err_vhdlExporting">Error during export to VHDL.</string>
|
||||
<string name="err_vhdlNoEntity_N">No VHDL code for {0} available!</string>
|
||||
<string name="err_verilogNoElement_N">No Verilog code for {0} available!</string>
|
||||
<string name="err_vhdlPin_N_hasNoNumber">Pin {0} has no number!</string>
|
||||
<string name="err_vhdlErrorWritingTestBench">Error creating a test bench!</string>
|
||||
<string name="err_vhdlValuesOfType_N_notAllowed">Values of typ {0} are not allowed!</string>
|
||||
<string name="err_vhdlANameIsMissing">A name is missing. Have e.g. all pins a label set?</string>
|
||||
|
@ -815,7 +815,6 @@
|
||||
<string name="err_vhdlExporting">Error en la exportación a VHDL.</string>
|
||||
<string name="err_vhdlNoEntity_N">¡No hay código VHDL disponible para {0}!</string>
|
||||
<string name="err_verilogNoElement_N">¡No hay código Verilog disponible para {0}!</string>
|
||||
<string name="err_vhdlPin_N_hasNoNumber">¡El pin {0} no tiene ningún número!</string>
|
||||
<string name="err_vhdlErrorWritingTestBench">¡Error en la creación del módulo de estímulo (test bench)!</string>
|
||||
<string name="err_vhdlValuesOfType_N_notAllowed">¡Los valores del tipo {0} no están permitidos!</string>
|
||||
<string name="err_vhdlANameIsMissing">Falta un nombre. Por ejemplo: ¿tienen todos los pines una etiqueta?</string>
|
||||
|
@ -824,7 +824,6 @@
|
||||
<string name="err_vhdlExporting">Error during export to VHDL.</string>
|
||||
<string name="err_vhdlNoEntity_N">No VHDL code for {0} available!</string>
|
||||
<string name="err_verilogNoElement_N">No Verilog code for {0} available!</string>
|
||||
<string name="err_vhdlPin_N_hasNoNumber">Pin {0} has no number!</string>
|
||||
<string name="err_vhdlErrorWritingTestBench">Error creating a test bench!</string>
|
||||
<string name="err_vhdlValuesOfType_N_notAllowed">Values of typ {0} are not allowed!</string>
|
||||
<string name="err_vhdlANameIsMissing">A name is missing. Have e.g. all pins a label set?</string>
|
||||
|
@ -829,7 +829,6 @@
|
||||
<string name="err_vhdlExporting">Erro ao exportar para VHDL.</string>
|
||||
<string name="err_vhdlNoEntity_N">Nenhum código VHDL disponível para {0}!</string>
|
||||
<string name="err_verilogNoElement_N">Nenhum código Verilog disponível para {0}!</string>
|
||||
<string name="err_vhdlPin_N_hasNoNumber">Pino {0} sem número!</string>
|
||||
<string name="err_vhdlErrorWritingTestBench">Erro ao criar os casos de testes!</string>
|
||||
<string name="err_vhdlValuesOfType_N_notAllowed">Valores de tipo {0} não são permitidos!</string>
|
||||
<string name="err_vhdlANameIsMissing">Falta nome. Todos os pinos têm rótulos (por exemplo)?</string>
|
||||
|
@ -834,7 +834,6 @@
|
||||
<string name="err_vhdlExporting">Error during export to VHDL.</string>
|
||||
<string name="err_vhdlNoEntity_N">No VHDL code for {0} available!</string>
|
||||
<string name="err_verilogNoElement_N">No Verilog code for {0} available!</string>
|
||||
<string name="err_vhdlPin_N_hasNoNumber">Pin {0} has no number!</string>
|
||||
<string name="err_vhdlErrorWritingTestBench">Error creating a test bench!</string>
|
||||
<string name="err_vhdlValuesOfType_N_notAllowed">Values of typ {0} are not allowed!</string>
|
||||
<string name="err_vhdlANameIsMissing">A name is missing. Have e.g. all pins a label set?</string>
|
||||
|
@ -1,92 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Ivan Deras.
|
||||
* 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.boards;
|
||||
|
||||
import de.neemann.digital.core.NodeException;
|
||||
import de.neemann.digital.draw.elements.PinException;
|
||||
import de.neemann.digital.draw.library.ElementNotFoundException;
|
||||
import de.neemann.digital.hdl.model2.HDLException;
|
||||
import de.neemann.digital.hdl.model2.HDLModel;
|
||||
import de.neemann.digital.integration.ToBreakRunner;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
public class ISEProjectGeneratorTest extends TestCase {
|
||||
|
||||
public void testISEProjectExport() throws IOException, PinException, NodeException, ElementNotFoundException, HDLException {
|
||||
HDLModel m = createModel("dig/hdl/model2/clock_mimasv1.dig");
|
||||
MimasV1Board b = new MimasV1Board();
|
||||
File dir = Files.createTempDirectory("digital_verilog_" + getTime() + "_").toFile();
|
||||
File file = new File(dir, "clock_mimasv1.v");
|
||||
|
||||
System.out.println(dir.getAbsolutePath());
|
||||
b.writeFiles(file, m);
|
||||
File iseProjectFile = new File(dir, "clock_mimasv1_ise" + File.separator + "clock_mimasv1.xise");
|
||||
String output = readAllFile(iseProjectFile);
|
||||
|
||||
assertEquals( "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>\n"
|
||||
+ "<project xmlns=\"http://www.xilinx.com/XMLSchema\" xmlns:xil_pn=\"http://www.xilinx.com/XMLSchema\">\n"
|
||||
+ " <header>\n"
|
||||
+ " </header>\n"
|
||||
+ " <version xil_pn:ise_version=\"14.7\" xil_pn:schema_version=\"2\"/>\n"
|
||||
+ " <files>\n"
|
||||
+ " <file xil_pn:name=\"../clock_mimasv1.v\" xil_pn:type=\"FILE_VERILOG\">\n"
|
||||
+ " <association xil_pn:name=\"BehavioralSimulation\" xil_pn:seqID=\"2\"/>\n"
|
||||
+ " <association xil_pn:name=\"Implementation\" xil_pn:seqID=\"2\"/>\n"
|
||||
+ " </file>\n"
|
||||
+ " <file xil_pn:name=\"../clock_mimasv1_constraints.ucf\" xil_pn:type=\"FILE_UCF\">\n"
|
||||
+ " <association xil_pn:name=\"Implementation\" xil_pn:seqID=\"0\"/>\n"
|
||||
+ " </file>\n"
|
||||
+ " </files>\n"
|
||||
+ " <autoManagedFiles>\n"
|
||||
+ " </autoManagedFiles>\n"
|
||||
+ " <properties>\n"
|
||||
+ " <property xil_pn:name=\"Create Binary Configuration File\" xil_pn:value=\"true\" xil_pn:valueState=\"non-default\"/>\n"
|
||||
+ " <property xil_pn:name=\"Create Bit File\" xil_pn:value=\"true\" xil_pn:valueState=\"default\"/>\n"
|
||||
+ " <property xil_pn:name=\"Device Family\" xil_pn:value=\"Spartan6\" xil_pn:valueState=\"non-default\"/>\n"
|
||||
+ " <property xil_pn:name=\"Device\" xil_pn:value=\"xc6slx9\" xil_pn:valueState=\"non-default\"/>\n"
|
||||
+ " <property xil_pn:name=\"Package\" xil_pn:value=\"tqg144\" xil_pn:valueState=\"non-default\"/>\n"
|
||||
+ " <property xil_pn:name=\"Implementation Top File\" xil_pn:value=\"../clock_mimasv1.v\" xil_pn:valueState=\"non-default\"/>\n"
|
||||
+ " <property xil_pn:name=\"Working Directory\" xil_pn:value=\".\" xil_pn:valueState=\"non-default\"/>\n"
|
||||
+ " </properties>\n"
|
||||
+ " <bindings/>\n"
|
||||
+ " <libraries/>\n"
|
||||
+ "</project>\n", output);
|
||||
}
|
||||
|
||||
private String readAllFile(File f) throws FileNotFoundException, IOException {
|
||||
BufferedReader r = new BufferedReader(new FileReader(f));
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String str;
|
||||
|
||||
while ((str = r.readLine()) != null) {
|
||||
sb.append(str).append("\n");
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
HDLModel createModel(String filePath) throws IOException, PinException, NodeException, ElementNotFoundException, HDLException {
|
||||
ToBreakRunner br = new ToBreakRunner(filePath);
|
||||
|
||||
HDLModel m = new HDLModel(br.getLibrary());
|
||||
|
||||
return m.create(br.getCircuit(), null);
|
||||
}
|
||||
|
||||
private String getTime() {
|
||||
DateFormat f = new SimpleDateFormat("YY-MM-dd_HH-mm_ss");
|
||||
return f.format(new Date());
|
||||
}
|
||||
}
|
@ -131,7 +131,7 @@ public class VerilogSimulatorTest extends TestCase {
|
||||
.replace('-', '_')+ ".v");
|
||||
CodePrinter out = new CodePrinter(srcFile);
|
||||
try (VerilogGenerator gen = new VerilogGenerator(br.getLibrary(), out)) {
|
||||
gen.disableClockIntegration().export(br.getCircuit());
|
||||
gen.export(br.getCircuit());
|
||||
ArrayList<File> testFiles = gen.getTestBenches();
|
||||
out.close();
|
||||
runIVerilog(srcFile, testFiles);
|
||||
|
@ -16,7 +16,6 @@ import de.neemann.digital.hdl.model2.clock.ClockIntegratorGeneric;
|
||||
import de.neemann.digital.hdl.model2.clock.HDLClockIntegrator;
|
||||
import de.neemann.digital.hdl.printer.CodePrinter;
|
||||
import de.neemann.digital.hdl.printer.CodePrinterStr;
|
||||
import de.neemann.digital.hdl.boards.ClockIntegratorARTIX7;
|
||||
import de.neemann.digital.integration.ToBreakRunner;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
@ -119,176 +118,6 @@ public class ClockTest extends TestCase {
|
||||
"end Behavioral;\n", code);
|
||||
}
|
||||
|
||||
public void testARTIX() throws ElementNotFoundException, NodeException, PinException, IOException, HDLException, HGSEvalException {
|
||||
String code = create(new ClockIntegratorARTIX7(10));
|
||||
assertEquals("\n" +
|
||||
"LIBRARY ieee;\n" +
|
||||
"USE ieee.std_logic_1164.all;\n" +
|
||||
"\n" +
|
||||
"Library UNISIM;\n" +
|
||||
"use UNISIM.vcomponents.all;\n" +
|
||||
"\n" +
|
||||
"entity DIG_MMCME2_BASE is\n" +
|
||||
" generic (\n" +
|
||||
" D_PARAM : integer;\n" +
|
||||
" M_PARAM : real;\n" +
|
||||
"\n" +
|
||||
" DIV_PARAM : integer;\n" +
|
||||
" DIV4_PARAM : integer;\n" +
|
||||
"\n" +
|
||||
" PERIOD_PARAM: real);\n" +
|
||||
" port (\n" +
|
||||
" cin: in std_logic;\n" +
|
||||
" cout: out std_logic );\n" +
|
||||
"end DIG_MMCME2_BASE;\n" +
|
||||
"\n" +
|
||||
"architecture DIG_MMCME2_BASE_arch of DIG_MMCME2_BASE is\n" +
|
||||
"\n" +
|
||||
" signal DEV_NULL: std_logic;\n" +
|
||||
" signal feedback: std_logic;\n" +
|
||||
"\n" +
|
||||
"begin\n" +
|
||||
"\n" +
|
||||
"DEV_NULL <= '0';\n" +
|
||||
"\n" +
|
||||
"-- code taken from the \"Vivado Design Suite 7 Series FPGA Libraries Guide\" (UG953)\n" +
|
||||
"\n" +
|
||||
"MMCME2_BASE_inst : MMCME2_BASE\n" +
|
||||
"generic map (\n" +
|
||||
"BANDWIDTH => \"OPTIMIZED\", -- Jitter programming (OPTIMIZED, HIGH, LOW)\n" +
|
||||
"CLKFBOUT_MULT_F => M_PARAM,\n" +
|
||||
"-- Multiply value for all CLKOUT (2.000-64.000).\n" +
|
||||
"DIVCLK_DIVIDE => D_PARAM,\n" +
|
||||
"-- Master division value (1-106)\n" +
|
||||
"CLKFBOUT_PHASE => 0.0,\n" +
|
||||
"-- Phase offset in degrees of CLKFB (-360.000-360.000).\n" +
|
||||
"CLKIN1_PERIOD => PERIOD_PARAM,\n" +
|
||||
"-- Input clock period in ns to ps resolution (i.e. 33.333 is 30 MHz).\n" +
|
||||
"-- CLKOUT0_DIVIDE - CLKOUT6_DIVIDE: Divide amount for each CLKOUT (1-128)\n" +
|
||||
"CLKOUT1_DIVIDE => 1,\n" +
|
||||
"CLKOUT2_DIVIDE => 1,\n" +
|
||||
"CLKOUT3_DIVIDE => 1,\n" +
|
||||
"\n" +
|
||||
"CLKOUT4_DIVIDE => DIV4_PARAM,\n" +
|
||||
"CLKOUT5_DIVIDE => 1,\n" +
|
||||
"CLKOUT6_DIVIDE => DIV_PARAM,\n" +
|
||||
"CLKOUT0_DIVIDE_F => 1.0,\n" +
|
||||
"\n" +
|
||||
"-- Divide amount for CLKOUT0 (1.000-128.000).\n" +
|
||||
"-- CLKOUT0_DUTY_CYCLE - CLKOUT6_DUTY_CYCLE: Duty cycle for each CLKOUT (0.01-0.99).\n" +
|
||||
"CLKOUT0_DUTY_CYCLE => 0.5,\n" +
|
||||
"CLKOUT1_DUTY_CYCLE => 0.5,\n" +
|
||||
"CLKOUT2_DUTY_CYCLE => 0.5,\n" +
|
||||
"CLKOUT3_DUTY_CYCLE => 0.5,\n" +
|
||||
"CLKOUT4_DUTY_CYCLE => 0.5,\n" +
|
||||
"CLKOUT5_DUTY_CYCLE => 0.5,\n" +
|
||||
"CLKOUT6_DUTY_CYCLE => 0.5,\n" +
|
||||
"-- CLKOUT0_PHASE - CLKOUT6_PHASE: Phase offset for each CLKOUT (-360.000-360.000).\n" +
|
||||
"CLKOUT0_PHASE => 0.0,\n" +
|
||||
"CLKOUT1_PHASE => 0.0,\n" +
|
||||
"CLKOUT2_PHASE => 0.0,\n" +
|
||||
"CLKOUT3_PHASE => 0.0,\n" +
|
||||
"CLKOUT4_PHASE => 0.0,\n" +
|
||||
"CLKOUT5_PHASE => 0.0,\n" +
|
||||
"CLKOUT6_PHASE => 0.0,\n" +
|
||||
"\n" +
|
||||
"CLKOUT4_CASCADE => true, -- Cascade CLKOUT4 counter with CLKOUT6 (FALSE, TRUE)\n" +
|
||||
"\n" +
|
||||
"REF_JITTER1 => 0.0,\n" +
|
||||
"-- Reference input jitter in UI (0.000-0.999).\n" +
|
||||
"STARTUP_WAIT => TRUE\n" +
|
||||
"-- Delays DONE until MMCM is locked (FALSE, TRUE)\n" +
|
||||
")\n" +
|
||||
"port map (\n" +
|
||||
"-- Clock Outputs: 1-bit (each) output: User configurable clock outputs\n" +
|
||||
"\n" +
|
||||
"CLKOUT4 => cout,\n" +
|
||||
"\n" +
|
||||
"-- 1-bit output: CLKOUT6\n" +
|
||||
"-- Feedback Clocks: 1-bit (each) output: Clock feedback ports\n" +
|
||||
"CLKFBOUT => feedback,\n" +
|
||||
"-- 1-bit output: Feedback clock\n" +
|
||||
"--CLKFBOUTB => CLKFBOUTB, -- 1-bit output: Inverted CLKFBOUT\n" +
|
||||
"-- Status Ports: 1-bit (each) output: MMCM status ports\n" +
|
||||
"--LOCKED => LOCKED,\n" +
|
||||
"-- 1-bit output: LOCK\n" +
|
||||
"-- Clock Inputs: 1-bit (each) input: Clock input\n" +
|
||||
"CLKIN1 => cin,\n" +
|
||||
"-- 1-bit input: Clock\n" +
|
||||
"-- Control Ports: 1-bit (each) input: MMCM control ports\n" +
|
||||
"PWRDWN => DEV_NULL,\n" +
|
||||
"-- 1-bit input: Power-down\n" +
|
||||
"RST => DEV_NULL,\n" +
|
||||
"-- 1-bit input: Reset\n" +
|
||||
"-- Feedback Clocks: 1-bit (each) input: Clock feedback ports\n" +
|
||||
"CLKFBIN => feedback\n" +
|
||||
"-- 1-bit input: Feedback clock\n" +
|
||||
");\n" +
|
||||
"\n" +
|
||||
"end DIG_MMCME2_BASE_arch;\n" +
|
||||
"\n" +
|
||||
"\n" +
|
||||
"LIBRARY ieee;\n" +
|
||||
"USE ieee.std_logic_1164.all;\n" +
|
||||
"\n" +
|
||||
"entity DIG_D_FF is\n" +
|
||||
" generic (\n" +
|
||||
" Default: std_logic ); \n" +
|
||||
" port ( D : in std_logic;\n" +
|
||||
" C : in std_logic;\n" +
|
||||
" Q : out std_logic;\n" +
|
||||
" notQ : out std_logic );\n" +
|
||||
"end DIG_D_FF;\n" +
|
||||
"\n" +
|
||||
"architecture Behavioral of DIG_D_FF is\n" +
|
||||
" signal state : std_logic := Default;\n" +
|
||||
"begin\n" +
|
||||
" Q <= state;\n" +
|
||||
" notQ <= NOT( state );\n" +
|
||||
"\n" +
|
||||
" process(C)\n" +
|
||||
" begin\n" +
|
||||
" if rising_edge(C) then\n" +
|
||||
" state <= D;\n" +
|
||||
" end if;\n" +
|
||||
" end process;\n" +
|
||||
"end Behavioral;\n" +
|
||||
"\n" +
|
||||
"\n" +
|
||||
"LIBRARY ieee;\n" +
|
||||
"USE ieee.std_logic_1164.all;\n" +
|
||||
"USE ieee.numeric_std.all;\n" +
|
||||
"\n" +
|
||||
"entity main is\n" +
|
||||
" port (\n" +
|
||||
" A: in std_logic;\n" +
|
||||
" C: in std_logic;\n" +
|
||||
" X: out std_logic);\n" +
|
||||
"end main;\n" +
|
||||
"\n" +
|
||||
"architecture Behavioral of main is\n" +
|
||||
" signal s0: std_logic;\n" +
|
||||
"begin\n" +
|
||||
" gate0: entity work.DIG_MMCME2_BASE\n" +
|
||||
" generic map (\n" +
|
||||
" D_PARAM => 1,\n" +
|
||||
" M_PARAM => 12.0,\n" +
|
||||
" DIV_PARAM => 10,\n" +
|
||||
" DIV4_PARAM => 120,\n" +
|
||||
" PERIOD_PARAM => 10.0)\n" +
|
||||
" port map (\n" +
|
||||
" cin => C,\n" +
|
||||
" cout => s0);\n" +
|
||||
" gate1: entity work.DIG_D_FF\n" +
|
||||
" generic map (\n" +
|
||||
" Default => '0')\n" +
|
||||
" port map (\n" +
|
||||
" D => A,\n" +
|
||||
" C => s0,\n" +
|
||||
" Q => X);\n" +
|
||||
"end Behavioral;\n", code);
|
||||
}
|
||||
|
||||
String create(HDLClockIntegrator ci) throws IOException, PinException, NodeException, ElementNotFoundException, HDLException, HGSEvalException {
|
||||
ToBreakRunner br = new ToBreakRunner("dig/hdl/model2/clock.dig");
|
||||
HDLCircuit c = new HDLCircuit(
|
||||
|
@ -128,7 +128,7 @@ public class VHDLSimulatorTest extends TestCase {
|
||||
.replace('-', '_')+ ".vhdl");
|
||||
CodePrinter out = new CodePrinter(vhdlFile);
|
||||
try (VHDLGenerator vhdl = new VHDLGenerator(br.getLibrary(), out)) {
|
||||
vhdl.disableClockIntegration().export(br.getCircuit());
|
||||
vhdl.export(br.getCircuit());
|
||||
ArrayList<File> testFiles = vhdl.getTestBenches();
|
||||
out.close();
|
||||
runGHDL(vhdlFile, testFiles);
|
||||
|
Loading…
x
Reference in New Issue
Block a user