package datapath.graph;
import datapath.graph.modlib.Module;
import datapath.graph.modlib.Wire;
import datapath.graph.modlib.WireIO;
import datapath.graph.operations.ParentInput;
import datapath.graph.operations.ParentOutput;
import datapath.graph.type.FixedPoint;
import java.io.IOException;
import java.io.Writer;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map.Entry;
import java.util.TreeSet;
/**
* Class to create a (very simple) testbench for one datapath.
* @author jh
*/
public class TestbenchCreator {
private Graph graph;
private Writer writer;
public static boolean fixpoint = true;
private TestbenchCreator(Graph graph, Writer writer) {
this.graph = graph;
this.writer = writer;
}
public static void writeTestbench(Graph graph, Writer writer) throws IOException {
TestbenchCreator creator = new TestbenchCreator(graph, writer);
creator.create();
writer.close();
}
private void create() {
HashMap<Wire, String> ios = new HashMap();
HashSet<Wire> in = new HashSet<Wire>();
HashSet<Wire> regs = new HashSet<Wire>();
HashSet<Wire> wires = new HashSet<Wire>();
writeLine("`timescale 1ns / 1ns");
writeLine("module testbench();");
regs.add(new Wire("RESULT_ACCEPT"));
regs.add(new Wire("CANCEL"));
regs.add(new Wire("START"));
regs.add(new Wire("START_CTRL"));
regs.add(new Wire("CLK"));
regs.add(new Wire("RESET"));
regs.add(new Wire("INIT"));
wires.add(new Wire("END"));
regs.add(new Wire("CE"));
TreeSet<ParentInput> input = new TreeSet<ParentInput>(new SortByNumber());
input.addAll(graph.getInput());
TreeSet<ParentOutput> output = new TreeSet<ParentOutput>(
new SortByNumber());
output.addAll(graph.getOutput());
Module m = new Module("graph" + graph.getId(), "g", graph.getId());
for (Wire reg : regs) {
writeLine("reg " + reg.withSize() + ";");
m.addIO(new WireIO(reg, reg.toString()));
}
for (Wire wire : wires) {
writeLine("wire " + wire.withSize() + ";");
m.addIO(new WireIO(wire, wire.toString()));
}
for (ParentInput inp : input) {
Wire io = new Wire(inp.getName());
in.add(io);
io.setSize(inp.getOutputBitsize());
ios.put(io, ModlibWriter.getDataWire(inp.getSource()));
writeLine("reg " + io.withSize() + ";");
}
for (ParentOutput out : output) {
Wire io = new Wire(out.getName());
io.setSize(out.getOutputBitsize());
ios.put(io, ModlibWriter.getDataWire(out));
writeLine("wire " + io.withSize() + ";");
}
for (Entry<Wire, String> entry : ios.entrySet()) {
m.addIO(new WireIO(entry.getKey(), entry.getValue()));
}
writeLine(Modlib.module(m));
writeLine("integer file;");
writeLine("integer error;");
writeLine("initial begin");
for (Wire reg : regs) {
writeLine(reg.toString() + " = 0;");
}
writeLine("file = $fopen(\"inputdata\", \"r\");");
writeLine("$ferror(file, error);");
writeLine("if (error != 0) begin");
writeLine("// input data begins here");
for (Wire inp : in) {
writeLine(String.format("%s = %d'd0;", inp.toString() ,inp.getSize()));
}
writeLine("// end of input data");
writeLine("end");
writeLine("else begin");
writeLine("`include \"inputdata\"");
writeLine("end");
writeLine("#20 RESET=1;");
writeLine("#10 RESET=0;");
writeLine("#4");
writeLine("INIT = 1;");
writeLine("CE = 1;");
writeLine("#5 INIT = 0;");
if(fixpoint) {
addFixpointOutput();
}
writeLine("end");
writeLine("// clock with cycle length 10");
writeLine("always begin");
writeLine("#5 CLK=~CLK;");
writeLine("end");
writeLine("endmodule");
}
private void writeLine(String line) {
try {
writer.write(line);
writer.write("\n");
} catch (IOException ex) {
System.err.println("Cannot write testbench");
}
}
private void addFixpointOutput() {
TreeSet<ParentOutput> output = new TreeSet<ParentOutput>(
new SortByNumber());
output.addAll(graph.getOutput());
TreeSet<ParentInput> input = new TreeSet<ParentInput>(new SortByNumber());
input.addAll(graph.getInput());
writeLine("@(posedge END) begin");
for(ParentInput in : input) {
assert in.getType() instanceof FixedPoint;
int frac = ((FixedPoint)in.getType()).getFractionlength();
int bits = in.getType().getBitsize();
writeLine(fixpoint(in.getName(), frac, bits,in.isSigned()));
}
for(ParentOutput out : output) {
assert out.getType() instanceof FixedPoint;
int frac = ((FixedPoint)out.getType()).getFractionlength();
int bits = out.getType().getBitsize();
writeLine(fixpoint(out.getName(), frac, bits,out.isSigned()));
}
writeLine("end");
}
private static String fixpoint(String name, int frac, int bits, boolean signed) {
bits = bits -1;
if(signed)
return String.format("$display(\"%s: %%s %%f\", (%s[%d:%d] == 1 )? \"-\": \" \", $itor((%s[%d:%d] == 1)? -%s:%s) / $itor(2)**%d);",name,name,bits,bits,name,bits,bits,name,name,frac);
else
return String.format("$display(\"%s: %%f\", %s / $itor(2)**%d);",name,name,frac);
}
}