Refactored database data model to improve speed and reduce memory

consumption
This commit is contained in:
Eyck Jentzsch 2018-11-05 18:21:54 +01:00
parent e687eef42c
commit 93fd192782
29 changed files with 360 additions and 471 deletions

View File

@ -24,7 +24,7 @@ public class LevelDBLoader implements IWaveformDbLoader {
return value.getBytes(UTF_8);
}
private StringDBWrapper levelDb;
private TxDBWrapper levelDb;
private IWaveformDb db;
private Long maxTime=null;
private List<RelationType> usedRelationsList = new ArrayList<>();
@ -33,7 +33,10 @@ public class LevelDBLoader implements IWaveformDbLoader {
public boolean load(IWaveformDb db, File inp) throws Exception {
try {
this.db=db;
levelDb = new StringDBWrapper(new Options(), inp);
levelDb = new TxDBWrapper(new Options(), inp);
JSONObject configVal = new JSONObject(levelDb.get("__config"));
if(!configVal.isEmpty())
levelDb.setTimeResolution(configVal.getLong("resolution"));
} catch(Exception e) {
return false;
}
@ -55,15 +58,15 @@ public class LevelDBLoader implements IWaveformDbLoader {
maxTime = 0L;
else {
String[] token = val.getKey().split("~");
maxTime = Long.parseLong(token[2], 16);
maxTime = Long.parseLong(token[2], 16)*levelDb.getTimeResolution();
}
}
return maxTime;
}
@Override
public List<IWaveform<? extends IWaveformEvent>> getAllWaves() {
List<IWaveform<? extends IWaveformEvent>> streams=new ArrayList<IWaveform<? extends IWaveformEvent>>();
public List<IWaveform> getAllWaves() {
List<IWaveform> streams=new ArrayList<IWaveform>();
SeekingIterator<String, String> it = levelDb.iterator();
it.seek("s~");
while(it.hasNext()) {

View File

@ -11,17 +11,19 @@ import org.iq80.leveldb.ReadOptions;
import org.iq80.leveldb.Snapshot;
import org.iq80.leveldb.impl.DbImpl;
import org.iq80.leveldb.impl.SeekingIterator;
import org.json.*;
class StringDBWrapper {
class TxDBWrapper {
private final Options options;
private final ReadOptions ro = new ReadOptions();
private final File databaseDir;
private DbImpl db;
private long timeResolution=1L;;
StringDBWrapper(Options options, File databaseDir) throws IOException {
this.options = options.verifyChecksums(true).createIfMissing(false).errorIfExists(false);
TxDBWrapper(Options options, File databaseDir) throws IOException {
this.options = options.verifyChecksums(true).createIfMissing(false).errorIfExists(false).cacheSize(64*1024*1024);
this.databaseDir = databaseDir;
this.db = new DbImpl(options, databaseDir);
ro.snapshot(db.getSnapshot());
}
public String get(String key) {
@ -33,11 +35,8 @@ class StringDBWrapper {
}
public String get(String key, Snapshot snapshot) {
byte[] slice = db.get(LevelDBLoader.toByteArray(key), new ReadOptions().snapshot(snapshot));
if (slice == null) {
return null;
}
return new String(slice, UTF_8);
byte[] slice = db.get(LevelDBLoader.toByteArray(key), ro);
return slice == null? null : new String(slice, UTF_8);
}
public void put(String key, String value) {
@ -57,7 +56,10 @@ class StringDBWrapper {
}
public void close() {
db.close();
try {
ro.snapshot().close();
db.close();
} catch (IOException e) {} // ignore any error
}
public long size(String start, String limit) {
@ -73,7 +75,16 @@ class StringDBWrapper {
}
public void reopen(Options options) throws IOException {
db.close();
this.close();
db = new DbImpl(options.verifyChecksums(true).createIfMissing(false).errorIfExists(false), databaseDir);
ro.snapshot(db.getSnapshot());
}
public long getTimeResolution() {
return timeResolution;
}
public void setTimeResolution(long resolution) {
this.timeResolution = resolution;
}
}

View File

@ -10,9 +10,6 @@
*******************************************************************************/
package com.minres.scviewer.database.leveldb;
import java.beans.IntrospectionException;
import java.lang.reflect.InvocationTargetException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@ -23,7 +20,6 @@ import org.iq80.leveldb.impl.SeekingIterator;
import org.json.JSONObject;
import java.util.NavigableMap;
import java.util.StringTokenizer;
import java.util.TreeMap;
import java.util.Vector;
@ -34,12 +30,11 @@ import com.minres.scviewer.database.ITxGenerator;
import com.minres.scviewer.database.ITxStream;
import com.minres.scviewer.database.IWaveform;
import com.minres.scviewer.database.IWaveformDb;
import com.minres.scviewer.database.IWaveformEvent;
import com.minres.scviewer.database.RelationType;
public class TxStream extends HierNode implements ITxStream<ITxEvent> {
private StringDBWrapper levelDb;
private TxDBWrapper levelDb;
private String fullName;
@ -59,7 +54,7 @@ public class TxStream extends HierNode implements ITxStream<ITxEvent> {
private List<RelationType> usedRelationsList;
public TxStream(StringDBWrapper database, IWaveformDb waveformDb, JSONObject object) {
public TxStream(TxDBWrapper database, IWaveformDb waveformDb, JSONObject object) {
super(object.get("name").toString());
this.levelDb=database;
this.db=waveformDb;
@ -93,10 +88,11 @@ public class TxStream extends HierNode implements ITxStream<ITxEvent> {
if(generators==null){
generators=new TreeMap<Long, TxGenerator>();
SeekingIterator<String, String> it = levelDb.iterator();
it.seek("sg~"+String.format("%016x", id));
String key="sg~"+String.format("%016x", id);
it.seek(key);
while(it.hasNext()) {
Entry<String, String> val = it.next();
if(!val.getKey().startsWith("sg~")) break;
if(!val.getKey().startsWith(key)) break;
JSONObject jVal = new JSONObject(val.getValue());
generators.put(jVal.getLong("id"), new TxGenerator(this, jVal));
}
@ -107,7 +103,7 @@ public class TxStream extends HierNode implements ITxStream<ITxEvent> {
@Override
public int getMaxConcurrency() {
if(maxConcurrency==null){
maxConcurrency=1;
getTransactions();
}
return maxConcurrency;
}
@ -117,8 +113,9 @@ public class TxStream extends HierNode implements ITxStream<ITxEvent> {
if(events==null){
events=new TreeMap<Long, List<ITxEvent>>();
for(Entry<Long, ITx> entry:getTransactions().entrySet()){
putEvent(new TxEvent(TxEvent.Type.BEGIN, entry.getValue()));
putEvent(new TxEvent(TxEvent.Type.END, entry.getValue()));
ITx tx = entry.getValue();
putEvent(new TxEvent(TxEvent.Type.BEGIN, tx));
putEvent(new TxEvent(TxEvent.Type.END, tx));
}
}
return events;
@ -139,16 +136,21 @@ public class TxStream extends HierNode implements ITxStream<ITxEvent> {
if(transactions==null){
if(generators==null) getGenerators();
transactions = new TreeMap<Long, ITx>();
maxConcurrency=0;
SeekingIterator<String, String> it = levelDb.iterator();
it.seek("sgx~"+String.format("%016x", id));
String key = "sgx~"+String.format("%016x", id);
it.seek(key);
while(it.hasNext()) {
Entry<String, String> val = it.next();
if(!val.getKey().startsWith("sgx~")) break;
if(!val.getKey().startsWith(key)) break;
String[] token = val.getKey().split("~");
long gid = Long.parseLong(token[2], 16); // gen id
long id = Long.parseLong(token[3], 16); // tx id
transactions.put(id, new Tx(levelDb, this, generators.get(gid), id));
ITx tx = new Tx(levelDb, this, generators.get(gid), id);
transactions.put(id, tx);
maxConcurrency= Math.max(maxConcurrency, tx.getConcurrencyIndex());
}
maxConcurrency++;
}
return transactions;
}
@ -169,7 +171,7 @@ public class TxStream extends HierNode implements ITxStream<ITxEvent> {
}
@Override
public Boolean equals(IWaveform<? extends IWaveformEvent> other) {
public Boolean equals(IWaveform other) {
return(other instanceof TxStream && this.getId()==other.getId());
}

View File

@ -13,6 +13,7 @@ package com.minres.scviewer.database.sqlite;
import java.beans.IntrospectionException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.lang.reflect.InvocationTargetException;
import java.sql.SQLException;
import java.util.ArrayList;
@ -60,9 +61,9 @@ public class SQLiteDbLoader implements IWaveformDbLoader {
}
@Override
public List<IWaveform<? extends IWaveformEvent>> getAllWaves() {
public List<IWaveform> getAllWaves() {
SQLiteDatabaseSelectHandler<ScvStream> handler = new SQLiteDatabaseSelectHandler<ScvStream>(ScvStream.class, database);
List<IWaveform<? extends IWaveformEvent>> streams=new ArrayList<IWaveform<? extends IWaveformEvent>>();
List<IWaveform> streams=new ArrayList<IWaveform>();
try {
for(ScvStream scvStream:handler.selectObjects()){
TxStream stream = new TxStream(database, db, scvStream);
@ -81,14 +82,17 @@ public class SQLiteDbLoader implements IWaveformDbLoader {
@Override
public boolean load(IWaveformDb db, File file) throws Exception {
this.db=db;
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 false;
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 false;
} catch(FileNotFoundException e) {
return false;
}
database=new SQLiteDatabase(file.getAbsolutePath());
database.setData("TIMERESOLUTION", 1L);
SQLiteDatabaseSelectHandler<ScvSimProps> handler = new SQLiteDatabaseSelectHandler<ScvSimProps>(ScvSimProps.class, database);

View File

@ -29,7 +29,6 @@ import com.minres.scviewer.database.ITxGenerator;
import com.minres.scviewer.database.ITxStream;
import com.minres.scviewer.database.IWaveform;
import com.minres.scviewer.database.IWaveformDb;
import com.minres.scviewer.database.IWaveformEvent;
import com.minres.scviewer.database.RelationType;
import com.minres.scviewer.database.sqlite.db.IDatabase;
import com.minres.scviewer.database.sqlite.db.SQLiteDatabaseSelectHandler;
@ -193,7 +192,7 @@ public class TxStream extends HierNode implements ITxStream<ITxEvent> {
}
@Override
public Boolean equals(IWaveform<? extends IWaveformEvent> other) {
public Boolean equals(IWaveform other) {
return(other instanceof TxStream && this.getId()==other.getId());
}

View File

@ -16,6 +16,7 @@ import static org.junit.Assert.assertTrue;
import java.io.File;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NavigableMap;
@ -33,6 +34,7 @@ import com.minres.scviewer.database.ITxStream;
import com.minres.scviewer.database.IWaveform;
import com.minres.scviewer.database.IWaveformDb;
import com.minres.scviewer.database.IWaveformDbFactory;
import com.minres.scviewer.database.vcd.VCDSignal;
public class DatabaseServicesTest {
@ -54,13 +56,6 @@ public class DatabaseServicesTest {
@Before
public void setUp() throws Exception {
waveformDb=waveformDbFactory.getDatabase();
// Wait for OSGi dependencies
// for (int i = 0; i < 10; i++) {
// if (waveformDb.size() == 3) // Dependencies fulfilled
// return;
// Thread.sleep(1000);
// }
// assertEquals("OSGi dependencies unfulfilled", 3, WaveformDb.getLoaders().size());
}
@After
@ -73,8 +68,17 @@ public class DatabaseServicesTest {
assertTrue(f.exists());
waveformDb.load(f);
assertNotNull(waveformDb);
assertEquals(14, waveformDb.getAllWaves().size());
List<IWaveform> waves= waveformDb.getAllWaves();
assertEquals(14, waves.size());
assertEquals(2, waveformDb.getChildNodes().size());
IWaveform bus_data_wave = waves.get(0);
VCDSignal<?> bus_data_sig = (VCDSignal<?>) bus_data_wave;
Entry<Long, ?> bus_data_entry = bus_data_sig.getEvents().floorEntry(1400000000L);
assertTrue("01111000".equals(bus_data_entry.getValue().toString()));
IWaveform rw_wave = waves.get(2);
VCDSignal<?> rw_sig = (VCDSignal<?>) rw_wave;
Entry<Long, ?> rw_entry = rw_sig.getEvents().floorEntry(2360000000L);
assertTrue("1".equals(rw_entry.getValue().toString()));
}
@Test
@ -104,18 +108,18 @@ public class DatabaseServicesTest {
waveformDb.load(f);
assertNotNull(waveformDb);
assertEquals(1, waveformDb.getChildNodes().size());
List<IWaveform<?>> waves = waveformDb.getAllWaves();
List<IWaveform> waves = waveformDb.getAllWaves();
assertEquals(3, waves.size());
IWaveform<?> wave = waves.get(0);
IWaveform wave = waves.get(0);
assertTrue(wave instanceof ITxStream<?>);
ITxStream<?> stream = (ITxStream<?>) wave;
assertEquals(2, stream.getGenerators().size());
NavigableMap<Long, List<ITxEvent>> eventsList = stream.getEvents();
assertEquals(18, eventsList.size());
assertEquals(27, eventsList.size());
Entry<Long, List<ITxEvent>> eventEntry = eventsList.firstEntry();
assertEquals(100000L, (long) eventEntry.getKey());
assertEquals(100000000L, (long) eventEntry.getKey());
List<ITxEvent> events = eventEntry.getValue();
assertEquals(2, events.size());
assertEquals(1, events.size());
ITxEvent event = events.get(0);
assertEquals(Type.BEGIN, event.getType());
ITx tx = event.getTransaction();

View File

@ -5,8 +5,7 @@ Bundle-SymbolicName: com.minres.scviewer.database.text
Bundle-Version: 1.0.1.qualifier
Bundle-Vendor: MINRES Technologies GmbH
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Import-Package: com.minres.scviewer.database,
org.osgi.framework;version="1.3.0"
Import-Package: org.osgi.framework;version="1.3.0"
Require-Bundle: com.minres.scviewer.database;bundle-version="1.0.0",
org.codehaus.groovy;bundle-version="1.8.6",
org.eclipse.equinox.util;bundle-version="1.0.500",

View File

@ -59,12 +59,14 @@ public class TextDbLoader implements IWaveformDbLoader{
boolean load(IWaveformDb db, File file) throws Exception {
this.db=db
this.streams=[]
def gzipped = isGzipped(file)
if(isTxfile(gzipped?new GZIPInputStream(new FileInputStream(file)):new FileInputStream(file))){
parseInput(gzipped?new GZIPInputStream(new FileInputStream(file)):new FileInputStream(file))
calculateConcurrencyIndicees()
return true
}
try {
def gzipped = isGzipped(file)
if(isTxfile(gzipped?new GZIPInputStream(new FileInputStream(file)):new FileInputStream(file))){
parseInput(gzipped?new GZIPInputStream(new FileInputStream(file)):new FileInputStream(file))
calculateConcurrencyIndicees()
return true
}
} catch(Exception e) { }
return false;
}

View File

@ -109,7 +109,7 @@ class TxStream extends HierNode implements ITxStream {
}
@Override
public Boolean equals(IWaveform<? extends IWaveformEvent> other) {
public Boolean equals(IWaveform other) {
return(other instanceof TxStream && this.getId()==other.getId());
}

View File

@ -47,15 +47,6 @@ public interface IVCDDatabaseBuilder {
*/
public int getNetWidth(int netId);
/**
* Append transition.
*
* @param netId the int value
* @param currentTime the current time in ps
* @param decodedValues the decoded bit values
*/
public void appendTransition(int netId, long currentTime, char decodedValue);
/**
* Append transition.
*

View File

@ -12,6 +12,7 @@ package com.minres.scviewer.database.vcd;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@ -22,10 +23,6 @@ import java.util.Vector;
import com.minres.scviewer.database.BitVector;
import com.minres.scviewer.database.ISignal;
import com.minres.scviewer.database.ISignalChange;
import com.minres.scviewer.database.ISignalChangeBitVector;
import com.minres.scviewer.database.ISignalChangeReal;
import com.minres.scviewer.database.ISignalChangeBit;
import com.minres.scviewer.database.IWaveform;
import com.minres.scviewer.database.IWaveformDb;
import com.minres.scviewer.database.IWaveformDbLoader;
@ -49,7 +46,7 @@ public class VCDDbLoader implements IWaveformDbLoader, IVCDDatabaseBuilder {
private Stack<String> moduleStack;
/** The signals. */
private List<IWaveform<? extends IWaveformEvent>> signals;
private List<IWaveform> signals;
/** The max time. */
private long maxTime;
@ -71,40 +68,41 @@ public class VCDDbLoader implements IWaveformDbLoader, IVCDDatabaseBuilder {
public boolean load(IWaveformDb db, File file) throws Exception {
this.db=db;
this.maxTime=0;
FileInputStream fis = new FileInputStream(file);
byte[] buffer = new byte[dateBytes.length];
int read = fis.read(buffer, 0, dateBytes.length);
fis.close();
if (read == dateBytes.length)
for (int i = 0; i < dateBytes.length; i++)
if (buffer[i] != dateBytes[i])
return false;
try {
FileInputStream fis = new FileInputStream(file);
byte[] buffer = new byte[dateBytes.length];
int read = fis.read(buffer, 0, dateBytes.length);
fis.close();
if (read == dateBytes.length)
for (int i = 0; i < dateBytes.length; i++)
if (buffer[i] != dateBytes[i])
return false;
} catch(FileNotFoundException e) {
return false;
}
signals = new Vector<IWaveform<? extends IWaveformEvent>>();
signals = new Vector<IWaveform>();
moduleStack= new Stack<String>();
boolean res = new VCDFileParser(false).load(new FileInputStream(file), this);
moduleStack=null;
if(!res) throw new InputFormatException();
// calculate max time of database
for(IWaveform<? extends IWaveformEvent> waveform:signals) {
NavigableMap<Long, ? extends ISignalChange> events =((ISignal<? extends ISignalChange>)waveform).getEvents();
for(IWaveform waveform:signals) {
NavigableMap<Long, ?> events =((ISignal<?>)waveform).getEvents();
if(events.size()>0)
maxTime= Math.max(maxTime, events.lastKey());
}
// extend signals to hav a last value set at max time
for(IWaveform<? extends IWaveformEvent> waveform:signals){
TreeMap<Long,? extends ISignalChange> events = ((VCDSignal<? extends ISignalChange>)waveform).values;
if(events.size()>0 && events.lastKey()<maxTime){
ISignalChange x = events.lastEntry().getValue();
if(x instanceof ISignalChangeBit)
((VCDSignal<ISignalChangeBit>)waveform).values.put(maxTime,
new VCDSignalChangeBit(maxTime, ((ISignalChangeBit)x).getValue()));
else if(x instanceof ISignalChangeBitVector)
((VCDSignal<ISignalChangeBitVector>)waveform).values.put(maxTime,
new VCDSignalChangeBitVector(maxTime, ((ISignalChangeBitVector)x).getValue()));
else if(x instanceof ISignalChangeReal)
((VCDSignal<ISignalChangeReal>)waveform).values.put(maxTime,
new VCDSignalChangeReal(maxTime, ((ISignalChangeReal)x).getValue()));
for(IWaveform s:signals){
if(s instanceof VCDSignal<?>) {
TreeMap<Long,?> events = (TreeMap<Long, ?>) ((VCDSignal<?>)s).getEvents();
if(events.size()>0 && events.lastKey()<maxTime){
Object val = events.lastEntry().getValue();
if(val instanceof BitVector) {
((VCDSignal<BitVector>)s).addSignalChange(maxTime, (BitVector) val);
} else if(val instanceof Double)
((VCDSignal<Double>)s).addSignalChange(maxTime, (Double) val);
}
}
}
return true;
@ -122,7 +120,7 @@ public class VCDDbLoader implements IWaveformDbLoader, IVCDDatabaseBuilder {
* @see com.minres.scviewer.database.ITrDb#getAllWaves()
*/
@Override
public List<IWaveform<? extends IWaveformEvent>> getAllWaves() {
public List<IWaveform> getAllWaves() {
return signals;
}
@ -154,18 +152,14 @@ public class VCDDbLoader implements IWaveformDbLoader, IVCDDatabaseBuilder {
public Integer newNet(String name, int i, int width) {
String netName = moduleStack.empty()? name: moduleStack.lastElement()+"."+name;
int id = signals.size();
VCDSignal<? extends IWaveformEvent> signal;
if(width<0) {
signal = i<0 ? new VCDSignal<ISignalChangeReal>(db, id, netName, width) :
new VCDSignal<ISignalChangeReal>((VCDSignal<ISignalChangeReal>)signals.get(i), id, netName);
} else if(width==1){
signal = i<0 ? new VCDSignal<ISignalChangeBit>(db, id, netName) :
new VCDSignal<ISignalChangeBit>((VCDSignal<ISignalChangeBit>)signals.get(i), id, netName);
} else {
signal = i<0 ? new VCDSignal<ISignalChangeBitVector>(db, id, netName, width) :
new VCDSignal<ISignalChangeBitVector>((VCDSignal<VCDSignalChangeBitVector>)signals.get(i), id, netName);
};
signals.add(signal);
assert(width>0);
if(width==0) {
signals.add( i<0 ? new VCDSignal<Double>(db, id, netName) :
new VCDSignal<Double>((VCDSignal<Double>)signals.get(i), id, netName));
} else if(width>0){
signals.add( i<0 ? new VCDSignal<BitVector>(db, id, netName, width) :
new VCDSignal<BitVector>((VCDSignal<BitVector>)signals.get(i), id, netName));
}
return id;
}
@ -174,7 +168,7 @@ public class VCDDbLoader implements IWaveformDbLoader, IVCDDatabaseBuilder {
*/
@Override
public int getNetWidth(int intValue) {
VCDSignal<? extends IWaveformEvent> signal = (VCDSignal<? extends IWaveformEvent>) signals.get(intValue);
VCDSignal<?> signal = (VCDSignal<?>) signals.get(intValue);
return signal.getWidth();
}
@ -183,12 +177,10 @@ public class VCDDbLoader implements IWaveformDbLoader, IVCDDatabaseBuilder {
*/
@SuppressWarnings("unchecked")
@Override
public void appendTransition(int signalId, long currentTime, char decodedValues) {
VCDSignal<? extends IWaveformEvent> signal = (VCDSignal<? extends IWaveformEvent>) signals.get(signalId);
Long time = currentTime*TIME_RES;
if(signal.getWidth()==1){
((VCDSignal<ISignalChangeBit>)signal).values.put(time, new VCDSignalChangeBit(time, decodedValues));
}
public void appendTransition(int signalId, long currentTime, BitVector value) {
VCDSignal<BitVector> signal = (VCDSignal<BitVector>) signals.get(signalId);
Long time = currentTime* TIME_RES;
signal.getEvents().put(time, value);
}
/* (non-Javadoc)
@ -196,24 +188,11 @@ public class VCDDbLoader implements IWaveformDbLoader, IVCDDatabaseBuilder {
*/
@SuppressWarnings("unchecked")
@Override
public void appendTransition(int signalId, long currentTime, BitVector decodedValues) {
VCDSignal<? extends IWaveformEvent> signal = (VCDSignal<? extends IWaveformEvent>) signals.get(signalId);
public void appendTransition(int signalId, long currentTime, double value) {
VCDSignal<?> signal = (VCDSignal<?>) signals.get(signalId);
Long time = currentTime* TIME_RES;
if(signal.getWidth()>1){
((VCDSignal<VCDSignalChangeBitVector>)signal).values.put(time, new VCDSignalChangeBitVector(time, decodedValues));
}
}
/* (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 signalId, long currentTime, double decodedValue) {
VCDSignal<? extends IWaveformEvent> signal = (VCDSignal<? extends IWaveformEvent>) signals.get(signalId);
Long time = currentTime* TIME_RES;
if(signal.getWidth()<0){
((VCDSignal<ISignalChangeReal>)signal).values.put(time, new VCDSignalChangeReal(time, decodedValue));
if(signal.getWidth()==0){
((VCDSignal<Double>)signal).getEvents().put(time, value);
}
}

View File

@ -13,6 +13,7 @@ package com.minres.scviewer.database.vcd;
import java.io.*;
import java.util.*;
import com.minres.scviewer.database.BitValue;
import com.minres.scviewer.database.BitVector;
class VCDFileParser {
@ -65,7 +66,7 @@ class VCDFileParser {
nextToken(); // size
int width = Integer.parseInt(tokenizer.sval);
if("real".equals(type))
width*=-1;
width=0;
nextToken();
String id = tokenizer.sval;
nextToken();
@ -183,7 +184,7 @@ class VCDFileParser {
}
int netWidth = traceBuilder.getNetWidth(net);
if(netWidth<0) {
if(netWidth==0) {
if("nan".equals(value))
traceBuilder.appendTransition(net, currentTime, Double.NaN);
else
@ -192,39 +193,40 @@ class VCDFileParser {
BitVector decodedValues = new BitVector(netWidth);
if (value.equals("z") && netWidth > 1) {
for (int i = 0; i < netWidth; i++)
decodedValues.setValue(i, BitVector.VALUE_Z);
decodedValues.setValue(i, BitValue.Z);
} else if (value.equals("x") && netWidth > 1) {
for (int i = 0; i < netWidth; i++)
decodedValues.setValue(i, BitVector.VALUE_X);
decodedValues.setValue(i, BitValue.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;
for (int convertedIndex = netWidth -1; convertedIndex >=0; convertedIndex--) {
if(convertedIndex<value.length()) {
switch (value.charAt(stringIndex++)) {
case 'z':
decodedValues.setValue(convertedIndex, BitValue.Z);
break;
case '1':
decodedValues.setValue(convertedIndex, BitVector.VALUE_1);
break;
case '1':
decodedValues.setValue(convertedIndex, BitValue.ONE);
break;
case '0':
decodedValues.setValue(convertedIndex, BitVector.VALUE_0);
break;
case '0':
decodedValues.setValue(convertedIndex, BitValue.ZERO);
break;
case 'x':
decodedValues.setValue(convertedIndex, BitVector.VALUE_X);
break;
case 'x':
decodedValues.setValue(convertedIndex, BitValue.X);
break;
default:
decodedValues.setValue(convertedIndex, BitVector.VALUE_X);
default:
decodedValues.setValue(convertedIndex, BitValue.X);
}
} else {
decodedValues.setValue(convertedIndex, BitValue.ZERO);
}
}
}
if(netWidth==1)
traceBuilder.appendTransition(net, currentTime, decodedValues.getValue()[0]);
else
traceBuilder.appendTransition(net, currentTime, decodedValues);
traceBuilder.appendTransition(net, currentTime, decodedValues);
}
}
return true;

View File

@ -16,12 +16,11 @@ import java.util.TreeMap;
import com.minres.scviewer.database.HierNode;
import com.minres.scviewer.database.ISignal;
import com.minres.scviewer.database.ISignalChange;
import com.minres.scviewer.database.IWaveform;
import com.minres.scviewer.database.IWaveformDb;
import com.minres.scviewer.database.IWaveformEvent;
public class VCDSignal<T extends ISignalChange> extends HierNode implements ISignal<T> {
public class VCDSignal<T> extends HierNode implements ISignal<T> {
private long id;
@ -31,9 +30,11 @@ public class VCDSignal<T extends ISignalChange> extends HierNode implements ISig
private final int width;
private final T dummy = null;
private IWaveformDb db;
TreeMap<Long, T> values;
private TreeMap<Long, T> values;
public VCDSignal(IWaveformDb db, String name) {
this(db, 0, name, 1);
@ -53,7 +54,7 @@ public class VCDSignal<T extends ISignalChange> extends HierNode implements ISig
}
@SuppressWarnings("unchecked")
public VCDSignal(IWaveform<? extends ISignalChange> other, int id, String name) {
public VCDSignal(ISignal<T> other, int id, String name) {
super(name);
fullName=name;
this.id=id;
@ -91,8 +92,8 @@ public class VCDSignal<T extends ISignalChange> extends HierNode implements ISig
return db;
}
public void addSignalChange(T change){
values.put(change.getTime(), change);
public void addSignalChange(Long time, T value){
values.put(time, value);
}
@Override
@ -101,12 +102,12 @@ public class VCDSignal<T extends ISignalChange> extends HierNode implements ISig
}
@Override
public T getWaveformEventsAtTime(Long time) {
public T getWaveformValueAtTime(Long time) {
return values.get(time);
}
@Override
public T getWaveformEventsBeforeTime(Long time) {
public T getWaveformValueBeforeTime(Long time) {
Entry<Long, T> e = values.floorEntry(time);
if(e==null)
return null;
@ -115,10 +116,15 @@ public class VCDSignal<T extends ISignalChange> extends HierNode implements ISig
}
@Override
public Boolean equals(IWaveform<? extends IWaveformEvent> other) {
public Boolean equals(IWaveform other) {
return(other instanceof VCDSignal<?> && this.getId()==other.getId());
}
@Override
public Class<?> getType() {
return dummy.getClass();
}
}

View File

@ -1,37 +0,0 @@
/*******************************************************************************
* Copyright (c) 2015 MINRES Technologies GmbH and others.
* 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
*******************************************************************************/
package com.minres.scviewer.database.vcd;
import com.minres.scviewer.database.ISignalChangeBit;
import com.minres.scviewer.database.SignalChange;
public class VCDSignalChangeBit extends SignalChange implements ISignalChangeBit, Cloneable {
private char value;
public VCDSignalChangeBit(Long time, char value) {
super(time);
this.value=value;
}
public char getValue() {
return value;
}
public void setValue(char value) {
this.value = value;
}
@Override
public String toString() {
return value+"@"+getTime();
}
}

View File

@ -1,43 +0,0 @@
/*******************************************************************************
* Copyright (c) 2015 MINRES Technologies GmbH and others.
* 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
*******************************************************************************/
package com.minres.scviewer.database.vcd;
import com.minres.scviewer.database.BitVector;
import com.minres.scviewer.database.ISignalChangeBitVector;
import com.minres.scviewer.database.SignalChange;
public class VCDSignalChangeBitVector extends SignalChange implements ISignalChangeBitVector, Cloneable {
private BitVector value;
public VCDSignalChangeBitVector(Long time) {
super(time);
}
public VCDSignalChangeBitVector(Long time, BitVector decodedValues) {
super(time);
this.value=decodedValues;
}
public BitVector getValue() {
return value;
}
public void setValue(BitVector value) {
this.value = value;
}
@Override
public String toString() {
return value.toHexString()+"@"+getTime();
}
}

View File

@ -1,37 +0,0 @@
/*******************************************************************************
* Copyright (c) 2015 MINRES Technologies GmbH and others.
* 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
*******************************************************************************/
package com.minres.scviewer.database.vcd;
import com.minres.scviewer.database.ISignalChangeReal;
import com.minres.scviewer.database.SignalChange;
public class VCDSignalChangeReal extends SignalChange implements ISignalChangeReal, Cloneable {
private double value;
public VCDSignalChangeReal(Long time, double value) {
super(time);
this.value=value;
}
public double getValue() {
return value;
}
public void setValue(double value) {
this.value = value;
}
@Override
public String toString() {
return value+"@"+getTime();
}
}

View File

@ -0,0 +1,68 @@
package com.minres.scviewer.database;
public enum BitValue {
ZERO,
ONE,
X,
Z;
private static final BitValue[] ORDINAL_TABLE = BitValue.values();
public static BitValue fromChar(char c) {
switch (c) {
case '0':
return ZERO;
case '1':
return ONE;
case 'x':
case 'X':
return X;
case 'z':
case 'Z':
return Z;
default:
throw new NumberFormatException("unknown digit " + c);
}
}
public char toChar() {
switch (this) {
case ZERO:
return '0';
case ONE:
return '1';
case X:
return 'x';
case Z:
return 'z';
}
return ' '; // Unreachable?
}
public static BitValue fromInt(int i) {
if (i == 0) {
return ZERO;
} else {
return ONE;
}
}
public int toInt() {
return (this == ONE) ? 1 : 0;
}
public static BitValue fromOrdinal(int ord) {
return ORDINAL_TABLE[ord];
}
public int compare(BitValue other) {
if (this == ONE && other == ZERO) {
return 1;
} else if (this == ZERO && other == ONE) {
return -1;
} else {
// Either these are equal, or there is an X and Z, which match everything.
return 0;
}
}
}

View File

@ -12,31 +12,53 @@ package com.minres.scviewer.database;
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;
private int[] packedValues;
public BitVector(int netWidth) {
this.width=netWidth;
value = new char[netWidth];
for(int i=0; i<netWidth; i++) value[i]='0';
packedValues = new int[(netWidth+15)/16];
for(int i=0; i<packedValues.length; i++) packedValues[i]=0;
}
public void setValue(int i, char value) {
this.value[i]=value;
public void setValue(int i, BitValue value) {
int bitIndex = i*2;
int wordOffset = bitIndex >> 5;
int bitOffset = bitIndex & 31;
packedValues[wordOffset] &= ~(3 << bitOffset);
packedValues[wordOffset] |= value.ordinal() << bitOffset;
}
public char[] getValue() {
return value;
int bitOffset = 0;
int wordOffset = 0;
char[] res = new char[width];
// Copy values out of packed array
for (int i = 0; i < width; i++) {
int currentWord = (packedValues[wordOffset] >> bitOffset)&3;
res[width-i-1]=BitValue.fromInt(currentWord).toChar();
bitOffset += 2;
if (bitOffset == 32) {
wordOffset++;
bitOffset = 0;
}
}
return res;
}
public void setValue(char[] value) {
this.value = value;
int bitIndex = width;
int wordOffset = bitIndex >> 4;
int bitOffset = (bitIndex * 2) % 32;
for (int i = Math.min(value.length, width) - 1; i >= 0; i--) {
packedValues[wordOffset] |= BitValue.fromChar(value[i]).ordinal() << bitOffset;
bitOffset += 2;
if (bitOffset == 32) {
wordOffset++;
bitOffset = 0;
}
}
}
public int getWidth() {
@ -44,67 +66,101 @@ public class BitVector {
}
public String toString(){
return new String(value);
return new String(getValue());
}
public String toHexString(){
int resWidth=(width-1)/4+1;
char[] value=getValue();
char[] res = new char[resWidth];
for(int i=resWidth-1; i>=0; i--){
int digit=0;
for(int j=3; j>=0; j--){
if(value[4*i+j]==VALUE_X ||value[4*i+j]==VALUE_Z ){
res[i]=VALUE_X;
}
if(value[4*i+j]==VALUE_1)
BitValue val = BitValue.fromChar(value[4*i+j]);
switch(val) {
case X:
case Z:
res[i]=val.toChar();
continue;
case ONE:
digit+=1<<(3-j);
res[i]=Character.forDigit(digit, 16); //((digit < 10) ? '0' + digit : 'a' + digit -10)
break;
default:
break;
}
}
res[i]=Character.forDigit(digit, 16); //((digit < 10) ? '0' + digit : 'a' + digit -10)
}
return new String(res);
}
public long toUnsignedValue() {
long res = 0;
for(char c:value) {
int bitOffset = width * 2;
int wordOffset = bitOffset >> 5;
bitOffset &= 31;
int currentWord = packedValues[wordOffset] >> bitOffset;
// Copy values out of packed array
for (int i = 0; i < width; i++) {
res<<=1;
switch (c) {
case VALUE_1:
switch (currentWord & 3) {
case 1:
res++;
break;
case VALUE_X:
case VALUE_Z:
case 2:
case 3:
return 0;
default:
break;
}
}
return res;
bitOffset += 2;
if (bitOffset == 32) {
wordOffset++;
currentWord = packedValues[wordOffset];
bitOffset = 0;
} else {
currentWord >>= 2;
}
}
return res;
}
public long toSignedValue() {
Boolean negative=null;
long res = 0;
for(char c:value) {
int bitOffset = width * 2;
int wordOffset = bitOffset >> 5;
bitOffset &= 31;
int currentWord = packedValues[wordOffset] >> bitOffset;
// Copy values out of packed array
for (int i = 0; i < width; i++) {
if(negative == null) {
switch (c) {
case VALUE_1: negative=true; break;
case VALUE_0: negative=false; break;
case VALUE_X:
case VALUE_Z: return 0;
switch (currentWord & 3) {
case 1: negative=true; break;
case 0: negative=false; break;
case 2:
case 3: return 0;
default:
}
} else {
res<<=1;
switch (c) {
case VALUE_1: if(!negative) res++; break;
case VALUE_0: if(negative) res++; break;
case VALUE_X:
case VALUE_Z: return 0;
switch (currentWord & 3) {
case 1: if(!negative) res++; break;
case 0: if(negative) res++; break;
case 2:
case 3: return 0;
default:
}
}
}
bitOffset += 2;
if (bitOffset == 32) {
wordOffset++;
currentWord = packedValues[wordOffset];
bitOffset = 0;
} else {
currentWord >>= 2;
}
}
return negative?-1*(res+1):res;
}
}

View File

@ -13,12 +13,14 @@ package com.minres.scviewer.database;
import java.util.NavigableMap;
public interface ISignal<T extends ISignalChange> extends IWaveform<T>{
public interface ISignal<T> extends IWaveform{
public NavigableMap<Long, T> getEvents();
public T getWaveformEventsAtTime(Long time);
public T getWaveformValueAtTime(Long time);
public T getWaveformEventsBeforeTime(Long time);
public T getWaveformValueBeforeTime(Long time);
public Class<?> getType();
}

View File

@ -1,15 +0,0 @@
/*******************************************************************************
* Copyright (c) 2015 MINRES Technologies GmbH and others.
* 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
*******************************************************************************/
package com.minres.scviewer.database;
public interface ISignalChange extends IWaveformEvent {
}

View File

@ -1,17 +0,0 @@
/*******************************************************************************
* Copyright (c) 2015 MINRES Technologies GmbH and others.
* 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
*******************************************************************************/
package com.minres.scviewer.database;
public interface ISignalChangeBit extends ISignalChange{
public char getValue();
}

View File

@ -1,17 +0,0 @@
/*******************************************************************************
* Copyright (c) 2015 MINRES Technologies GmbH and others.
* 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
*******************************************************************************/
package com.minres.scviewer.database;
public interface ISignalChangeBitVector extends ISignalChange {
public BitVector getValue();
}

View File

@ -1,17 +0,0 @@
/*******************************************************************************
* Copyright (c) 2015 MINRES Technologies GmbH and others.
* 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
*******************************************************************************/
package com.minres.scviewer.database;
public interface ISignalChangeReal extends ISignalChange{
public double getValue();
}

View File

@ -14,7 +14,7 @@ import java.util.Collection;
import java.util.List;
import java.util.NavigableMap;
public interface ITxStream<T extends ITxEvent> extends IWaveform<T> {
public interface ITxStream<T extends ITxEvent> extends IWaveform {
public List<ITxGenerator> getGenerators();

View File

@ -11,7 +11,7 @@
package com.minres.scviewer.database;
public interface IWaveform<T extends IWaveformEvent> extends IHierNode {
public interface IWaveform extends IHierNode {
public Long getId();
@ -19,6 +19,6 @@ public interface IWaveform<T extends IWaveformEvent> extends IHierNode {
public IWaveformDb getDb();
public Boolean equals(IWaveform<? extends IWaveformEvent> other);
public Boolean equals(IWaveform other);
}

View File

@ -18,9 +18,9 @@ public interface IWaveformDb extends IHierNode {
public Long getMaxTime();
public IWaveform<? extends IWaveformEvent> getStreamByName(String name);
public IWaveform getStreamByName(String name);
public List<IWaveform<?>> getAllWaves();
public List<IWaveform> getAllWaves();
public List<RelationType> getAllRelationTypes();

View File

@ -20,7 +20,7 @@ public interface IWaveformDbLoader {
public Long getMaxTime();
public List<IWaveform<? extends IWaveformEvent>> getAllWaves() ;
public List<IWaveform> getAllWaves() ;
public Collection<RelationType> getAllRelationTypes() ;

View File

@ -1,46 +0,0 @@
/*******************************************************************************
* Copyright (c) 2015 MINRES Technologies GmbH and others.
* 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
*******************************************************************************/
package com.minres.scviewer.database;
public class SignalChange implements IWaveformEvent {
Long time;
public SignalChange() {
time=0L;
}
public SignalChange(Long time) {
super();
this.time = time;
}
@Override
public int compareTo(IWaveformEvent o) {
return time.compareTo(o.getTime());
}
@Override
public Long getTime() {
return time;
}
public void setTime(Long time) {
this.time = time;
}
@Override
public IWaveformEvent duplicate() throws CloneNotSupportedException {
return (IWaveformEvent) this.clone();
}
}

View File

@ -41,7 +41,7 @@ public class WaveformDb extends HierNode implements IWaveformDb {
private List<RelationType> relationTypes;
private Map<String, IWaveform<?>> waveforms;
private Map<String, IWaveform> waveforms;
private Long maxTime;
@ -61,7 +61,7 @@ public class WaveformDb extends HierNode implements IWaveformDb {
public WaveformDb() {
super();
waveforms = new HashMap<String, IWaveform<?>>();
waveforms = new HashMap<String, IWaveform>();
relationTypes=new ArrayList<>();
maxTime=0L;
}
@ -72,20 +72,20 @@ public class WaveformDb extends HierNode implements IWaveformDb {
}
@Override
public IWaveform<? extends IWaveformEvent> getStreamByName(String name) {
public IWaveform getStreamByName(String name) {
return waveforms.get(name);
}
@Override
public List<IWaveform<?>> getAllWaves() {
return new ArrayList<IWaveform<?>>(waveforms.values());
public List<IWaveform> getAllWaves() {
return new ArrayList<IWaveform>(waveforms.values());
}
@Override
public boolean load(File inp) throws Exception {
for(IWaveformDbLoader loader:loaders){
if(loader.load(this, inp)){
for(IWaveform<?> w:loader.getAllWaves()){
for(IWaveform w:loader.getAllWaves()){
waveforms.put(w.getFullName(),w);
}
if(loader.getMaxTime()>maxTime){
@ -125,8 +125,8 @@ public class WaveformDb extends HierNode implements IWaveformDb {
private void buildHierarchyNodes() throws InputFormatException{
childNodes= new ArrayList<IHierNode>();
for(IWaveform<?> stream:getAllWaves()){
updateMaxTime(stream);
for(IWaveform stream:getAllWaves()){
//updateMaxTime(stream);
String[] hier = stream.getName().split("\\.");
IHierNode node = this;
List<String> path=new LinkedList<String>();
@ -169,16 +169,6 @@ public class WaveformDb extends HierNode implements IWaveformDb {
}
}
private void updateMaxTime(IWaveform<?> waveform) {
Long last=0L;
if(waveform instanceof ITxStream<?> && ((ITxStream<?>)waveform).getEvents().lastEntry()!=null)
last=((ITxStream<?>)waveform).getEvents().lastEntry().getKey();
else if(waveform instanceof ISignal<?> && ((ISignal<?>)waveform).getEvents().lastEntry()!=null)
last=((ISignal<?>)waveform).getEvents().lastEntry().getKey();
if(last>maxTime)
maxTime=last;
}
private static String join(Collection<?> col, String delim) {
StringBuilder sb = new StringBuilder();
Iterator<?> iter = col.iterator();