mirror of
https://github.com/hneemann/Digital.git
synced 2025-09-28 07:28:20 -04:00
Initial tt2 support. not production ready!
This commit is contained in:
parent
ace69a0088
commit
a9ab9c0f16
353
src/main/java/de/neemann/digital/builder/tt2/TT2Exporter.java
Normal file
353
src/main/java/de/neemann/digital/builder/tt2/TT2Exporter.java
Normal file
@ -0,0 +1,353 @@
|
||||
package de.neemann.digital.builder.tt2;
|
||||
|
||||
import de.neemann.digital.analyse.expression.Expression;
|
||||
import de.neemann.digital.analyse.expression.Not;
|
||||
import de.neemann.digital.analyse.expression.Operation;
|
||||
import de.neemann.digital.analyse.expression.Variable;
|
||||
import de.neemann.digital.builder.*;
|
||||
import de.neemann.digital.builder.jedec.FuseMapFillerException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Exporter for the tt2 format needed by the ATF15xx fitters from ATMEL.
|
||||
* Created by hneemann on 03.03.17.
|
||||
*/
|
||||
public class TT2Exporter implements ExpressionExporter<TT2Exporter> {
|
||||
private BuilderCollector builder;
|
||||
private PinMap pinMap;
|
||||
private int clockPin;
|
||||
private String name;
|
||||
private String device;
|
||||
private OutputStreamWriter writer;
|
||||
private HashMap<String, Integer> varIndexMap;
|
||||
private HashMap<String, Integer> outIndexMap;
|
||||
private TreeMap<ProdInput, StateSet> termMap;
|
||||
private ArrayList<String> inputs;
|
||||
private ArrayList<String> outputs;
|
||||
|
||||
/**
|
||||
* Creates a new instance
|
||||
*/
|
||||
public TT2Exporter() {
|
||||
builder = new BuilderCollector();
|
||||
pinMap = new PinMap();
|
||||
device = "f1502plcc44";
|
||||
name = "unknown";
|
||||
clockPin = 43;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BuilderInterface getBuilder() {
|
||||
return builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the pin connected to the clock of the ff
|
||||
*
|
||||
* @param clockPin the pin number
|
||||
* @return this for chained calls
|
||||
*/
|
||||
public TT2Exporter setClockPin(int clockPin) {
|
||||
this.clockPin = clockPin;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the project name used
|
||||
*
|
||||
* @param name the project name
|
||||
* @return this for chained calls
|
||||
*/
|
||||
public TT2Exporter setName(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the device name used
|
||||
*
|
||||
* @param device the device name
|
||||
* @return this for chained calls
|
||||
*/
|
||||
public TT2Exporter setDevice(String device) {
|
||||
this.device = device;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PinMap getPinMapping() {
|
||||
return pinMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(OutputStream out) throws FuseMapFillerException, IOException, PinMapException {
|
||||
writeTo(new OutputStreamWriter(out, "ISO-8859-1"));
|
||||
}
|
||||
|
||||
private void writeTo(OutputStreamWriter writer) throws IOException, FuseMapFillerException, PinMapException {
|
||||
createProductTerms();
|
||||
|
||||
this.writer = writer;
|
||||
line("#$ TOOL CUPL");
|
||||
line("# Berkeley PLA format generated using Digital");
|
||||
line("#$ TITLE " + name);
|
||||
line("#$ MODULE " + name);
|
||||
line("#$ JEDECFILE " + name);
|
||||
line("#$ DEVICE " + device);
|
||||
line("#$ PINS " + getPins());
|
||||
line(".i " + inputs.size());
|
||||
line(".o " + outputs.size());
|
||||
line(".type f");
|
||||
line(".ilb " + strList(inputs));
|
||||
line(".ob " + strList(outputs));
|
||||
line(".phase " + getPhase());
|
||||
|
||||
line(".p " + termMap.size());
|
||||
for (Map.Entry<ProdInput, StateSet> e : termMap.entrySet())
|
||||
line(e.getKey() + " " + e.getValue());
|
||||
|
||||
line(".e");
|
||||
writer.close();
|
||||
}
|
||||
|
||||
private void createProductTerms() throws FuseMapFillerException {
|
||||
|
||||
inputs = builder.getInputs();
|
||||
varIndexMap = new HashMap<>();
|
||||
int i = 0;
|
||||
for (String name : inputs) {
|
||||
varIndexMap.put(name, i);
|
||||
i++;
|
||||
}
|
||||
|
||||
ProdInput clkIn = null;
|
||||
if (!builder.getRegistered().isEmpty()) {
|
||||
int clk = inputs.size();
|
||||
inputs.add("CLK");
|
||||
varIndexMap.put("CLK", i);
|
||||
i++;
|
||||
for (String reg : builder.getRegistered().keySet()) {
|
||||
inputs.add(reg + ".Q");
|
||||
varIndexMap.put(reg, i);
|
||||
i++;
|
||||
}
|
||||
|
||||
clkIn = new ProdInput(inputs.size());
|
||||
clkIn.set(clk, 1);
|
||||
}
|
||||
|
||||
ArrayList<Integer> clkInList = new ArrayList<Integer>();
|
||||
outputs = new ArrayList<>();
|
||||
outIndexMap = new HashMap<>();
|
||||
i = 0;
|
||||
for (String name : builder.getOutputs()) {
|
||||
if (builder.getRegistered().containsKey(name)) {
|
||||
outIndexMap.put(name + ".REG", i++);
|
||||
outputs.add(name + ".REG");
|
||||
outIndexMap.put(name + ".AR", i++);
|
||||
outputs.add(name + ".AR");
|
||||
clkInList.add(i);
|
||||
outIndexMap.put(name + ".C", i++);
|
||||
outputs.add(name + ".C");
|
||||
} else {
|
||||
outIndexMap.put(name, i++);
|
||||
outputs.add(name);
|
||||
}
|
||||
}
|
||||
|
||||
termMap = new TreeMap<>();
|
||||
if (!builder.getRegistered().isEmpty()) { // connect clock and ar
|
||||
StateSet clk = new StateSet(outputs.size());
|
||||
for (int c : clkInList)
|
||||
clk.set(c, 1);
|
||||
termMap.put(clkIn, clk);
|
||||
|
||||
// AR
|
||||
termMap.put(new ProdInput(inputs.size()), new StateSet(outputs.size()));
|
||||
}
|
||||
|
||||
|
||||
for (Map.Entry<String, Expression> e : builder.getCombinatorial().entrySet())
|
||||
addExpression(e.getKey(), e.getValue());
|
||||
|
||||
for (Map.Entry<String, Expression> e : builder.getRegistered().entrySet())
|
||||
addExpression(e.getKey() + ".REG", e.getValue());
|
||||
}
|
||||
|
||||
private void addExpression(String name, Expression expression) throws FuseMapFillerException {
|
||||
if (expression instanceof Operation.Or) {
|
||||
Operation.Or or = (Operation.Or) expression;
|
||||
for (Expression e : or.getExpressions())
|
||||
addProdFor(name, e);
|
||||
} else
|
||||
addProdFor(name, expression);
|
||||
}
|
||||
|
||||
private void addProdFor(String name, Expression e) throws FuseMapFillerException {
|
||||
ProdInput pt = new ProdInput(getInputCount());
|
||||
if (e instanceof Operation.And) {
|
||||
Operation.And and = (Operation.And) e;
|
||||
for (Expression z : and.getExpressions())
|
||||
pt.add(z);
|
||||
} else
|
||||
pt.add(e);
|
||||
|
||||
StateSet o = termMap.computeIfAbsent(pt, k -> new StateSet(getOutputCount()));
|
||||
o.set(getOutNum(name));
|
||||
}
|
||||
|
||||
private String strList(ArrayList<String> pins) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (String p : pins) {
|
||||
if (sb.length() > 0)
|
||||
sb.append(" ");
|
||||
sb.append(p);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private void line(String s) throws IOException {
|
||||
writer.write(s);
|
||||
writer.write("\r\n");
|
||||
}
|
||||
|
||||
private int getInputCount() {
|
||||
return varIndexMap.size();
|
||||
}
|
||||
|
||||
private int getVarNum(String identifier) throws FuseMapFillerException {
|
||||
final Integer i = varIndexMap.get(identifier);
|
||||
if (i == null)
|
||||
throw new FuseMapFillerException("ident " + identifier + " not found!");
|
||||
return i;
|
||||
}
|
||||
|
||||
private int getOutputCount() {
|
||||
return outIndexMap.size();
|
||||
}
|
||||
|
||||
private int getOutNum(String identifier) {
|
||||
return outIndexMap.get(identifier);
|
||||
}
|
||||
|
||||
private String getPhase() {
|
||||
StringBuilder sb = new StringBuilder(getOutputCount());
|
||||
for (int i = 0; i < getOutputCount(); i++)
|
||||
sb.append("1");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private String getPins() throws PinMapException {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int numPins = builder.getInputs().size() + builder.getOutputs().size();
|
||||
if (!builder.getRegistered().isEmpty())
|
||||
numPins++;
|
||||
|
||||
sb.append(numPins);
|
||||
|
||||
|
||||
for (String i : builder.getInputs()) {
|
||||
int p = pinMap.getInputFor(i);
|
||||
sb.append(" ").append(i).append("+:").append(p);
|
||||
}
|
||||
|
||||
if (!builder.getRegistered().isEmpty())
|
||||
sb.append(" CLK+:").append(clockPin);
|
||||
|
||||
for (String o : builder.getOutputs()) {
|
||||
int p = pinMap.getInputFor(o);
|
||||
sb.append(" ").append(o).append("+:").append(p);
|
||||
}
|
||||
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static class StateSet implements Comparable<StateSet> {
|
||||
private final int[] state;
|
||||
|
||||
private StateSet(int outputCount) {
|
||||
state = new int[outputCount];
|
||||
}
|
||||
|
||||
void setAllToUnused() {
|
||||
Arrays.fill(state, 2);
|
||||
}
|
||||
|
||||
private void set(int i) {
|
||||
set(i, 1);
|
||||
}
|
||||
|
||||
void set(int i, int value) {
|
||||
state[i] = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(StateSet stateSet) {
|
||||
for (int i = 0; i < state.length; i++) {
|
||||
int c = Integer.compare(state[i], stateSet.state[i]);
|
||||
if (c != 0)
|
||||
return c;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
StateSet stateSet = (StateSet) o;
|
||||
|
||||
return Arrays.equals(state, stateSet.state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Arrays.hashCode(state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder(state.length);
|
||||
for (int i : state)
|
||||
switch (i) {
|
||||
case 0:
|
||||
sb.append("0");
|
||||
break;
|
||||
case 1:
|
||||
sb.append("1");
|
||||
break;
|
||||
default:
|
||||
sb.append("-");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
private final class ProdInput extends StateSet {
|
||||
private ProdInput(int inputCount) {
|
||||
super(inputCount);
|
||||
setAllToUnused();
|
||||
}
|
||||
|
||||
public void add(Expression z) throws FuseMapFillerException {
|
||||
if (z instanceof Not)
|
||||
add(((Not) z).getExpression(), true);
|
||||
else
|
||||
add(z, false);
|
||||
}
|
||||
|
||||
private void add(Expression var, boolean invers) throws FuseMapFillerException {
|
||||
if (var instanceof Variable) {
|
||||
set(getVarNum(((Variable) var).getIdentifier()), invers ? 0 : 1);
|
||||
} else
|
||||
throw new FuseMapFillerException("invalid Expression");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
/**
|
||||
* Generator for the OpenABLE Truth Table (tt) format.
|
||||
* Used to create the input files for the ATF15xx Fitters provided by ATMEL.
|
||||
* These fitters then are used to create the needed JEDEC files.
|
||||
* <p>
|
||||
* Created by hneemann on 03.03.17.
|
||||
*/
|
||||
package de.neemann.digital.builder.tt2;
|
@ -0,0 +1,102 @@
|
||||
package de.neemann.digital.builder.tt2;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
||||
import static de.neemann.digital.analyse.expression.Not.not;
|
||||
import static de.neemann.digital.analyse.expression.Operation.and;
|
||||
import static de.neemann.digital.analyse.expression.Operation.or;
|
||||
import static de.neemann.digital.analyse.expression.Variable.v;
|
||||
|
||||
/**
|
||||
* Created by hneemann on 03.03.17.
|
||||
*/
|
||||
public class TT2ExporterTest extends TestCase {
|
||||
|
||||
public void testCombinatorial() throws Exception {
|
||||
TT2Exporter tt2 = new TT2Exporter();
|
||||
tt2.getPinMapping().setAvailBidirectional(4,5,6,8,20,21);
|
||||
tt2.getBuilder().addCombinatorial("Y", and(v("A"), v("B")));
|
||||
tt2.getBuilder().addCombinatorial("X", or(v("A1"), v("B1")));
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
tt2.writeTo(baos);
|
||||
|
||||
assertEquals("#$ TOOL CUPL\r\n" +
|
||||
"# Berkeley PLA format generated using Digital\r\n" +
|
||||
"#$ TITLE unknown\r\n" +
|
||||
"#$ MODULE unknown\r\n" +
|
||||
"#$ JEDECFILE unknown\r\n" +
|
||||
"#$ DEVICE f1502plcc44\r\n" +
|
||||
"#$ PINS 6 A+:4 A1+:5 B+:6 B1+:8 Y+:20 X+:21\r\n" +
|
||||
".i 4\r\n" +
|
||||
".o 2\r\n" +
|
||||
".type f\r\n" +
|
||||
".ilb A A1 B B1\r\n" +
|
||||
".ob Y X\r\n" +
|
||||
".phase 11\r\n" +
|
||||
".p 3\r\n" +
|
||||
"1-1- 10\r\n" +
|
||||
"-1-- 01\r\n" +
|
||||
"---1 01\r\n" +
|
||||
".e\r\n",baos.toString());
|
||||
}
|
||||
|
||||
public void testSequential() throws Exception {
|
||||
TT2Exporter tt2 = new TT2Exporter();
|
||||
tt2.getPinMapping().setAvailBidirectional(4,5,6,8,20,21);
|
||||
tt2.getBuilder().addSequential("Yn", and(v("A"), not(v("Yn"))));
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
tt2.writeTo(baos);
|
||||
|
||||
assertEquals("#$ TOOL CUPL\r\n" +
|
||||
"# Berkeley PLA format generated using Digital\r\n" +
|
||||
"#$ TITLE unknown\r\n" +
|
||||
"#$ MODULE unknown\r\n" +
|
||||
"#$ JEDECFILE unknown\r\n" +
|
||||
"#$ DEVICE f1502plcc44\r\n" +
|
||||
"#$ PINS 3 A+:4 CLK+:43 Yn+:5\r\n" +
|
||||
".i 3\r\n" +
|
||||
".o 3\r\n" +
|
||||
".type f\r\n" +
|
||||
".ilb A CLK Yn.Q\r\n" +
|
||||
".ob Yn.REG Yn.AR Yn.C\r\n" +
|
||||
".phase 111\r\n" +
|
||||
".p 3\r\n" +
|
||||
"1-0 100\r\n" +
|
||||
"-1- 001\r\n" +
|
||||
"--- 000\r\n" +
|
||||
".e\r\n",baos.toString());
|
||||
}
|
||||
|
||||
public void testSequential2() throws Exception {
|
||||
TT2Exporter tt2 = new TT2Exporter();
|
||||
tt2.getPinMapping().setAvailBidirectional(4,5,6,8,20,21);
|
||||
tt2.getBuilder().addSequential("Yn", and(v("A"), not(v("Yn"))));
|
||||
tt2.getBuilder().addSequential("Xn", or(v("B"), not(v("Xn"))));
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
tt2.writeTo(baos);
|
||||
|
||||
assertEquals("#$ TOOL CUPL\r\n" +
|
||||
"# Berkeley PLA format generated using Digital\r\n" +
|
||||
"#$ TITLE unknown\r\n" +
|
||||
"#$ MODULE unknown\r\n" +
|
||||
"#$ JEDECFILE unknown\r\n" +
|
||||
"#$ DEVICE f1502plcc44\r\n" +
|
||||
"#$ PINS 5 A+:4 B+:5 CLK+:43 Yn+:6 Xn+:8\r\n" +
|
||||
".i 5\r\n" +
|
||||
".o 6\r\n" +
|
||||
".type f\r\n" +
|
||||
".ilb A B CLK Xn.Q Yn.Q\r\n" +
|
||||
".ob Yn.REG Yn.AR Yn.C Xn.REG Xn.AR Xn.C\r\n" +
|
||||
".phase 111111\r\n" +
|
||||
".p 5\r\n" +
|
||||
"1---0 100000\r\n" +
|
||||
"-1--- 000100\r\n" +
|
||||
"--1-- 001001\r\n" +
|
||||
"---0- 000100\r\n" +
|
||||
"----- 000000\r\n" +
|
||||
".e\r\n",baos.toString());
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user