/* -*- tab-width: 4 -*-
*
* Electric(tm) VLSI Design System
*
* File: Netscan4Driver.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;
/**
* Low-level drvier providing initialization, configuration, and connection for
* all four ports on Corelis NETUSB-1149.1/E boundary scan controller (JTAG
* tester device). Shifting data in and out should instead be performed using
* {@link ChainControl}. Class is static and non-instantiable.
*/
class Netscan4Driver extends Logger {
/** Minumum allowed value of the JTAG port (TAP) parameter */
public static final int MIN_TAP = 1;
/** Maximum allowed value of the JTAG port (TAP) parameter */
public static final int MAX_TAP = 4;
/** Number of GPIO pins per JTAG port (TAP) */
public static final int NUM_OUTPUT_PINS = 3;
/** Identifier for accessing GPIO in output mode */
public static final int POD_IO_OUTPUT = 0x01;
/** Identifiers for the 3 GPIO pins */
public static final int POD_GPIO[] = new int[] { 0x0D, 0x0E, 0x0F };
/** IP address of JTAG tester. */
private static String addressIP;
/** Number of ports in use on the Netscan4 device. */
private static int numPortsRegistered = 0;
/** Suppress default constructor to make class non-instantiable */
private Netscan4Driver() {
}
/**
* Registers to use a port on the Netscan4 JTAG tester and, if it hasn't
* done so already, connects to it by using the NetUSB_Connect routine in
* the scan function library. The Corelis Netscan SFL library only supports
* one JTAG tester at a time, a restriction we enforce in Java for better
* error messages. The tester must then be configured before use, by calling
* {@link #configure}.
*
* @param addressIP
* IP address of JTAG tester
*/
static void registerPort(String addressIP, int jtagPort) {
checkJtagPort(jtagPort);
numPortsRegistered++;
// If already connected to the device, we can return
if (Netscan4Driver.addressIP != null) {
if (addressIP.equals(Netscan4Driver.addressIP)) {
return;
}
Infrastructure.fatal("Attempt to connect to Netscan4 at IP"
+ " address " + addressIP + ", when one at "
+ Netscan4Driver.addressIP
+ " is already connected. Corelis Netscan SFL"
+ " library only supports one JTAG tester at a time");
}
Netscan4Driver.addressIP = addressIP;
NetscanGeneric.incrementNumTesters();
// Connect to tester via ethernet
Logger.logInit("Connecting to Netscan4 at " + addressIP);
int status = Netscan4JNI.netUSB_Connect(addressIP);
if (status <= 0) {
Infrastructure.fatal("Netscan4JNI.net_connect returned error code "
+ status);
}
}
/**
* Check if jtagPort is in the allowed range. Routine should be overridden
* if multiple ports are supported.
*
* @param jtagPort
* proposed port on the JTAG tester
*/
static void checkJtagPort(int jtagPort) {
if (jtagPort < MIN_TAP || jtagPort > MAX_TAP) {
Infrastructure.fatal("JTAG port number " + jtagPort
+ " not in allowed range " + MIN_TAP + ".." + MAX_TAP);
}
}
/**
* Configures the JTAG tester, setting its parameters, and resets the JTAG
* controller (clears TRSTb briefly). Can be run at any time after
* initialization to change settings.
*
* @param tapVolt
* signal (TAP) voltage in Volts
* @param kiloHerz
* the TCK frequency in kHz (from 391 kHz to 40 MHz)
* @param logger
* Object with logging properties to use
*/
static void configure(float tapVolt, long kiloHerz, Logger logger) {
int milliVolt = Math.round(tapVolt * 1000.f);
logger.logSet("Netscan4 configuring " + kiloHerz + " kHz and "
+ milliVolt + " mV");
int status = Netscan4JNI.netUSB_hard_reset(kiloHerz, milliVolt);
// N.B.: For some reason, Corelis used ZERO for the ERROR condition!
if (status == 0)
Infrastructure.fatal("Netscan4JNI.netUSB_hard_reset returned "
+ status);
status = Netscan4JNI.netUSB_set_scan_clk(kiloHerz);
if (status != 0)
Infrastructure.fatal("Netscan4JNI.netUSB_set_scan_clk returned "
+ status);
// Reset the JTAG controller
reset();
}
/**
* Return the IP address of the Netscan4
*
* @return Returns the IP address of the Netscan4
*/
static String getAddressIP() {
return addressIP;
}
/**
* Reset the finite state machine of the chip's JTAG controller by briefly
* setting the TRSTb signal <tt>LO</tt>. The IR becomes bypass
* automatically.
*/
static void reset() {
int status = Netscan4JNI.netUSB_set_trst(0);
if (status != 0)
Infrastructure
.fatal("Netscan4JNI.net_set_trst(0) returned error code "
+ status);
status = Netscan4JNI.netUSB_set_trst(1);
if (status != 0)
Infrastructure
.fatal("Netscan4JNI.net_set_trst(1) returned error code "
+ status);
}
/**
* Reset the finite state machine of the chip's JTAG controller by briefly
* setting the TMS signal <tt>HI</tt> for five cycles. The IR becomes bypass
* automatically.
*/
static void tms_reset(int jtagPort) {
int status = Netscan4JNI.netUSB_tms_reset(jtagPort);
if (status != 0)
Infrastructure
.fatal("Netscan4JNI.net_tms_reset("+jtagPort+") returned error code "
+ status);
}
/**
* Deregisters to use a port on the JTAG tester. If no more ports are
* registered, disconnect from the JTAG tester. Should be called for each
* registered port before exiting JVM.
*/
static void deregisterPort() {
numPortsRegistered--;
if (numPortsRegistered == 0) {
int status = Netscan4JNI.netUSB_Disconnect();
if (status != 0) {
Infrastructure.fatal("Netscan4JNI.net_disconnect() "
+ "returned error code " + status);
}
}
}
/**
* Write the bits <code>scanIn</code> to the JTAG controller's instruction
* register. The first bit scanned in to the chip is the LSB of
* <code>scanIn[0]</code>, and the first bit scanned out from the chip is
* the LSB of <code>scanOut[0]</code>.
*
* @param jtagPort
* TAP port to use
* @param numBits
* The number of bits to shift
* @param scanIn
* Bit sequence to write to instruction register
* @param scanOut
* Bits scanned out of instruction register
* @param logger
* Object with logging properties to use
*
* @return 0x00 (success), 0x11 (transmit error), 0x33 (receive error)
*/
protected static int hw_net_scan_ir(int jtagPort, int numBits,
short[] scanIn, short[] scanOut, Logger logger) {
checkJtagPort(jtagPort);
logger.logOther("IR into TAP " + jtagPort + ": # shorts="
+ scanIn.length + ", # bits="+ numBits+", " + NetscanGeneric.shortsToString(scanIn));
int result = Netscan4JNI.netUSB_scan_ir(scanIn, numBits, scanOut, jtagPort);
logger.logOther("IR out: # shorts=" + scanOut.length + ", "
+ NetscanGeneric.shortsToString(scanOut));
return result;
}
/**
* Write the bits <code>scanIn</code> to the JTAG controller's data
* register, and read back the bits <code>scanOut</code>. The first bit
* scanned in to the chip is the LSB of <code>scanIn[0]</code>, and the
* first bit scanned out from the chip is the LSB of <code>scanOut[0]</code>.
*
* @param jtagPort
* TAP port to use
* @param numBits
* The number of bits to shift
* @param scanIn
* Bit sequence to write to data register
* @param scanOut
* Bits scanned out of data register
* @param logger
* Object with logging properties to use
*
* @return 0x00 (success), 0x11 (transmit error), 0x33 (receive error)
*/
protected static int hw_net_scan_dr(int jtagPort, int numBits,
short[] scanIn, short[] scanOut, Logger logger) {
checkJtagPort(jtagPort);
logger.logOther("DR into TAP " + jtagPort + ": # shorts="
+ scanIn.length + ", " + NetscanGeneric.shortsToString(scanIn));
logger.logOther(" lentgth=" + numBits);
int result = Netscan4JNI.netUSB_scan_dr(scanIn, numBits,
scanOut, jtagPort);
logger.logOther("DR out: # shorts=" + scanOut.length + ", "
+ NetscanGeneric.shortsToString(scanOut));
return result;
}
/** Checks if parallel I/O port and index are in the allowed ranges */
static void checkGpioID(int jtagPort, int index) {
Netscan4Driver.checkJtagPort(jtagPort);
if (index < 0 || index >= POD_GPIO.length) {
Infrastructure.fatal("Index " + index + " not in allowed range 0.."
+ (POD_GPIO.length - 1));
}
}
/**
* Set the logic level for a single channel of the parallel programmable
* output signals from the JTAG tester to the chip.
*
* @param jtagPort
* Which JTAG port ({@link #MIN_TAP}..{@link #MAX_TAP}) to
* set output on
* @param index
* Which of the TAP's parallel outputs (0..2) to set
* @param newLevel
* set parallel output <tt>HI</tt>?
*/
static void setParallelIO(int jtagPort, int index, boolean newLevel) {
checkGpioID(jtagPort, index);
int value;
if (newLevel) {
value = 1;
} else {
value = 0;
}
int status = Netscan4JNI.netUSB_AccessScanGPIO(jtagPort,
POD_GPIO[index], POD_IO_OUTPUT, value);
if (status != 0) {
Infrastructure
.fatal("net_access_gpio returned error code" + status);
}
}
}