/*******************************************************************************
* See the NOTICE file distributed with this work for additional information
* regarding copyright ownership.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package hr.fer.zemris.vhdllab.applets.editor.newtb.model;
import hr.fer.zemris.vhdllab.applets.editor.newtb.enums.ChangeStateEdge;
import hr.fer.zemris.vhdllab.applets.editor.newtb.enums.TimeScale;
import hr.fer.zemris.vhdllab.applets.editor.newtb.enums.VectorDirection;
import hr.fer.zemris.vhdllab.applets.editor.newtb.exceptions.UniformTestbenchParserException;
import hr.fer.zemris.vhdllab.applets.editor.newtb.model.signals.EditableSignal;
import hr.fer.zemris.vhdllab.applets.editor.newtb.model.signals.ScalarSignal;
import hr.fer.zemris.vhdllab.applets.editor.newtb.model.signals.SignalChange;
import hr.fer.zemris.vhdllab.applets.editor.newtb.model.signals.VectorSignal;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;
/**
*
* @author Davor Jurisic
*
*/
public class TestbenchParser {
private TestbenchParser() {
}
public static Testbench parseXml(String xml) throws UniformTestbenchParserException {
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder db;
db = factory.newDocumentBuilder();
InputSource in = new InputSource();
in.setCharacterStream(new StringReader(xml.replace("\n", "")));
Document xmldoc = db.parse(in);
return parse(xmldoc);
} catch (Exception e) {
throw new UniformTestbenchParserException(e.getMessage());
}
}
private static Testbench parse(Document xmldoc) throws UniformTestbenchParserException {
Element root = xmldoc.getDocumentElement();
Node testBenchInfoNode = root.getElementsByTagName("TestBenchInfo").item(0);
Node initTimingInfoNode = root.getElementsByTagName("InitTimingInfo").item(0);
Node signalsNode = root.getElementsByTagName("Signals").item(0);
if(testBenchInfoNode == null)
throw new UniformTestbenchParserException(generateErrorMsg("TestBenchInfo", "element"));
if(initTimingInfoNode == null)
throw new UniformTestbenchParserException(generateErrorMsg("InitTimingInfo", "element"));
if(signalsNode == null)
throw new UniformTestbenchParserException(generateErrorMsg("Signals", "element"));
String sourceName = null;
String simulationLength = null;
for(int i = 0; i < testBenchInfoNode.getChildNodes().getLength(); i++) {
Node n = testBenchInfoNode.getChildNodes().item(i);
if(n.getNodeName().equals("SourceName")) sourceName = n.getTextContent();
if(n.getNodeName().equals("SimulationLength")) simulationLength = n.getTextContent();
}
if(sourceName == null)
throw new UniformTestbenchParserException(generateErrorMsg("SourceName", "element"));
if(simulationLength == null)
throw new UniformTestbenchParserException(generateErrorMsg("SimulationLength", "element"));
String testbenchType = null;
String testBenchLength = null;
String timeScale = null;
Node singleClockInfoNode = null;
Node combinatorialInfoNode = null;
for(int i = 0; i < initTimingInfoNode.getChildNodes().getLength(); i++) {
Node n = initTimingInfoNode.getChildNodes().item(i);
if(n.getNodeName().equals("TestBenchType")) testbenchType = n.getAttributes().getNamedItem("type").getNodeValue();
if(n.getNodeName().equals("TestBenchLength")) testBenchLength = n.getTextContent();
if(n.getNodeName().equals("TimeScale")) timeScale = n.getTextContent();
if(n.getNodeName().equals("SingleClockInfo")) singleClockInfoNode = n;
if(n.getNodeName().equals("CombinatorialInfo")) combinatorialInfoNode = n;
}
if(testbenchType == null)
throw new UniformTestbenchParserException(generateErrorMsg("type", "atribut"));
if(testBenchLength == null)
throw new UniformTestbenchParserException(generateErrorMsg("TestBenchLength", "element"));
if(timeScale == null)
throw new UniformTestbenchParserException(generateErrorMsg("TimeScale", "element"));
String clockSignalName = null;
String changeStateEdge = null;
String clockTimeHigh = null;
String clockTimeLow = null;
String inputSetupTime = null;
String checkOutputsTime = null;
String assignInputsTime = null;
if(testbenchType.equals("single") && singleClockInfoNode != null) {
clockSignalName = singleClockInfoNode.getAttributes().getNamedItem("clockSignalName").getNodeValue();
changeStateEdge = singleClockInfoNode.getAttributes().getNamedItem("changeStateEdge").getNodeValue();
clockTimeHigh = singleClockInfoNode.getAttributes().getNamedItem("clockTimeHigh").getNodeValue();
clockTimeLow = singleClockInfoNode.getAttributes().getNamedItem("clockTimeLow").getNodeValue();
inputSetupTime = singleClockInfoNode.getAttributes().getNamedItem("inputSetupTime").getNodeValue();
if(clockSignalName == null)
throw new UniformTestbenchParserException(generateErrorMsg("clockSignalName", "atribut"));
if(changeStateEdge == null)
throw new UniformTestbenchParserException(generateErrorMsg("changeStateEdge", "atribut"));
if(clockTimeHigh == null)
throw new UniformTestbenchParserException(generateErrorMsg("clockTimeHigh", "atribut"));
if(clockTimeLow == null)
throw new UniformTestbenchParserException(generateErrorMsg("clockTimeLow", "atribut"));
if(inputSetupTime == null)
throw new UniformTestbenchParserException(generateErrorMsg("inputSetupTime", "atribut"));
}
else if (testbenchType.equals("combinatorial") && combinatorialInfoNode != null) {
checkOutputsTime = combinatorialInfoNode.getAttributes().getNamedItem("checkOutputsTime").getNodeValue();
assignInputsTime = combinatorialInfoNode.getAttributes().getNamedItem("assignInputsTime").getNodeValue();
if(checkOutputsTime == null)
throw new UniformTestbenchParserException(generateErrorMsg("checkOutputsTime", "atribut"));
if(assignInputsTime == null)
throw new UniformTestbenchParserException(generateErrorMsg("assignInputsTime", "atribut"));
}
else {
throw new UniformTestbenchParserException(generateErrorMsg("SingleClockInfo ili CombinatorialInfo", "element"));
}
Testbench tb = null;
TimeScale ts = TimeScale.valueOf(timeScale);
try {
if(testbenchType.equals("single")) {
SingleClockTestbench.Properties p = new SingleClockTestbench.Properties();
p.changeStateEdge = ChangeStateEdge.valueOf(changeStateEdge);
p.clockSignalName = clockSignalName;
p.clockTimeHigh = Long.parseLong(clockTimeHigh) * TimeScale.getMultiplier(ts);
p.clockTimeLow = Long.parseLong(clockTimeLow) * TimeScale.getMultiplier(ts);
p.inputSetupTime = Long.parseLong(inputSetupTime) * TimeScale.getMultiplier(ts);
tb = new SingleClockTestbench(
sourceName,
Long.parseLong(testBenchLength) * TimeScale.getMultiplier(ts),
TimeScale.valueOf(timeScale),
p
);
tb.setSimulationLength(Long.parseLong(simulationLength) * TimeScale.getMultiplier(ts));
addSignals(signalsNode, tb);
}
else if(testbenchType.equals("combinatorial")) {
CombinatorialTestbench.Properties p = new CombinatorialTestbench.Properties();
p.assignInputsTime = Long.parseLong(assignInputsTime) * TimeScale.getMultiplier(ts);
p.checkOutputsTime = Long.parseLong(checkOutputsTime) * TimeScale.getMultiplier(ts);
tb = new CombinatorialTestbench(
sourceName,
Long.parseLong(testBenchLength) * TimeScale.getMultiplier(ts),
TimeScale.valueOf(timeScale),
p
);
tb.setSimulationLength(Long.parseLong(simulationLength) * TimeScale.getMultiplier(ts));
addSignals(signalsNode, tb);
}
else {
throw new UniformTestbenchParserException("");
}
} catch(Exception e) {
throw new UniformTestbenchParserException("Greska kod instanciranja novog testbencha.");
}
return tb;
}
private static void addSignals(Node signalsNode, Testbench tb) throws Exception {
String name = null;
String type = null;
String dimension = null;
String direction = null;
String data = null;
EditableSignal s = null;
for(int i = 0; i < signalsNode.getChildNodes().getLength(); i++) {
name = null;
type = null;
dimension = null;
direction = null;
data = null;
Node n = signalsNode.getChildNodes().item(i);
name = n.getAttributes().getNamedItem("name").getNodeValue();
type = n.getAttributes().getNamedItem("type").getNodeValue();
if(n.getAttributes().getNamedItem("dimension") != null) {
dimension = n.getAttributes().getNamedItem("dimension").getNodeValue();
}
if(n.getAttributes().getNamedItem("direction") != null) {
direction = n.getAttributes().getNamedItem("direction").getNodeValue();
}
data = n.getTextContent();
if(type.equals("scalar")) {
s = new ScalarSignal(name);
s.setSignalChangeValue(getChanges(data, (short)1, tb.getTimeScale()));
}
else if(type.equals("vector")) {
s = new VectorSignal(name, Short.parseShort(dimension), VectorDirection.valueOf(direction));
s.setSignalChangeValue(getChanges(data, Short.parseShort(dimension), tb.getTimeScale()));
}
tb.addSignal(s);
}
}
private static List<SignalChange> getChanges(String data, short dimension, TimeScale timeScale) throws Exception
{
List<SignalChange> ls = new ArrayList<SignalChange>();
if(data.length() == 0)
return ls;
data = data.replace(")(", "#");
data = data.replace("(", "");
data = data.replace(")", "");
String[] datas = data.split("#");
if(datas == null)
return ls;
for (String s : datas) {
String[] tmp = s.split(",");
ls.add(new SignalChange(dimension, tmp[1], Long.parseLong(tmp[0]) * TimeScale.getMultiplier(timeScale)));
}
return ls;
}
private static String generateErrorMsg(String elementName, String elementType) {
return "Nedostaje " + elementName + " " + elementType;
}
}