/* -*- tab-width: 4 -*-
*
* Electric(tm) VLSI Design System
*
* File: BERT.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.Comparator;
import java.util.Iterator;
/**
* Interface for a HP81250 Bit Error Rate Tester.
* A BERT is composed of several test modules. Each Module
* is composed of one or more terminals. A terminal drives a
* single waveform (and it's complement for differential signals)
* to the chip.
* <P>
* The BERT interface tries to hide the details from the user -
* handles names, port locations, terminal locations, etc. Rather
* than having to know what the address and port location of a Data Generator
* is on the BERT, the user instead calls BERT.createDataGenerator().
* This will return a DataGenerator for the user to use.
* <P>
* It is up to the implementation of the BERT to return a DataGenerator
* and keep track of its address and port. Or, to issue an error if
* there are no (more) DataGenerators available on the BERT.
*/
public interface BERT {
/**
* Create a Data Module that is part of the BERT for use
* by the user. May return null if not more data modules
* can be created (i.e. are present in the real BERT).
* @return a new DataModule
*/
public DataModule createDataModule();
/**
* Run the BERT and its configured modules for the specified
* time in nanoseconds. This is a replacement for doing
* start, wait(nanoseconds), stop.
* @param nanoseconds
*/
public void run(double nanoseconds);
/**
* Same as {@link #run(double)}, but in minutes for
* very long runs.
* @param minutes number of minutes to run
*/
public void runMinutes(double minutes);
// ======================================================================
/**
* A Data Generator/Analyzer Module.
*/
public interface DataModule {
/**
* Create a Data Generator from this module.
* Returns null if not possible. It is up
* to the implementation of the Module to
* know what is the number of data generators
* available on this module.
* @return a Data Generator.
*/
public DataGenerator createDataGenerator();
/**
* Create a Data Analyzer from this module.
* Returns null if not possible. It is up
* to the implementation of the Module to
* know what is the number of data analyzers
* available on this module.
* @return a Data Analyzer.
*/
public DataAnalyzer createDataAnalyzer();
/**
* This sets the frequency of the module,
* which also dictates the frequency of all its terminals
* @param freqKHz the frequency in Kilohertz
*/
public void setFrequency(double freqKHz);
/**
* Get the frequency set for this module
* @return the frequency in Kilohertz
*/
public double getFrequency();
/**
* Return the frequency as a period, in nanoseconds.
* @return the period in nanoseconds
*/
public double getPeriod();
}
/**
* A Terminal drives or reads a signal to or from a
* chip.
*/
public interface Terminal {
/**
* Get the parent Module that this Terminal is part of.
* @return the parent Module
*/
public DataModule getParentModule();
/**
* Enable or disable this Terminal
* @param enable true to enable (should be default),
* false to disable
*/
public void setEnabled(boolean enable);
/**
* Get whether or not this Terminal is enabled.
* @return true if it is enabled, false otherwise.
*/
public boolean isEnabled();
}
/**
* A Data Generator is a terminal that generates data
*/
public interface DataGenerator extends Terminal {
/**
* Set the pattern that this generator will generate.
* The frequency is set by the module this generator is in.
* @param start the start of the pattern
* @param repeat the pattern that will repeat after the start pattern
*/
public void setPattern(BitVector start, BitVector repeat);
/**
* Set the pattern that this generator will generate.
* The frequency is set by the module this generator is in.
* @param start the start of the pattern
* @param repeat the pattern that will repeat after the start pattern
*/
public void setPattern(String start, String repeat);
/**
* Set the delay before the pattern starts. Defaults to zero.
* @param ns the time delay, in nanoseconds
*/
public void setDelay(double ns);
/**
* Set the way data is generated.
* @param mode which mode to use.
*/
public void setSignalMode(SignalMode mode);
/**
* Configure this terminal to generate a clock. This sets pattern
* to be always 1, and mode to be Return to Zero. The clock
* transitions high at time 0 and every period multiple thereafter.
* You will still need to set the voltage and delay (if any).
*/
public void setClock();
/**
* Configure this terminal to generate a DDR clock. This sets
* the pattern to be alternating 1's and 0's, and mode to be
* Non-return to zero. The clock transistions to high at time 0,
* and then transistions to the opposite voltage every period
* multiple thereafter.
* You will still need to set the voltage and delay (if any).
*/
public void setDDRClock();
/**
* Add the name of a pin this terminal connects to.
* A terminal can connect to several pins by shorting them together.
* @param pinName the pin name
*/
public void addPinName(String pinName);
/**
* Many terminal outputs both True and Complement.
* This adds the name of a the complement terminal connects to.
* A terminal can connect to several pins by shorting them together.
* @param pinName the pin name
*/
public void addPinNameComplement(String pinName);
/**
* Get the names of pins connected to the true output
* of this terminal (String iterator).
* @return Iterator over pin names.
*/
public Iterator getPinNames();
/**
* Get the names of pins connected to the complement output
* of this terminal (String iterator).
* @return Iterator over pin names in complement output.
*/
public Iterator getPinNamesComplement();
/**
* Clear all pin assignments (both true and complement).
*/
public void clearPins();
/**
* Set the voltage driven by Data Generator. Note the complement
* is only a complement value, so the voltage is never negative.
* @param voltageLow the voltage for a logic low value
* @param voltageHigh the voltage for a logic high value
*/
public void setVoltage(double voltageLow, double voltageHigh);
/**
* Enable or disable complement signal
* @param enable true to enable, false to disable
*/
public void enableComplement(boolean enable);
}
/**
* A Data Analyzer is a terminal that acquires/analyzes data.
* It can be used in conjunction with a {@link DataGenerator}
* to do bit error rate testing.
*/
public interface DataAnalyzer extends Terminal {
/**
* Set the delay before starting to acquire data. The delay
* is the sum of a number of periods (frequency set by the parent Module)
* plus some number of absolute nanoseconds.
* @param periods the number of periods
* @param ns the number of nanoseconds
*/
public void setDelay(int periods, double ns);
/**
* Measure the Bit Error Rate using expected data from the
* given data generator. Any delay set on the generator is
* added to the delay set on this Analyzer.
* @param expectedData
*/
public void measureBER(DataGenerator expectedData);
/**
* Get the Bit Error Rate measured the last time
* the BERT was run. If the analyzer was not
* configured to measure the BER from a DataGenerator,
* this returns zero.
* @return the Bit Error Rate (num failed / num tested)
*/
public double getMeasuredBER();
/**
* Set the name of the pin this terminal connects to.
* @param pinName the pin name
*/
public void setPinName(String pinName);
/**
* Get the name of the pin this terminal connects to.
* @return the pin this analyzer is connected to
*/
public String getPinName();
/**
* Set the voltage thresholds for distinguishing a logic low
* and logic high value.
* @param voltageLowThreshold voltages below this value will be considered logic low
* @param voltageHighThreshold voltages above this value will be considered logic high
*/
public void setVoltageThreshold(double voltageLowThreshold, double voltageHighThreshold);
/**
* Return a BitVector representing the captured data
* @return the BitVector of the captured data.
*/
public BitVector getCapturedData();
}
// ----------------------------------------------------------
public static class StringComparator implements Comparator {
public int compare(Object o1, Object o2) {
String s1 = (String)o1;
String s2 = (String)o2;
return s1.compareTo(s2);
}
}
public static class SignalMode {
private final String name;
private SignalMode(String n) { name = n; }
public String toString() { return name; }
}
/**
* All data tends to be Non-return to zero. The signal does not
* change until the next bit in the pattern.
*/
public static final SignalMode NONRETURNTOZERO = new SignalMode("Non-Return to Zero");
/**
* Return to Zero signals return to zero halfway through the period.
* A clock signal can be generated with a pattern of all 1's, if it
* uses return to zero.
*/
public static final SignalMode RETURNTOZERO = new SignalMode("Return to Zero");
}