Added support for VCD Database
This commit is contained in:
@ -1,3 +1,5 @@
|
||||
package com.minres.scviewer.database;
|
||||
|
||||
public enum AssociationType {BEGIN, RECORD, END}
|
||||
public enum AssociationType {
|
||||
BEGIN, RECORD, END
|
||||
}
|
@ -1,16 +1,18 @@
|
||||
package com.minres.scviewer.database;
|
||||
public enum DataType {
|
||||
BOOLEAN, // bool
|
||||
ENUMERATION, // enum
|
||||
INTEGER, // char, short, int, long, long long, sc_int, sc_bigint
|
||||
UNSIGNED, // unsigned { char, short, int, long, long long }, sc_uint, sc_biguint
|
||||
FLOATING_POINT_NUMBER, // float, double
|
||||
BIT_VECTOR, // sc_bit, sc_bv
|
||||
LOGIC_VECTOR, // sc_logic, sc_lv
|
||||
FIXED_POINT_INTEGER, // sc_fixed
|
||||
UNSIGNED_FIXED_POINT_INTEGER, // sc_ufixed
|
||||
RECORD, // struct/class
|
||||
POINTER, // T*
|
||||
ARRAY, // T[N]
|
||||
STRING // string, std::string
|
||||
};
|
||||
|
||||
public enum DataType {
|
||||
BOOLEAN, // bool
|
||||
ENUMERATION, // enum
|
||||
INTEGER, // char, short, int, long, long long, sc_int, sc_bigint
|
||||
UNSIGNED, // unsigned { char, short, int, long, long long }, sc_uint,
|
||||
// sc_biguint
|
||||
FLOATING_POINT_NUMBER, // float, double
|
||||
BIT_VECTOR, // sc_bit, sc_bv
|
||||
LOGIC_VECTOR, // sc_logic, sc_lv
|
||||
FIXED_POINT_INTEGER, // sc_fixed
|
||||
UNSIGNED_FIXED_POINT_INTEGER, // sc_ufixed
|
||||
RECORD, // struct/class
|
||||
POINTER, // T*
|
||||
ARRAY, // T[N]
|
||||
STRING // string, std::string
|
||||
};
|
||||
|
@ -16,8 +16,11 @@ public class EventTime implements Comparable<EventTime>{
|
||||
|
||||
public static final double MS = 1000000000.0;
|
||||
|
||||
public static final EventTime ZERO = new EventTime(0L, "fs");
|
||||
|
||||
private long value; // unit is femto seconds
|
||||
|
||||
|
||||
public EventTime(Long value, String unit){
|
||||
setValue(value, unit);
|
||||
}
|
||||
|
@ -0,0 +1,46 @@
|
||||
package com.minres.scviewer.database;
|
||||
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class HierNode implements IHierNode {
|
||||
|
||||
protected String name;
|
||||
|
||||
protected ArrayList<IHierNode> childs;
|
||||
|
||||
public HierNode(String name) {
|
||||
this.name=name;
|
||||
childs = new ArrayList<IHierNode>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPropertyChangeListener(PropertyChangeListener l) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removePropertyChangeListener(PropertyChangeListener l) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFullName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setName(String name) {
|
||||
this.name=name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<IHierNode> getChildNodes() {
|
||||
return childs;
|
||||
}
|
||||
|
||||
}
|
@ -13,7 +13,8 @@ package com.minres.scviewer.database;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.List;
|
||||
|
||||
public interface ITrHierNode {
|
||||
public interface IHierNode {
|
||||
|
||||
/**
|
||||
* Attach a non-null PropertyChangeListener to this object.
|
||||
*
|
||||
@ -23,6 +24,7 @@ public interface ITrHierNode {
|
||||
* if the parameter is null
|
||||
*/
|
||||
public void addPropertyChangeListener(PropertyChangeListener l);
|
||||
|
||||
/**
|
||||
* Remove a PropertyChangeListener from this component.
|
||||
*
|
||||
@ -37,6 +39,6 @@ public interface ITrHierNode {
|
||||
|
||||
public void setName(String name);
|
||||
|
||||
public List<ITrHierNode> getChildNodes();
|
||||
public List<IHierNode> getChildNodes();
|
||||
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package com.minres.scviewer.database;
|
||||
|
||||
import java.util.NavigableSet;
|
||||
|
||||
public interface ISignal<T extends ISignalChange> extends IWaveform{
|
||||
|
||||
public NavigableSet<ISignalChange> getSignalChanges();
|
||||
|
||||
public T getSignalChangeByTime(EventTime time);
|
||||
|
||||
public NavigableSet<ISignalChange> getSignalChangesByTimes(EventTime start, EventTime end);
|
||||
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package com.minres.scviewer.database;
|
||||
|
||||
public interface ISignalChange extends Comparable<ISignalChange>{
|
||||
|
||||
public EventTime getTime();
|
||||
|
||||
public ISignalChange duplicate() throws CloneNotSupportedException;
|
||||
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package com.minres.scviewer.database;
|
||||
|
||||
public interface ISignalChangeMulti extends ISignalChange {
|
||||
|
||||
public String getValue();
|
||||
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package com.minres.scviewer.database;
|
||||
|
||||
public interface ISignalChangeSingle extends ISignalChange{
|
||||
|
||||
public char getValue();
|
||||
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
package com.minres.scviewer.database;
|
||||
|
||||
public interface ITrRelation {
|
||||
|
||||
RelationType getRelationType();
|
||||
|
||||
ITransaction getSource();
|
||||
|
||||
ITransaction getTarget();
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
package com.minres.scviewer.database;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public interface ITransactionDbFactory {
|
||||
|
||||
ITrDb createDatabase(File file);
|
||||
|
||||
}
|
@ -12,23 +12,22 @@ package com.minres.scviewer.database;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public interface ITransaction {
|
||||
public interface ITx {
|
||||
|
||||
public Long getId();
|
||||
|
||||
public ITrStream getStream();
|
||||
public ITxStream getStream();
|
||||
|
||||
public ITrGenerator getGenerator();
|
||||
public ITxGenerator getGenerator();
|
||||
|
||||
public EventTime getBeginTime();
|
||||
|
||||
public EventTime getEndTime();
|
||||
|
||||
public List<ITrAttribute> getAttributes();
|
||||
public List<ITxAttribute> getAttributes();
|
||||
|
||||
public Collection<ITrRelation> getIncomingRelations();
|
||||
public Collection<ITxRelation> getIncomingRelations();
|
||||
|
||||
public Collection<ITrRelation> getOutgoingRelations();
|
||||
public Collection<ITxRelation> getOutgoingRelations();
|
||||
}
|
@ -10,6 +10,6 @@
|
||||
*******************************************************************************/
|
||||
package com.minres.scviewer.database;
|
||||
|
||||
public interface ITrAttribute extends ITrAttrType {
|
||||
public interface ITxAttribute extends ITxAttributeType {
|
||||
public Object getValue();
|
||||
}
|
@ -10,7 +10,7 @@
|
||||
*******************************************************************************/
|
||||
package com.minres.scviewer.database;
|
||||
|
||||
public interface ITrAttrType {
|
||||
public interface ITxAttributeType {
|
||||
public String getName();
|
||||
public DataType getDataType();
|
||||
public AssociationType getType();
|
@ -12,9 +12,9 @@ package com.minres.scviewer.database;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ITrGenerator {
|
||||
public interface ITxGenerator {
|
||||
public Long getId();
|
||||
public ITrStream getStream();
|
||||
public ITxStream getStream();
|
||||
public String getName();
|
||||
public List<ITransaction> getTransactions();
|
||||
public List<ITx> getTransactions();
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
package com.minres.scviewer.database;
|
||||
|
||||
public interface ITxRelation {
|
||||
|
||||
RelationType getRelationType();
|
||||
|
||||
ITx getSource();
|
||||
|
||||
ITx getTarget();
|
||||
}
|
@ -12,18 +12,12 @@ package com.minres.scviewer.database;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ITrStream extends ITrHierNode {
|
||||
public interface ITxStream extends IWaveform {
|
||||
|
||||
public Long getId();
|
||||
public List<ITxGenerator> getGenerators();
|
||||
|
||||
public String getKind();
|
||||
public List<ITx> getTransactions();
|
||||
|
||||
public ITrDb getDb();
|
||||
|
||||
public List<ITrGenerator> getGenerators();
|
||||
|
||||
public List<ITransaction> getTransactions();
|
||||
|
||||
public ITransaction getTransactionById(long id);
|
||||
public ITx getTransactionById(long id);
|
||||
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package com.minres.scviewer.database;
|
||||
|
||||
public interface IWaveform extends IHierNode {
|
||||
|
||||
public Long getId();
|
||||
|
||||
public String getKind();
|
||||
|
||||
public IWaveformDb getDb();
|
||||
|
||||
|
||||
}
|
@ -11,19 +11,18 @@
|
||||
package com.minres.scviewer.database;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public interface ITrDb extends ITrHierNode {
|
||||
public interface IWaveformDb extends IHierNode {
|
||||
|
||||
public EventTime getMaxTime();
|
||||
|
||||
public ITrStream getStreamByName(String name);
|
||||
public IWaveform getStreamByName(String name);
|
||||
|
||||
public List<ITrStream> getAllStreams();
|
||||
public List<IWaveform> getAllWaves();
|
||||
|
||||
public void load(File inp) throws InputFormatException;
|
||||
public void load(File inp) throws Exception;
|
||||
|
||||
public void clear();
|
||||
|
@ -0,0 +1,9 @@
|
||||
package com.minres.scviewer.database;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public interface IWaveformDbFactory {
|
||||
|
||||
IWaveformDb createDatabase(File file);
|
||||
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package com.minres.scviewer.database;
|
||||
|
||||
public class SignalChange implements ISignalChange {
|
||||
|
||||
EventTime time;
|
||||
|
||||
|
||||
public SignalChange() {
|
||||
time=EventTime.ZERO;
|
||||
}
|
||||
|
||||
public SignalChange(EventTime time) {
|
||||
super();
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(ISignalChange o) {
|
||||
return time.compareTo(o.getTime());
|
||||
}
|
||||
|
||||
@Override
|
||||
public EventTime getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public void setTime(EventTime time) {
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ISignalChange duplicate() throws CloneNotSupportedException {
|
||||
return (ISignalChange) this.clone();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package com.minres.scviewer.database.vcd;
|
||||
|
||||
public class BitVector {
|
||||
|
||||
public static final char VALUE_X = 'X';
|
||||
public static final char VALUE_Z = 'Z';
|
||||
public static final char VALUE_1 = '1';
|
||||
public static final char VALUE_0 = '0';
|
||||
|
||||
private final int width;
|
||||
|
||||
private char[] value;
|
||||
|
||||
public BitVector(int netWidth) {
|
||||
this.width=netWidth;
|
||||
value = new char[netWidth];
|
||||
for(int i=0; i<netWidth; i++) value[i]='0';
|
||||
}
|
||||
|
||||
public void setValue(int i, char value) {
|
||||
this.value[i]=value;
|
||||
}
|
||||
|
||||
public char[] getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(char[] value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
public String toString(){
|
||||
return new String(value);
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
package com.minres.scviewer.database.vcd;
|
||||
|
||||
// TODO: Auto-generated Javadoc
|
||||
/**
|
||||
* The Interface ITraceBuilder.
|
||||
*/
|
||||
public interface IVCDDatabaseBuilder {
|
||||
|
||||
/**
|
||||
* Enter module.
|
||||
*
|
||||
* @param tokenString the token string
|
||||
*/
|
||||
public void enterModule(String tokenString);
|
||||
|
||||
/**
|
||||
* Exit module.
|
||||
*/
|
||||
public void exitModule();
|
||||
|
||||
/**
|
||||
* New net.
|
||||
*
|
||||
* @param netName the net name
|
||||
* @param i the index of the net, -1 if a new one, otherwise the id if the referenced
|
||||
* @param width the width
|
||||
* @return the integer
|
||||
*/
|
||||
public Integer newNet(String netName, int i, int width) ;
|
||||
|
||||
/**
|
||||
* Gets the net width.
|
||||
*
|
||||
* @param intValue the int value
|
||||
* @return the net width
|
||||
*/
|
||||
public int getNetWidth(int intValue);
|
||||
|
||||
/**
|
||||
* Append transition.
|
||||
*
|
||||
* @param intValue the int value
|
||||
* @param fCurrentTime the f current time
|
||||
* @param decodedValues the decoded values
|
||||
*/
|
||||
public void appendTransition(int intValue, long fCurrentTime, BitVector decodedValues);
|
||||
|
||||
}
|
@ -0,0 +1,211 @@
|
||||
package com.minres.scviewer.database.vcd;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Stack;
|
||||
import java.util.Vector;
|
||||
|
||||
import com.minres.scviewer.database.EventTime;
|
||||
import com.minres.scviewer.database.HierNode;
|
||||
import com.minres.scviewer.database.ISignal;
|
||||
import com.minres.scviewer.database.ISignalChange;
|
||||
import com.minres.scviewer.database.ISignalChangeMulti;
|
||||
import com.minres.scviewer.database.ISignalChangeSingle;
|
||||
import com.minres.scviewer.database.IWaveformDb;
|
||||
import com.minres.scviewer.database.IHierNode;
|
||||
import com.minres.scviewer.database.ITxStream;
|
||||
import com.minres.scviewer.database.IWaveform;
|
||||
import com.minres.scviewer.database.InputFormatException;
|
||||
import com.minres.scviewer.database.SignalChange;
|
||||
|
||||
// TODO: Auto-generated Javadoc
|
||||
/**
|
||||
* The Class VCDDb.
|
||||
*/
|
||||
public class VCDDb extends HierNode implements IWaveformDb, IVCDDatabaseBuilder {
|
||||
|
||||
|
||||
private static final String TIME_RES = "ps";
|
||||
|
||||
/** The module stack. */
|
||||
private Stack<String> moduleStack;
|
||||
|
||||
/** The signals. */
|
||||
private List<IWaveform> signals;
|
||||
|
||||
private HashMap<String, IWaveform> waveformLookup;
|
||||
|
||||
private long maxTime;
|
||||
|
||||
/**
|
||||
* Instantiates a new VCD db.
|
||||
*
|
||||
* @param netName the net name
|
||||
*/
|
||||
public VCDDb() {
|
||||
super("VCDDb");
|
||||
signals = new Vector<IWaveform>();
|
||||
waveformLookup = new HashMap<String, IWaveform>();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.minres.scviewer.database.ITrDb#getStreamByName(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public ITxStream getStreamByName(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.minres.scviewer.database.ITrDb#load(java.io.File)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void load(File inp) throws Exception {
|
||||
moduleStack= new Stack<String>();
|
||||
boolean res = new VCDFileParser(false).load(new FileInputStream(inp), this);
|
||||
moduleStack=null;
|
||||
if(!res) throw new InputFormatException();
|
||||
EventTime lastTime=new EventTime(maxTime, TIME_RES);
|
||||
for(IWaveform signal:signals){
|
||||
ISignalChange change = ((ISignal<ISignalChange>)signal).getSignalChanges().last();
|
||||
if(lastTime.compareTo(change.getTime())>0){
|
||||
ISignalChange lastChange = change.duplicate();
|
||||
((SignalChange)lastChange).setTime(lastTime);
|
||||
((ISignal<ISignalChange>)signal).getSignalChanges().add(lastChange);
|
||||
}
|
||||
}
|
||||
buildHierarchyNodes();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.minres.scviewer.database.ITrDb#clear()
|
||||
*/
|
||||
@Override
|
||||
public void clear() {
|
||||
signals.clear();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.minres.scviewer.database.ITrDb#getMaxTime()
|
||||
*/
|
||||
@Override
|
||||
public EventTime getMaxTime() {
|
||||
return new EventTime(maxTime, TIME_RES);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.minres.scviewer.database.ITrDb#getAllWaves()
|
||||
*/
|
||||
@Override
|
||||
public List<IWaveform> getAllWaves() {
|
||||
return signals;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.minres.scviewer.database.vcd.ITraceBuilder#enterModule(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public void enterModule(String tokenString) {
|
||||
if(moduleStack.isEmpty())
|
||||
moduleStack.push(tokenString);
|
||||
else
|
||||
moduleStack.push(moduleStack.peek()+"."+tokenString);
|
||||
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.minres.scviewer.database.vcd.ITraceBuilder#exitModule()
|
||||
*/
|
||||
@Override
|
||||
public void exitModule() {
|
||||
if(!moduleStack.isEmpty()) moduleStack.pop();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.minres.scviewer.database.vcd.ITraceBuilder#newNet(java.lang.String, int, int)
|
||||
*/
|
||||
@Override
|
||||
public Integer newNet(String netName, int i, int width) {
|
||||
int id = signals.size();
|
||||
VCDSignal<? extends ISignalChange> signal;
|
||||
if(width==1){
|
||||
signal = i<0 ? new VCDSignal<ISignalChangeSingle>(id, netName) :
|
||||
new VCDSignal<ISignalChangeSingle>(signals.get(i), id, netName);
|
||||
} else {
|
||||
signal = i<0 ? new VCDSignal<ISignalChangeMulti>(id, netName, width) :
|
||||
new VCDSignal<ISignalChangeMulti>(signals.get(i), id, netName);
|
||||
};
|
||||
signals.add(signal);
|
||||
return id;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.minres.scviewer.database.vcd.ITraceBuilder#getNetWidth(int)
|
||||
*/
|
||||
@Override
|
||||
public int getNetWidth(int intValue) {
|
||||
VCDSignal<? extends ISignalChange> signal = (VCDSignal<? extends ISignalChange>) signals.get(intValue);
|
||||
return signal.getWidth();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.minres.scviewer.database.vcd.ITraceBuilder#appendTransition(int, long, com.minres.scviewer.database.vcd.BitVector)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void appendTransition(int intValue, long fCurrentTime, BitVector decodedValues) {
|
||||
VCDSignal<? extends ISignalChange> signal = (VCDSignal<? extends ISignalChange>) signals.get(intValue);
|
||||
EventTime time = new EventTime(fCurrentTime, TIME_RES);
|
||||
if(signal.getWidth()==1){
|
||||
VCDSignalChangeSingle change = new VCDSignalChangeSingle(time, decodedValues.getValue()[0]);
|
||||
((VCDSignal<ISignalChangeSingle>)signal).addSignalChange(change);
|
||||
} else {
|
||||
VCDSignalChangeMulti change = new VCDSignalChangeMulti(time, new String(decodedValues.getValue()));
|
||||
((VCDSignal<VCDSignalChangeMulti>)signal).addSignalChange(change);
|
||||
}
|
||||
maxTime= Math.max(maxTime, fCurrentTime);
|
||||
}
|
||||
|
||||
private void buildHierarchyNodes() throws InputFormatException{
|
||||
for(IWaveform stream:getAllWaves()){
|
||||
waveformLookup.put(stream.getFullName(), stream);
|
||||
String[] hier = stream.getFullName().split("\\.");
|
||||
IHierNode node = this;
|
||||
for(String name:hier){
|
||||
IHierNode n1 = null;
|
||||
for (IHierNode n : node.getChildNodes()) {
|
||||
if (n.getName().equals(name)) {
|
||||
n1=n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(name == hier[hier.length-1]){ //leaf
|
||||
if(n1!=null) {
|
||||
if(n1 instanceof HierNode){
|
||||
node.getChildNodes().remove(n1);
|
||||
stream.getChildNodes().addAll(n1.getChildNodes());
|
||||
} else {
|
||||
throw new InputFormatException();
|
||||
}
|
||||
}
|
||||
stream.setName(name);
|
||||
node.getChildNodes().add(stream);
|
||||
node=stream;
|
||||
} else { // intermediate
|
||||
if(n1 != null) {
|
||||
node=n1;
|
||||
} else {
|
||||
HierNode newNode = new HierNode(name);
|
||||
node.getChildNodes().add(newNode);
|
||||
node=newNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
package com.minres.scviewer.database.vcd;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
|
||||
import com.minres.scviewer.database.IWaveformDb;
|
||||
import com.minres.scviewer.database.IWaveformDbFactory;
|
||||
|
||||
public class VCDDbFactory implements IWaveformDbFactory {
|
||||
|
||||
private byte[] x = "$date".getBytes();
|
||||
|
||||
public VCDDbFactory(){
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public IWaveformDb createDatabase(File file) {
|
||||
try {
|
||||
FileInputStream fis = new FileInputStream(file);
|
||||
byte[] buffer = new byte[x.length];
|
||||
int read = fis.read(buffer, 0, x.length);
|
||||
fis.close();
|
||||
if (read == x.length)
|
||||
for (int i = 0; i < x.length; i++)
|
||||
if (buffer[i] != x[i])
|
||||
return null;
|
||||
VCDDb db = new VCDDb();
|
||||
db.load(file);
|
||||
return db;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,212 @@
|
||||
package com.minres.scviewer.database.vcd;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
class VCDFileParser {
|
||||
private StreamTokenizer tokenizer;
|
||||
private IVCDDatabaseBuilder traceBuilder;
|
||||
private HashMap<String, Integer> nameToNetMap = new HashMap<String, Integer>();
|
||||
private long picoSecondsPerIncrement;
|
||||
private boolean stripNetWidth;
|
||||
long currentTime;
|
||||
|
||||
public VCDFileParser(boolean stripNetWidth) {
|
||||
this.stripNetWidth=stripNetWidth;
|
||||
}
|
||||
|
||||
public boolean load(InputStream is, IVCDDatabaseBuilder builder) {
|
||||
tokenizer = new StreamTokenizer(new BufferedReader(new InputStreamReader(is)));
|
||||
tokenizer.resetSyntax();
|
||||
tokenizer.wordChars(33, 126);
|
||||
tokenizer.whitespaceChars('\r', '\r');
|
||||
tokenizer.whitespaceChars('\n', '\n');
|
||||
tokenizer.whitespaceChars(' ', ' ');
|
||||
tokenizer.whitespaceChars('\t', '\t');
|
||||
try {
|
||||
traceBuilder = builder;
|
||||
currentTime=0;
|
||||
while (parseDefinition());
|
||||
while (parseTransition());
|
||||
return true;
|
||||
} catch (Exception exc) {
|
||||
exc.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void parseScope() throws Exception {
|
||||
nextToken(); // Scope type (ignore)
|
||||
nextToken();
|
||||
traceBuilder.enterModule(tokenizer.sval);
|
||||
match("$end");
|
||||
}
|
||||
|
||||
private void parseUpscope() throws Exception {
|
||||
match("$end");
|
||||
traceBuilder.exitModule();
|
||||
}
|
||||
|
||||
private void parseVar() throws Exception {
|
||||
nextToken(); // type
|
||||
nextToken(); // size
|
||||
int width = Integer.parseInt(tokenizer.sval);
|
||||
|
||||
nextToken();
|
||||
String id = tokenizer.sval;
|
||||
nextToken();
|
||||
String netName = tokenizer.sval;
|
||||
while (nextToken() && !tokenizer.sval.equals("$end")) {
|
||||
netName+=tokenizer.sval;
|
||||
}
|
||||
|
||||
Integer net = nameToNetMap.get(id);
|
||||
if (net == null) {
|
||||
// We've never seen this net before
|
||||
if(stripNetWidth){
|
||||
int openBracket = netName.indexOf('[');
|
||||
if (openBracket != -1) netName = netName.substring(0, openBracket);
|
||||
}
|
||||
nameToNetMap.put(id, traceBuilder.newNet(netName, -1, width));
|
||||
} else {
|
||||
// Shares data with existing net. Add as clone.
|
||||
traceBuilder.newNet(netName, net, width);
|
||||
}
|
||||
}
|
||||
|
||||
private void parseTimescale() throws Exception {
|
||||
nextToken();
|
||||
String s = tokenizer.sval;
|
||||
nextToken();
|
||||
while(!tokenizer.sval.equals("$end")){
|
||||
s+=" "+tokenizer.sval;
|
||||
nextToken();
|
||||
}
|
||||
switch (s.charAt(s.length() - 2)){
|
||||
case 'p': // Nano-seconds
|
||||
picoSecondsPerIncrement = 1;
|
||||
s = s.substring(0, s.length() - 2).trim();
|
||||
break;
|
||||
case 'n': // Nano-seconds
|
||||
picoSecondsPerIncrement = 1000;
|
||||
s = s.substring(0, s.length() - 2).trim();
|
||||
break;
|
||||
case 'u': // Microseconds
|
||||
picoSecondsPerIncrement = 1000000;
|
||||
s = s.substring(0, s.length() - 2).trim();
|
||||
break;
|
||||
case 'm': // Microseconds
|
||||
picoSecondsPerIncrement = 1000000000;
|
||||
s = s.substring(0, s.length() - 2).trim();
|
||||
break;
|
||||
default: // Seconds
|
||||
picoSecondsPerIncrement = 1000000000000L;
|
||||
s = s.substring(0, s.length() - 1);
|
||||
break;
|
||||
}
|
||||
picoSecondsPerIncrement *= Long.parseLong(s);
|
||||
}
|
||||
|
||||
private boolean parseDefinition() throws Exception {
|
||||
nextToken();
|
||||
if (tokenizer.sval.equals("$scope"))
|
||||
parseScope();
|
||||
else if (tokenizer.sval.equals("$var"))
|
||||
parseVar();
|
||||
else if (tokenizer.sval.equals("$upscope"))
|
||||
parseUpscope();
|
||||
else if (tokenizer.sval.equals("$timescale"))
|
||||
parseTimescale();
|
||||
else if (tokenizer.sval.equals("$enddefinitions")) {
|
||||
match("$end");
|
||||
return false;
|
||||
} else {
|
||||
// Ignore this defintion
|
||||
do {
|
||||
if (!nextToken()) return false;
|
||||
} while (!tokenizer.sval.equals("$end"));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean parseTransition() throws Exception {
|
||||
if (!nextToken()) return false;
|
||||
if (tokenizer.sval.charAt(0) == '#') { // If the line begins with a #, this is a timestamp.
|
||||
currentTime = Long.parseLong(tokenizer.sval.substring(1)) * picoSecondsPerIncrement;
|
||||
} else {
|
||||
if(tokenizer.sval.equals("$comment")){
|
||||
do {
|
||||
if (!nextToken()) return false;
|
||||
} while (!tokenizer.sval.equals("$end"));
|
||||
return true;
|
||||
}
|
||||
if (tokenizer.sval.equals("$dumpvars") || tokenizer.sval.equals("$end")) return true;
|
||||
String value, id;
|
||||
if (tokenizer.sval.charAt(0) == 'b') {
|
||||
// Multiple value net. Value appears first, followed by space,
|
||||
// then identifier
|
||||
value = tokenizer.sval.substring(1);
|
||||
nextToken();
|
||||
id = tokenizer.sval;
|
||||
} else {
|
||||
// Single value net. identifier first, then value, no space.
|
||||
value = tokenizer.sval.substring(0, 1);
|
||||
id = tokenizer.sval.substring(1);
|
||||
}
|
||||
|
||||
Integer net = nameToNetMap.get(id);
|
||||
if (net == null) {
|
||||
System.out.println("unknown net " + id + " value " + value);
|
||||
return true;
|
||||
}
|
||||
|
||||
int netWidth = traceBuilder.getNetWidth(net);
|
||||
BitVector decodedValues = new BitVector(netWidth);
|
||||
if (value.equals("z") && netWidth > 1) {
|
||||
for (int i = 0; i < netWidth; i++)
|
||||
decodedValues.setValue(i, BitVector.VALUE_Z);
|
||||
} else if (value.equals("x") && netWidth > 1) {
|
||||
for (int i = 0; i < netWidth; i++)
|
||||
decodedValues.setValue(i, BitVector.VALUE_X);
|
||||
} else {
|
||||
int stringIndex = 0;
|
||||
for (int convertedIndex = netWidth - value.length(); convertedIndex < netWidth; convertedIndex++) {
|
||||
switch (value.charAt(stringIndex++)) {
|
||||
case 'z':
|
||||
decodedValues.setValue(convertedIndex, BitVector.VALUE_Z);
|
||||
break;
|
||||
|
||||
case '1':
|
||||
decodedValues.setValue(convertedIndex, BitVector.VALUE_1);
|
||||
break;
|
||||
|
||||
case '0':
|
||||
decodedValues.setValue(convertedIndex, BitVector.VALUE_0);
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
decodedValues.setValue(convertedIndex, BitVector.VALUE_X);
|
||||
break;
|
||||
|
||||
default:
|
||||
decodedValues.setValue(convertedIndex, BitVector.VALUE_X);
|
||||
}
|
||||
}
|
||||
}
|
||||
traceBuilder.appendTransition(net, currentTime, decodedValues);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void match(String value) throws Exception {
|
||||
nextToken();
|
||||
if (!tokenizer.sval.equals(value))
|
||||
throw new Exception("Line "+tokenizer.lineno()+": parse error, expected "+value+" got "+tokenizer.sval);
|
||||
}
|
||||
|
||||
private boolean nextToken() throws IOException {
|
||||
return tokenizer.nextToken() != StreamTokenizer.TT_EOF;
|
||||
}
|
||||
|
||||
};
|
@ -0,0 +1,108 @@
|
||||
package com.minres.scviewer.database.vcd;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.NavigableSet;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import com.minres.scviewer.database.EventTime;
|
||||
import com.minres.scviewer.database.HierNode;
|
||||
import com.minres.scviewer.database.ISignal;
|
||||
import com.minres.scviewer.database.ISignalChange;
|
||||
import com.minres.scviewer.database.IWaveformDb;
|
||||
import com.minres.scviewer.database.IWaveform;
|
||||
import com.minres.scviewer.database.SignalChange;
|
||||
|
||||
public class VCDSignal<T extends ISignalChange> extends HierNode implements ISignal<T> {
|
||||
|
||||
private long id;
|
||||
|
||||
private String fullName;
|
||||
|
||||
private final String kind = "signal";
|
||||
|
||||
private final int width;
|
||||
|
||||
private VCDDb db;
|
||||
|
||||
TreeSet<ISignalChange> values;
|
||||
|
||||
public VCDSignal(String name) {
|
||||
this(0, name, 1);
|
||||
}
|
||||
|
||||
public VCDSignal(int id, String name) {
|
||||
this(id,name,1);
|
||||
}
|
||||
|
||||
public VCDSignal(int id, String name, int width) {
|
||||
super(name);
|
||||
fullName=name;
|
||||
this.id=id;
|
||||
this.width=width;
|
||||
this.values=new TreeSet<ISignalChange>();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public VCDSignal(IWaveform other, int id, String name) {
|
||||
super(name);
|
||||
fullName=name;
|
||||
this.id=id;
|
||||
assert(other instanceof VCDSignal<?>);
|
||||
this.width=((VCDSignal<? extends ISignalChange>)other).width;
|
||||
this.values=((VCDSignal<T>)other).values;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFullName() {
|
||||
return fullName;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id=id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKind() {
|
||||
return kind;
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IWaveformDb getDb() {
|
||||
return db;
|
||||
}
|
||||
|
||||
public void addSignalChange(T change){
|
||||
values.add(change);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NavigableSet<ISignalChange> getSignalChanges() {
|
||||
return values;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T getSignalChangeByTime(EventTime time) {
|
||||
return (T) values.floor(new SignalChange(time));
|
||||
}
|
||||
|
||||
@Override
|
||||
public NavigableSet<ISignalChange> getSignalChangesByTimes(EventTime start, EventTime end) {
|
||||
ISignalChange low = values.floor(new SignalChange(start));
|
||||
ISignalChange high = values.ceiling(new SignalChange(end));
|
||||
if(high!=null)
|
||||
return values.subSet(low, true, high, true);
|
||||
else
|
||||
return values.subSet(low, true, values.last(), true);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package com.minres.scviewer.database.vcd;
|
||||
|
||||
import com.minres.scviewer.database.EventTime;
|
||||
import com.minres.scviewer.database.ISignalChangeMulti;
|
||||
import com.minres.scviewer.database.SignalChange;
|
||||
|
||||
public class VCDSignalChangeMulti extends SignalChange implements ISignalChangeMulti, Cloneable {
|
||||
|
||||
private String value;
|
||||
|
||||
public VCDSignalChangeMulti(EventTime time) {
|
||||
super(time);
|
||||
}
|
||||
|
||||
public VCDSignalChangeMulti(EventTime time, String value) {
|
||||
super(time);
|
||||
this.value=value;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package com.minres.scviewer.database.vcd;
|
||||
|
||||
import com.minres.scviewer.database.EventTime;
|
||||
import com.minres.scviewer.database.ISignalChangeSingle;
|
||||
import com.minres.scviewer.database.SignalChange;
|
||||
|
||||
public class VCDSignalChangeSingle extends SignalChange implements ISignalChangeSingle, Cloneable {
|
||||
|
||||
private char value;
|
||||
|
||||
public VCDSignalChangeSingle(EventTime time, char value) {
|
||||
super(time);
|
||||
this.value=value;
|
||||
}
|
||||
|
||||
public char getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(char value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user