2015-01-21 21:58:35 +01:00
|
|
|
/*******************************************************************************
|
2021-01-09 14:26:49 +01:00
|
|
|
* Copyright (c) 2015-2021 MINRES Technologies GmbH and others.
|
2015-01-21 21:58:35 +01:00
|
|
|
* All rights reserved. This program and the accompanying materials
|
|
|
|
* are made available under the terms of the Eclipse Public License v1.0
|
|
|
|
* which accompanies this distribution, and is available at
|
|
|
|
* http://www.eclipse.org/legal/epl-v10.html
|
|
|
|
*
|
|
|
|
* Contributors:
|
|
|
|
* MINRES Technologies GmbH - initial API and implementation
|
|
|
|
*******************************************************************************/
|
2015-01-06 17:14:16 +01:00
|
|
|
package com.minres.scviewer.database.vcd;
|
|
|
|
|
2021-01-09 20:10:58 +01:00
|
|
|
import java.beans.PropertyChangeListener;
|
|
|
|
import java.beans.PropertyChangeSupport;
|
2015-01-06 17:14:16 +01:00
|
|
|
import java.io.File;
|
|
|
|
import java.io.FileInputStream;
|
2019-03-14 20:51:02 +01:00
|
|
|
import java.io.IOException;
|
|
|
|
import java.io.InputStream;
|
2020-11-29 10:25:48 +01:00
|
|
|
import java.util.ArrayDeque;
|
2015-11-15 22:15:37 +01:00
|
|
|
import java.util.Collection;
|
|
|
|
import java.util.Collections;
|
2015-01-06 17:14:16 +01:00
|
|
|
import java.util.List;
|
|
|
|
import java.util.Vector;
|
2019-03-14 20:51:02 +01:00
|
|
|
import java.util.zip.GZIPInputStream;
|
2015-01-06 17:14:16 +01:00
|
|
|
|
2021-01-09 20:10:58 +01:00
|
|
|
import com.google.common.collect.Iterables;
|
2015-01-09 09:16:40 +01:00
|
|
|
import com.minres.scviewer.database.BitVector;
|
2020-11-28 10:22:22 +01:00
|
|
|
import com.minres.scviewer.database.DoubleVal;
|
2021-02-26 12:57:54 +01:00
|
|
|
import com.minres.scviewer.database.IEventList;
|
2015-01-06 17:14:16 +01:00
|
|
|
import com.minres.scviewer.database.IWaveform;
|
2015-01-20 18:50:15 +01:00
|
|
|
import com.minres.scviewer.database.IWaveformDb;
|
2015-01-10 00:23:46 +01:00
|
|
|
import com.minres.scviewer.database.IWaveformDbLoader;
|
2015-01-06 17:14:16 +01:00
|
|
|
import com.minres.scviewer.database.InputFormatException;
|
2015-11-15 22:15:37 +01:00
|
|
|
import com.minres.scviewer.database.RelationType;
|
2015-01-06 17:14:16 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* The Class VCDDb.
|
|
|
|
*/
|
2015-01-10 00:23:46 +01:00
|
|
|
public class VCDDbLoader implements IWaveformDbLoader, IVCDDatabaseBuilder {
|
2015-01-06 17:14:16 +01:00
|
|
|
|
2020-11-29 10:25:48 +01:00
|
|
|
|
2015-11-22 12:47:07 +01:00
|
|
|
/** The Constant TIME_RES. */
|
2020-11-29 10:25:48 +01:00
|
|
|
private static final Long TIME_RES = 1000L; // ps
|
2015-01-06 17:14:16 +01:00
|
|
|
|
|
|
|
/** The module stack. */
|
2020-11-29 10:25:48 +01:00
|
|
|
private ArrayDeque<String> moduleStack;
|
|
|
|
|
2015-01-06 17:14:16 +01:00
|
|
|
/** The signals. */
|
2018-11-05 18:21:54 +01:00
|
|
|
private List<IWaveform> signals;
|
2020-11-29 10:25:48 +01:00
|
|
|
|
2015-11-22 12:47:07 +01:00
|
|
|
/** The max time. */
|
2015-01-06 17:14:16 +01:00
|
|
|
private long maxTime;
|
|
|
|
|
2021-01-09 20:10:58 +01:00
|
|
|
/** The pcs. */
|
|
|
|
protected PropertyChangeSupport pcs = new PropertyChangeSupport(this);
|
|
|
|
|
2019-03-14 20:51:02 +01:00
|
|
|
private static boolean isGzipped(File f) {
|
2020-11-29 10:25:48 +01:00
|
|
|
try (InputStream is = new FileInputStream(f)) {
|
2019-03-14 20:51:02 +01:00
|
|
|
byte [] signature = new byte[2];
|
|
|
|
int nread = is.read( signature ); //read the gzip signature
|
|
|
|
return nread == 2 && signature[ 0 ] == (byte) 0x1f && signature[ 1 ] == (byte) 0x8b;
|
2020-11-29 10:25:48 +01:00
|
|
|
}
|
|
|
|
catch (IOException e) {
|
2019-03-14 20:51:02 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-06 17:14:16 +01:00
|
|
|
|
2021-01-09 20:10:58 +01:00
|
|
|
/**
|
|
|
|
* Can load.
|
|
|
|
*
|
|
|
|
* @param inputFile the input file
|
|
|
|
* @return true, if successful
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public boolean canLoad(File inputFile) {
|
|
|
|
if(!inputFile.isDirectory() || inputFile.exists()) {
|
|
|
|
String name = inputFile.getName();
|
|
|
|
if(!(name.endsWith(".vcd") ||
|
|
|
|
name.endsWith(".vcdz") ||
|
|
|
|
name.endsWith(".vcdgz") ||
|
|
|
|
name.endsWith(".vcd.gz")) )
|
|
|
|
return false;
|
|
|
|
boolean gzipped = isGzipped(inputFile);
|
|
|
|
try(InputStream stream = gzipped ? new GZIPInputStream(new FileInputStream(inputFile)) : new FileInputStream(inputFile)){
|
|
|
|
byte[] buffer = new byte[8];
|
|
|
|
if (stream.read(buffer, 0, buffer.length) == buffer.length) {
|
|
|
|
return buffer[0]=='$';
|
|
|
|
}
|
|
|
|
} catch (Exception e) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-01-06 17:14:16 +01:00
|
|
|
/* (non-Javadoc)
|
|
|
|
* @see com.minres.scviewer.database.ITrDb#load(java.io.File)
|
|
|
|
*/
|
2015-01-20 18:50:15 +01:00
|
|
|
@SuppressWarnings("unchecked")
|
2015-01-06 17:14:16 +01:00
|
|
|
@Override
|
2021-01-09 20:10:58 +01:00
|
|
|
public void load(IWaveformDb db, File file) throws InputFormatException {
|
2021-01-08 15:04:30 +01:00
|
|
|
dispose();
|
2018-10-15 09:10:10 +02:00
|
|
|
this.maxTime=0;
|
2020-11-29 10:25:48 +01:00
|
|
|
boolean res = false;
|
|
|
|
try {
|
|
|
|
signals = new Vector<>();
|
|
|
|
moduleStack= new ArrayDeque<>();
|
|
|
|
FileInputStream fis = new FileInputStream(file);
|
|
|
|
res = new VCDFileParser(false).load(isGzipped(file)?new GZIPInputStream(fis):fis, this);
|
|
|
|
moduleStack=null;
|
|
|
|
} catch(IOException e) {
|
|
|
|
moduleStack=null;
|
2021-01-09 23:24:00 +01:00
|
|
|
throw new InputFormatException(e.toString());
|
2020-11-29 10:25:48 +01:00
|
|
|
}
|
2021-02-27 14:33:15 +01:00
|
|
|
if(!res)
|
|
|
|
throw new InputFormatException("Could not parse VCD file");
|
2021-01-09 20:10:58 +01:00
|
|
|
// calculate max time of this database
|
2018-11-05 18:21:54 +01:00
|
|
|
for(IWaveform waveform:signals) {
|
2021-02-27 13:26:07 +01:00
|
|
|
IEventList events =waveform.getEvents();
|
2021-01-09 20:10:58 +01:00
|
|
|
if(!events.isEmpty())
|
2018-10-11 11:20:36 +02:00
|
|
|
maxTime= Math.max(maxTime, events.lastKey());
|
|
|
|
}
|
2021-01-09 20:10:58 +01:00
|
|
|
// extend signals to have a last value set at max time
|
2018-11-05 18:21:54 +01:00
|
|
|
for(IWaveform s:signals){
|
|
|
|
if(s instanceof VCDSignal<?>) {
|
2021-02-27 13:26:07 +01:00
|
|
|
IEventList events = ((VCDSignal<?>)s).getEvents();
|
2018-11-05 18:21:54 +01:00
|
|
|
if(events.size()>0 && events.lastKey()<maxTime){
|
2021-02-27 13:26:07 +01:00
|
|
|
Object val = events.lastEntry().events[0];
|
2018-11-05 18:21:54 +01:00
|
|
|
if(val instanceof BitVector) {
|
|
|
|
((VCDSignal<BitVector>)s).addSignalChange(maxTime, (BitVector) val);
|
2020-11-28 10:22:22 +01:00
|
|
|
} else if(val instanceof DoubleVal)
|
|
|
|
((VCDSignal<DoubleVal>)s).addSignalChange(maxTime, (DoubleVal) val);
|
2018-11-05 18:21:54 +01:00
|
|
|
}
|
2015-01-06 17:14:16 +01:00
|
|
|
}
|
|
|
|
}
|
2021-01-09 20:10:58 +01:00
|
|
|
pcs.firePropertyChange(IWaveformDbLoader.LOADING_FINISHED, null, null);
|
2015-01-06 17:14:16 +01:00
|
|
|
}
|
|
|
|
|
2021-01-08 15:04:30 +01:00
|
|
|
public void dispose() {
|
|
|
|
moduleStack=null;
|
|
|
|
signals=null;
|
|
|
|
}
|
|
|
|
|
2015-01-06 17:14:16 +01:00
|
|
|
/* (non-Javadoc)
|
|
|
|
* @see com.minres.scviewer.database.ITrDb#getMaxTime()
|
|
|
|
*/
|
|
|
|
@Override
|
2021-02-27 14:59:00 +01:00
|
|
|
public long getMaxTime() {
|
2015-01-21 21:58:35 +01:00
|
|
|
return maxTime;
|
2015-01-06 17:14:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* (non-Javadoc)
|
|
|
|
* @see com.minres.scviewer.database.ITrDb#getAllWaves()
|
|
|
|
*/
|
|
|
|
@Override
|
2020-04-02 14:13:39 +02:00
|
|
|
public Collection<IWaveform> getAllWaves() {
|
2015-01-06 17:14:16 +01:00
|
|
|
return signals;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* (non-Javadoc)
|
|
|
|
* @see com.minres.scviewer.database.vcd.ITraceBuilder#enterModule(java.lang.String)
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public void enterModule(String tokenString) {
|
2018-07-16 13:17:58 +02:00
|
|
|
if(moduleStack.isEmpty()) {
|
|
|
|
if("SystemC".compareTo(tokenString)!=0) moduleStack.push(tokenString);
|
|
|
|
} else
|
2015-01-06 17:14:16 +01:00
|
|
|
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)
|
|
|
|
*/
|
2015-01-20 18:50:15 +01:00
|
|
|
@SuppressWarnings("unchecked")
|
2015-01-06 17:14:16 +01:00
|
|
|
@Override
|
2018-07-16 13:17:58 +02:00
|
|
|
public Integer newNet(String name, int i, int width) {
|
2020-11-29 10:25:48 +01:00
|
|
|
String netName = moduleStack.isEmpty()? name: moduleStack.peek()+"."+name;
|
2015-01-06 17:14:16 +01:00
|
|
|
int id = signals.size();
|
2018-11-05 18:21:54 +01:00
|
|
|
if(width==0) {
|
2021-01-02 17:02:05 +01:00
|
|
|
signals.add( i<0 ? new VCDSignal<DoubleVal>(id, netName, width) :
|
2020-11-28 10:22:22 +01:00
|
|
|
new VCDSignal<DoubleVal>((VCDSignal<DoubleVal>)signals.get(i), id, netName));
|
2018-11-05 18:21:54 +01:00
|
|
|
} else if(width>0){
|
2021-01-02 17:02:05 +01:00
|
|
|
signals.add( i<0 ? new VCDSignal<BitVector>(id, netName, width) :
|
2018-11-05 18:21:54 +01:00
|
|
|
new VCDSignal<BitVector>((VCDSignal<BitVector>)signals.get(i), id, netName));
|
|
|
|
}
|
2021-01-09 20:10:58 +01:00
|
|
|
pcs.firePropertyChange(IWaveformDbLoader.SIGNAL_ADDED, null, Iterables.getLast(signals));
|
2015-01-06 17:14:16 +01:00
|
|
|
return id;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* (non-Javadoc)
|
|
|
|
* @see com.minres.scviewer.database.vcd.ITraceBuilder#getNetWidth(int)
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public int getNetWidth(int intValue) {
|
2018-11-05 18:21:54 +01:00
|
|
|
VCDSignal<?> signal = (VCDSignal<?>) signals.get(intValue);
|
2021-01-14 23:13:11 +01:00
|
|
|
return signal.getRowCount();
|
2015-01-06 17:14:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* (non-Javadoc)
|
|
|
|
* @see com.minres.scviewer.database.vcd.ITraceBuilder#appendTransition(int, long, com.minres.scviewer.database.vcd.BitVector)
|
|
|
|
*/
|
|
|
|
@SuppressWarnings("unchecked")
|
|
|
|
@Override
|
2018-11-05 18:21:54 +01:00
|
|
|
public void appendTransition(int signalId, long currentTime, BitVector value) {
|
|
|
|
VCDSignal<BitVector> signal = (VCDSignal<BitVector>) signals.get(signalId);
|
2018-10-11 11:20:36 +02:00
|
|
|
Long time = currentTime* TIME_RES;
|
2020-11-28 10:22:22 +01:00
|
|
|
signal.addSignalChange(time, value);
|
2018-10-11 11:20:36 +02:00
|
|
|
}
|
2020-11-29 10:25:48 +01:00
|
|
|
|
2018-10-11 11:20:36 +02:00
|
|
|
/* (non-Javadoc)
|
|
|
|
* @see com.minres.scviewer.database.vcd.ITraceBuilder#appendTransition(int, long, com.minres.scviewer.database.vcd.BitVector)
|
|
|
|
*/
|
|
|
|
@SuppressWarnings("unchecked")
|
|
|
|
@Override
|
2018-11-05 18:21:54 +01:00
|
|
|
public void appendTransition(int signalId, long currentTime, double value) {
|
2020-11-28 10:22:22 +01:00
|
|
|
VCDSignal<DoubleVal> signal = (VCDSignal<DoubleVal>) signals.get(signalId);
|
2018-10-11 11:20:36 +02:00
|
|
|
Long time = currentTime* TIME_RES;
|
2020-11-28 10:22:22 +01:00
|
|
|
signal.addSignalChange(time, new DoubleVal(value));
|
2015-01-06 17:14:16 +01:00
|
|
|
}
|
2020-11-29 10:25:48 +01:00
|
|
|
|
2015-11-22 12:47:07 +01:00
|
|
|
/* (non-Javadoc)
|
|
|
|
* @see com.minres.scviewer.database.IWaveformDbLoader#getAllRelationTypes()
|
|
|
|
*/
|
2015-11-15 22:15:37 +01:00
|
|
|
@Override
|
|
|
|
public Collection<RelationType> getAllRelationTypes(){
|
|
|
|
return Collections.emptyList();
|
|
|
|
}
|
2015-01-06 17:14:16 +01:00
|
|
|
|
2021-01-09 20:10:58 +01:00
|
|
|
/**
|
|
|
|
* Adds the property change listener.
|
|
|
|
*
|
|
|
|
* @param l the l
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public void addPropertyChangeListener(PropertyChangeListener l) {
|
|
|
|
pcs.addPropertyChangeListener(l);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Removes the property change listener.
|
|
|
|
*
|
|
|
|
* @param l the l
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public void removePropertyChangeListener(PropertyChangeListener l) {
|
|
|
|
pcs.removePropertyChangeListener(l);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-01-06 17:14:16 +01:00
|
|
|
}
|