/* -*- tab-width: 4 -*-
*
* Electric(tm) VLSI Design System
*
* File: NanosimDataAnalyzer.java
* Written by Jonathan Gainsley, Sun Microsystems.
*
* Copyright (c) 2005 Sun Microsystems and Static Free Software
*
* Electric(tm) is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* Electric(tm) is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Electric(tm); see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, Mass 02111-1307, USA.
*/
package com.sun.electric.tool.simulation.test;
import java.util.*;
public class NanosimDataAnalyzer extends NanosimBERT.NanosimTerminal implements BERT.DataAnalyzer {
private int delayPeriods;
private double delayNS;
private NanosimDataGen checkGenerator;
private StringBuffer capturedData;
private String pinName;
private double voltageLowThreshold;
private double voltageHighThreshold;
private int numErrors; // true if error during check phase of BER testing
/**
* Constructor
* @param parentModule the parent Module that this Terminal is part of
*/
NanosimDataAnalyzer(NanosimBERT.NanosimDataModule parentModule) {
super(parentModule);
delayPeriods = 0;
delayNS = 0;
capturedData = new StringBuffer();
pinName = null;
voltageLowThreshold = voltageHighThreshold = 0.5;
numErrors = 0;
}
public void measureBER(BERT.DataGenerator expectedData) {
if (!(expectedData instanceof NanosimDataGen)) {
System.out.println("Invalid argument to NanosimDataAcquire.acquireDataFor(): can only acquire data for NanosimDataGen");
return;
}
checkGenerator = (NanosimDataGen)expectedData;
}
public void setDelay(int periods, double ns) {
this.delayNS = ns;
this.delayPeriods = periods;
}
public void setPinName(String pin) {
pinName = pin;
}
public String getPinName() {
return pinName;
}
public void setVoltageThreshold(double voltageLowThreshold, double voltageHighThreshold) {
this.voltageLowThreshold = voltageLowThreshold;
this.voltageHighThreshold = voltageHighThreshold;
}
public double getMeasuredBER() {
if (capturedData.length() == 0) return 0;
return (double)numErrors / (double)(capturedData.length());
}
/**
* Convert the voltage to a valid state 0 or 1.
* If the voltage does not translate to a valid state,
* -1 is returned
* @param voltage the voltage to convert
* @return 0 or 1, or -1 if not a valid voltage state
*/
public int voltageToState(double voltage) {
if (voltage < voltageLowThreshold) return 0;
if (voltage >= voltageHighThreshold) return 1;
return -1;
}
private double getDelay() {
double delay = getParentModule().getPeriod() * delayPeriods + delayNS;
return delay;
}
void logError() {
numErrors++;
}
/**
* Return a Set of {@link NanosimBERT.Event} objects
* that characterize the behavior of the Module
* when the BERT runs (BERT starts at time 0).
* @param stopTimeNS the time to the BERT will stop,
* with the BERT start time being time zero.
* @return a Set of Events
*/
public Set generateEvents(double startTimeNS, double stopTimeNS) {
Set set = new TreeSet();
double curTime = startTimeNS;
curTime += getDelay();
String node = pinName;
if (node == null) {
System.out.println("Error: no pin defined for DataAnalyzer, will not capture or check data");
return set;
}
if (checkGenerator != null) {
// check and capture
int bitIndex = 0;
while (curTime < stopTimeNS) {
boolean val = checkGenerator.getBit(bitIndex);
NanosimBERT.Event e = NanosimBERT.Event.createCaptureAndCheckNodeEvent(curTime, node, val ? 1 : 0, this);
set.add(e);
curTime += getParentModule().getPeriod();
bitIndex++;
}
} else {
// capture only
while (curTime < stopTimeNS) {
NanosimBERT.Event e = NanosimBERT.Event.createCaptureNodeEvent(curTime, node, this);
set.add(e);
curTime += getParentModule().getPeriod();
}
}
return set;
}
void captureBit(boolean b) {
capturedData.append(b ? '1' : '0');
}
public BitVector getCapturedData() {
return new BitVector(capturedData.toString(), "captured data");
}
public void clearCapturedData() {
capturedData.delete(0, capturedData.length());
numErrors = 0;
}
public void printCapturedData() {
String status = checkGenerator == null ? "" : (numErrors != 0 ? "ERRORS!" : "OK");
System.out.println("Analyzer on pin '"+getPinName()+"' captured "+status+": "+getCapturedData().getState());
}
/** Unit Test */
public static void main(String args[]) {
// create Module, set frequency (data gen needs frequency defined)
NanosimBERT.NanosimDataModule module = new NanosimBERT.NanosimDataModule();
module.setFrequency(1000000);
// create Generator, define pin (data gen needs one pin defined)
NanosimDataGen gen = (NanosimDataGen)module.createDataGenerator();
gen.addPinName("testpin");
// create Analyzer
NanosimDataAnalyzer ana = (NanosimDataAnalyzer)module.createDataAnalyzer();
ana.setPinName("testpinOut");
ana.setDelay(1, 0.5);
double time = 10;
System.out.println("Capture only, "+time+"ns");
NanosimBERT.printEvents(ana.generateEvents(0, time));
time = 30;
System.out.println("-----------------------------------");
System.out.println("Capture plus Check, "+time+"ns");
gen.setPattern(new BitVector("1011110", "blah"), new BitVector("0100001011", ""));
ana.measureBER(gen);
NanosimBERT.printEvents(ana.generateEvents(0, time));
}
}