/* -*- tab-width: 4 -*-
*
* Electric(tm) VLSI Design System
*
* File: PowerChannel.java
* Written by Tom O'Neill, Sun Microsystems.
*
* Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
*
* 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;
/**
* Abstract class allowing generic control of a single power supply channel,
* independent of the nature of the power supply. Primarily used for controlling
* chip V_DD.
*/
public abstract class PowerChannel extends Logger implements CurrentReadable,
VoltageReadable {
/**
* Maximum allowed delay in milliseconds for voltage to reach within the
* power supply's voltage resolution.
*/
public long maxSettleMsec = 4000;
/** Delay between each voltage check in {@link #waitForVoltage}. */
public float settleResolution = 0.1f;
/** Default voltage resolution for power supply */
public static final float DEFAULT_VOLTAGE_RESOLUTION = 0.01f;
/* Name of the signal on this power supply channel */
protected String name;
/** Obsolete, use getState() instead */
public String toString() {
Infrastructure
.nonfatal("Please change toString() reference to getState()");
return getName();
}
/**
* Returns the name and state (voltage, current) of the channel
*
* @return the name and state of the channel
*/
public String getState() {
return getName() + ": " + readVoltage() + " V, " + readCurrent() + " A";
}
/**
* Returns the name of the signal on this channel of the power supply (e.g.,
* vdd, master clear, etc.)
*
* @return the name of the signal on this power supply channel
*/
public String getName() {
return name;
}
/**
* Measures the voltage on this channel of the power supply
*
* @return voltage provided on this channel, in Volts
*/
public abstract float readVoltage();
/**
* Get the channel's voltage setpoint
*
* @return voltage setpoint for the channel, in Volts
*/
public abstract float getVoltageSetpoint();
/**
* Returns voltage resolution of power supply, if known. Otherwise returns a
* "safe" typical value.
*
* @return voltage resolution of power supply
*/
public float getVoltageResolution() {
return DEFAULT_VOLTAGE_RESOLUTION;
}
/**
* Set the channel's voltage to the value provided
*
* @param volts
* new voltage for the channel, in Volts
*/
public abstract void setVoltageNoWait(float volts);
/**
* Set the channel's voltage and wait until it reaches requested value.
*
* @param volts
* new voltage for the channel, in Volts
*/
public void setVoltageWait(float volts) {
setVoltageNoWait(volts);
waitForVoltage(volts);
}
/**
* Waits until voltage measured on the channel is equal to setVolts within
* the resolution of the power supply. Issues a fatal error if voltage error
* exceeds resolution after MAX_SETTLE_MSEC milliseconds have elapsed.
*/
public void waitForVoltage(float setVolts) {
long startTime = java.lang.System.currentTimeMillis();
long endTime;
float gotV;
// Multiply by 1.001f to allow for rounding issues
float voltsErr = 1.001f * getVoltageResolution();
// Wait until voltage within allowed range, or maximum
// settling time has elapsed.
do {
boolean checkedSetpoint = false;
try { Thread.sleep( (int)(1000 * settleResolution) ); } catch (InterruptedException _) { }
gotV = readVoltage();
if (Math.abs(gotV - setVolts) <= voltsErr) {
logOther(" " + getName() + ".waitForVoltage(): achieved "
+ gotV + " V");
return;
}
if (checkedSetpoint == false) {
checkedSetpoint = true;
float setpoint = getVoltageSetpoint();
if (Math.abs(setpoint - setVolts) > (1.0001 * getVoltageResolution())) {
Infrastructure.fatal(this.getName()
+ ".waitForVoltage: requested setpoint is "
+ setVolts + " V, but actual setpoint is "
+ setpoint + ". Voltage is " + gotV
+ " V and current is " + readCurrent() + " A.");
}
}
try { Thread.sleep( (int)(1000 * settleResolution) ); } catch (InterruptedException _) { }
endTime = java.lang.System.currentTimeMillis();
} while ((endTime - startTime) <= maxSettleMsec);
Infrastructure.fatal(this.getName()
+ ".waitForVoltage: requested setpoint is " + setVolts
+ " V, but voltage is " + gotV + " V after "
+ (endTime - startTime) + " msec. Actual setpoint is "
+ getVoltageSetpoint() + " V. Current is " + readCurrent()
+ " A, setpoint is " + getCurrentSetpoint() + " A.");
}
/**
* Set the channel's current limit to the value provided
*
* @param amps
* new current limit for the channel, in Amps
*/
public abstract void setCurrent(float amps);
/**
* Get the channel's current limit setpoint
*
* @return current limit setpoint for the channel, in Amps
*/
public abstract float getCurrentSetpoint();
/**
* Measures current using range appropriate for <code>ampsExpected</code>,
* and resolution of <code>ampsResolution</code>. Supplies that allow
* range setting should override this default implementation.
*
* @param ampsExpected
* expected value of current in amps, for range setting
* @param ampsResolution
* desired resolution for measurement, in amps
* @return current in Amps
*/
public float readCurrent(float ampsExpected, float ampsResolution) {
System.err.println("WARNING: " + getName()
+ " does not support manual range and resolution setting");
return readCurrent();
}
/**
* Measures the current on this channel of the power supply
*
* @return current drawn over this channel, in Amps
*/
public abstract float readCurrent();
}