home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Hack-Phreak Scene Programs
/
cleanhpvac.zip
/
cleanhpvac
/
FPGAWKII.ZIP
/
JTAG.C
< prev
next >
Wrap
C/C++ Source or Header
|
1995-04-10
|
39KB
|
1,211 lines
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <stdarg.h>
#include <conio.h>
#include <malloc.h>
#include "jtag.h"
/* BITSTREAM-HANDLING SUBROUTINES */
/*
* RTN AllocBits: allocates a bitstream containing at least NumBits.
*/
bitstream *AllocBits( int NumBits )
{
int i, WordLength, NumWords;
bitstream *bits;
/* compute the number of bitstream words needed to store the
requested number of bits */
WordLength = 8 * sizeof(bitstream) / sizeof(char);
NumWords = (NumBits-1)/WordLength + 1;
/* let's see if we can allocate the bitstream storage */
if( (bits=NEWV(bitstream, NumWords)) == NULL )
{
/* Oops! Guess not! */
fprintf( stderr, "Out of memory; can't create bitstream\n" );
assert(0==1); /* this will cause an abort */
}
/* otherwise, we have the storage so we need to initialize it */
for( i=0; i<NumWords; i++ )
bits[i] = 0; /* make it all zeroes */
return( bits ); /* return a pointer to the bitstream storage */
}
/*
* RTN FreeBits: free the storage used by a bitstream.
*/
void FreeBits( bitstream *bits )
{
FREE( bits );
}
/*
* RTN GetBit: gets the value of a bit from a bitstream.
*/
unsigned int GetBit( bitstream *bits, int i )
{
int WordLength, WordIndex, BitIndex;
/* calculate the number of bits in a bitstream data word
and use this to calculate what word and bit position in
that word the requested bit lies in. */
WordLength = 8 * sizeof(bitstream) / sizeof(char);
WordIndex = i / WordLength;
BitIndex = i % WordLength;
/* now get the word and shift it so the requested bit is in the LSB.
Then mask off the reset and return just a 1 or a 0. */
return (unsigned int)((bits[WordIndex]>>BitIndex) & 1L);
}
/*
* RTN SetBit: sets the value of a bit in a bitstream
*/
void SetBit( bitstream *bits, int i, int val )
{
int WordLength, WordIndex;
bitstream BitMask;
/* calculate the number of bits in a bitstream data word
and use this to calculate what word the requested bit lies in
and to generate a bitmask to mask off that bit. */
WordLength = 8 * sizeof(bitstream) / sizeof(char);
WordIndex = i / WordLength;
BitMask = 1L << (i % WordLength);
/* now use the bitmask to force the requested bit to zero */
bits[WordIndex] &= ~BitMask;
/* and then set the requested bit to one if that's needed.
Otherwise leave it at zero. */
if( val )
bits[WordIndex] |= BitMask;
}
/*
* RTN CmpBits: mask two bitstreams and then XOR them.
*
* This routine compares selected bits of two bitstreams of the same
* length and places the XOR of them into a result bitstream.
* Any 1 bits in the result indicate places where the bitstreams differ.
*/
void CmpBits( int length, bitstream *b1, bitstream *b2,
bitstream *mask, bitstream *result )
{
int i, WordLength, WordIndex, MaxWord;
/* compute the number of bitstream data words in the bitstreams */
WordLength = 8 * sizeof(bitstream) / sizeof(char);
MaxWord = (length+WordLength) / WordLength;
/* XOR the bitstreams and store a 1 in the result anywhere the
two bitstreams differ and the mask is non-zero. */
for( i=0; i<MaxWord; i++ )
result[i] = (b1[i] ^ b2[i]) & mask[i];
}
/*
* RTN PrintBits: prints a bitstream to the standard output.
*/
void PrintBits( bitstream *bits, int length )
{
int i;
/* start printing with the MSB which is stored at the
end of the bitstream. Then work your way to the beginning. */
for( i=length-1; i>=0; i-- )
printf( "%c", GetBit(bits,i) ? '1':'0' );
printf( "\n" );
}
/* LOW-LEVEL PRINTER PORT SUBROUTINES */
/* We have to store the value we are currently outputing
through the parallel port since we can't reliably read it back. */
static int OutPortValue=0xffff;
/* We may want to delay the transitions of signals through the
printer port if we are going too fast for reliable data transfer. */
static int PortDelay=0; /* start off with the maximum speed */
/* Here we will store the output and input addresses for the printer port. */
static int OutPort=0; /* the 0 address will alert us that these */
static int InPort =0; /* addresses are not initialized yet */
/*
* RTN SelectPort: select the printer port the JTAG signals go thru.
*
* Pass in either 1, 2, or 3 since most PCs support up to three
* printer ports. The subroutine will warn you if you pick a
* non-existent port.
*/
void SelectPort( int PortNum )
{
int PortAddresses[4]; /* storage for the printer port addresses */
PortAddresses[3] = 0; /* store a dummy, non-existent port address
in the final location of the array */
if( PortNum<1 || PortNum>3 )
PortNum = 4; /* invalid port #, so set to dummy port # */
/* get the parallel port addresses stored in memory
starting at memory address 0x408 and move them to the
PortAddresses array. Move the only the first six bytes so the final
entry in PortAddresses will still be zero. */
_asm{
mov ax,0x0
mov es,ax
mov bx,es:0x408
mov PortAddresses[0],bx
mov bx,es:0x40a
mov PortAddresses[2],bx
mov bx,es:0x40c
mov PortAddresses[4],bx
}
/* now get the port I/O address for the requested printer port # */
OutPort = PortAddresses[PortNum-1];
InPort = OutPort+1; /* the input address is always at the
output address + 1 */
/* the requested printer port doesn't exist if the
port address is 0 */
if( OutPort==0 )
{
fprintf( stderr, "The requested printer port does not exist!\n" );
assert(0==1);
}
}
/*
* RTN PortWait: delay for letting the output port signals settle.
*/
void PortWait( void )
{
int i;
for( i=PortDelay; i>0; i-- ) ;
}
/*
* RTN SetPortDelay: sets the time for letting the printer port settle.
*/
void SetPortDelay( int delay )
{
PortDelay = delay;
}
/*
* RTN OutToPort: output a value to the selected printer port.
*/
void OutToPort( int val )
{
/* if a valid printer port has not been selected, then we'll
select printer port 1 by default */
if( OutPort==0 )
SelectPort(1);
/* output the value to the printer port and save the value
that is being put out */
outp( OutPort, val );
OutPortValue = val;
/* {
bitstream b = OutPortValue;
PrintBits( &b, 32 );
} */
/* insert a delay after the output value is changed */
PortWait();
}
/*
* RTN GetOutportValue: get the value currently being output on the
* printer port.
*/
int GetOutPortValue( void )
{
return OutPortValue;
}
/*
* RTN InFromPort: return a value from the selected printer port.
*/
int InFromPort( void )
{
/* if a valid printer port has not been selected, then we'll
select printer port 1 by default */
if( InPort==0 )
SelectPort(1);
/* read the value from the status portion of the selected
printer port and return it */
return( inp( InPort) );
}
/* TAP INTERFACE SUBROUTINES */
/* PC parallel port assignments to TAP pins */
/* Remember! TDO is the bit we put OUT from the PC printer port
to the TDI pin of the attached chip. TDI is the bit we read
IN from the TDO pin of the attached chip. In other words, the
names refer to the simulated TAP of the PC printer port, not to
the TAP of the attached chip. */
#define TCKBIT 0
#define TMSBIT 1
#define TDOBIT 6
#define TDIBIT 7
/*
* RTN SetPortBit: sets a bit of the port to a given value
*/
void SetPortBit( int bit, int val )
{
/* create a masking pattern for the bit */
unsigned int mask = 1<<bit;
/* set the bit value to 0 */
int NewValue = GetOutPortValue() & ~mask;
/* now set it to 1 if the val is non-zero */
if( val )
NewValue |= mask;
/* now output the updated port value */
OutToPort( NewValue );
}
/*
* RTN GetPortBit: gets the value (0 or 1) of a bit of the port.
*/
unsigned int GetPortBit( int bit )
{
return (GetOutPortValue()>>bit) & 1;
}
/*
* RTN SetTMSValue: sets the value of the TMS bit on the TAP.
*/
void SetTMSValue( int val )
{
SetPortBit( TMSBIT, val );
}
/*
* RTN GetTMSValue: returns the value of the TMS bit on the TAP.
*/
unsigned int GetTMSValue( void )
{
return GetPortBit( TMSBIT );
}
/*
* RTN SetTDOValue: sets the value of the TDO bit on the JTAG port.
*/
void SetTDOValue( int val )
{
SetPortBit( TDOBIT, val );
}
/*
* RTN GetTDOValue: gets the value of the TDO bit on the JTAG Port
*/
unsigned int GetTDOValue( void )
{
return GetPortBit( TDOBIT );
}
/*
* RTN GetTDIValue: gets the value of the TDI bit from the input port
* which is fed from the TDO bit of the TAP port of the
* attached chip.
*/
unsigned int GetTDIValue( void )
{
return ((InFromPort()>>TDIBIT) & 1) ^ 1;
}
/*
* RTN GetTCKValue: gets the value of the TCK bit on the output port.
*/
unsigned int GetTCKValue( void )
{
return GetPortBit( TCKBIT );
}
/*
* RTN SetTCKValue: sets the value of the TCK bit on the output port.
*/
void SetTCKValue( int val )
{
SetPortBit( TCKBIT, val );
}
/*
* RTN JTAGTraceOnOff: enables/disables the trace of TAP signals coming
* out the printer port.
*/
static int JTAGTraceFlag = 0; /* start up with trace disabled */
JTAGTraceOnOff( int OnOff )
{
JTAGTraceFlag = OnOff;
}
/*
* RTN PulseTCK: put a pulse on the TCK pin by toggling TCK twice.
*/
char *GetTAPStateText(); /* a declaration so we can use this routine */
void PulseTCK( void )
{
/* get the original value of TCK */
int OldTCK = GetTCKValue();
if( JTAGTraceFlag )
printf( "%s\t%1d %1d %1d\n", GetTAPStateText(),
GetTMSValue(), GetTDOValue(), GetTDIValue() );
/* now toggle it to its opposite value ... */
SetTCKValue( OldTCK ^ 1 );
/* and then return it to its original value */
SetTCKValue( OldTCK );
/* now make a check that TCK is 0. This is the normal
quiescent value for our system. */
assert( OldTCK==0 );
}
/*
* RTN JTAGPortInit: initialize the JTAG port output value.
*/
void JTAGPortInit( void )
{
SetTMSValue(1);
SetTCKValue(0);
HardTAPReset();
}
/* TAP CONTROLLER TRANSITION SUBROUTINES */
/* TAP controller state definitions */
typedef enum
{
TestLogicReset, RunTestIdle,
SelectDRScan, SelectIRScan,
CaptureDR, CaptureIR,
ShiftDR, ShiftIR,
Exit1DR, Exit1IR,
PauseDR, PauseIR,
Exit2DR, Exit2IR,
UpdateDR, UpdateIR
} JTAGState;
#define NumTAPStates 16 /* number of TAP controller states */
/* This variable records the current state of TAP controller */
static JTAGState CurrentTAPState = TestLogicReset;
/* The following array stores the transition table for the TAP
controller. It tells us what the next state will be by placing the
current state code in the first index and the value of
the TMS input in the second index. */
static JTAGState NextTAPState[NumTAPStates][2] =
{
/* TMS=0 */ /* TMS=1 */ /* current TAP state */
{ RunTestIdle, TestLogicReset }, /* TestLogicReset */
{ RunTestIdle, SelectDRScan }, /* RunTestIdle */
{ CaptureDR, SelectIRScan }, /* SelectDRScan */
{ CaptureIR, TestLogicReset }, /* SelectIRScan */
{ ShiftDR, Exit1DR }, /* CaptureDR */
{ ShiftIR, Exit1IR }, /* CaptureIR */
{ ShiftDR, Exit1DR }, /* ShiftDR */
{ ShiftIR, Exit1IR }, /* ShiftIR */
{ PauseDR, UpdateDR }, /* Exit1DR */
{ PauseIR, UpdateIR }, /* Exit1IR */
{ PauseDR, Exit2DR }, /* PauseDR */
{ PauseIR, Exit2IR }, /* PauseIR */
{ ShiftDR, UpdateDR }, /* Exit2DR */
{ ShiftIR, UpdateIR }, /* Exit2IR */
{ RunTestIdle, SelectDRScan }, /* UpdateDR */
{ RunTestIdle, SelectDRScan }, /* UpdateIR */
};
/*
* RTN TAPStateToText: converts the TAP controller state into its
* textual name.
*/
char *TAPStateToText( JTAGState TAPState )
{
switch( TAPState )
{
case TestLogicReset: return "Test-Logic-Reset";
case RunTestIdle: return "Run-Test/Idle";
case SelectDRScan: return "Select_DR-Scan";
case SelectIRScan: return "Select_IR-Scan";
case CaptureDR: return "Capture-DR";
case CaptureIR: return "Capture-IR";
case ShiftDR: return "Shift-DR";
case ShiftIR: return "Shift-IR";
case Exit1DR: return "Exit1-DR";
case Exit1IR: return "Exit1-IR";
case PauseDR: return "Pause-DR";
case PauseIR: return "Pause-IR";
case Exit2DR: return "Exit2-DR";
case Exit2IR: return "Exit2-IR";
case UpdateDR: return "Update-DR";
default:
case UpdateIR: return "Update-IR";
}
}
/*
* RTN HardTAPReset: guarantees the TAP controller is in
* Test-Logic-Reset state.
*/
void HardTAPReset( void )
{
CurrentTAPState = TestLogicReset;
/* the TAP controller will always be reset by raising TMS to 1
and then pulsing the TCK five times */
SetTMSValue(1);
PulseTCK();
PulseTCK();
PulseTCK();
PulseTCK();
PulseTCK();
}
/*
* RTN UpdateTAPState: use the current TAP controller state and TMS
* bit to compute the next TAP controller state.
*
* This routine keeps the copy of the TAP controller state in the
* program up-to-date with the TAP controller state in the chip
* (we hope).
*/
void UpdateTAPState( void )
{
CurrentTAPState = NextTAPState[ CurrentTAPState ][ GetTMSValue() ];
}
char *GetTAPStateText( void )
{
return TAPStateToText(CurrentTAPState);
}
/*
* RTN GotoNextTAPState: sets the TMS line to the appropriate value
* such that the next TCK pulse will move the TAP controller
* to the requested NextState.
*
* If the new state of the TAP controller doesn't match the requested
* state, the subroutine will cause the program to abort.
*/
char *TAPStateToText( JTAGState s );
void GotoNextTAPState( JTAGState NextState )
{
/* determine the correct TMS value to move to the desired state */
if( NextTAPState[CurrentTAPState][0] == NextState )
SetTMSValue(0);
else /* ( NextTAPState[CurrentTAPState][1] == NextState ) */
SetTMSValue(1);
/* now transition the chip TAP controller to the new state */
PulseTCK();
/* update the internal copy of the TAP controller state */
UpdateTAPState();
/* check to make sure the current state matches what was requested */
assert( CurrentTAPState==NextState );
}
/*
* RTN GoThruTAPSequence: moves through a sequence of TAP controller states.
*
* The desired TAP controller state sequences is entered as an argument
* string terminated with a -1.
*/
void GoThruTAPSequence( JTAGState NextState, ... )
{
/* progress through the states until a -1 is seen */
va_list ap;
for( va_start(ap,NextState); NextState != -1;
NextState=va_arg(ap,JTAGState) )
GotoNextTAPState( NextState );
va_end( ap );
}
/* BSDR and BSIR INPUT/OUTPUT SUBROUTINES */
/*
* RTN SendRcvBit: get the current bit from TDI, send a bit through TDO,
* and pulse TCLK.
*
* This subroutine assumes that the TCK is 0 and the TAP controller state
* is Shift-DR or Shift-IR upon entry. That's why we pick up the value
* coming in through TDI right away.
*/
unsigned int SendRcvBit( unsigned SendBit )
{
unsigned int TDIValue;
/* Make sure we are in the Shift-IR or Shift-DR state. Gathering
and shifting out data isn't legal otherwise. */
assert( CurrentTAPState==ShiftIR || CurrentTAPState==ShiftDR );
/* get the value on the TDI input when TCK is low */
TDIValue = GetTDIValue();
/* now output the specified value on TDO */
SetTDOValue( SendBit & 1 );
/* pulse TCK to move the BSIR or BSDR by one bit */
PulseTCK(); /* clock goes high then low */
/* update the current TAP controller state */
UpdateTAPState();
/* return the value we captured off TDI */
return TDIValue;
}
/*
* RTN SendRcvBitstream: transmit a bitstream through TDO while receiving
* a bitstream through TDI.
*
* This subroutine assumes the TAP controller state is
* Shift-IR or Shift-DR upon entry. Upon termination, this subroutine
* will leave the TAP controller in the Exit1-IR or Exit1-DR state.
*
* Either SendBits or RcvBits can be NULL if you don't want to transmit
* or receive bits during a particular call to this subroutine.
* For example, you may want to load the BSDR with a bit pattern but
* you might not care what data gets shifted out of the BSDR during
* the loading.
*
* SendBits and RcvBits can point to the same bitstream without
* causing problems.
*
* Note that the LSB of a bitstream has an index of 0.
*/
void SendRcvBitstream( int length, bitstream *SendBits, bitstream *RcvBits )
{
int i, j, WordLength, NumWords;
bitstream SendWord;
/* compute the number of words in the bitstream */
WordLength = 8 * sizeof(bitstream)/sizeof(char);
/* it's nonsense to operate on a zero-length bitstream, so
abort if that's the case. */
assert( length>0 );
/* lower the TMS line to make sure the TAP controller stays
in the Shift-IR or Shift-DR state for the first length-1 cycles */
SetTMSValue(0);
for( i=0; i<length; i++ )
{
unsigned int sendbit, rcvbit;
/* On the last bit, raise the TMS line so the TAP
controller will move out of the Shift state into
the Exit1 state. */
if( i==length-1 )
SetTMSValue(1);
/* send the next bit if the bitstream is not NULL ... */
if( SendBits!=NULL )
rcvbit = SendRcvBit(GetBit(SendBits,i));
/* else just shift in a zero */
else
rcvbit = SendRcvBit(0);
/* store the received bit if the bitstream is not NULL */
if( RcvBits!=NULL )
SetBit( RcvBits, i, rcvbit );
}
}
/*
* RTN LoadBSIRthenBSDR: load the BSIR, execute the instruction, and
* then capture and reload the BSDR.
*
* This subroutine assumes the TAP controller is in the Test-Logic-Reset
* or Run-Test/Idle state upon entry. The TAP controller is returned to the
* Run-Test/Idle state upon exit.
*/
void LoadBSIRthenBSDR( int BSIRLength, bitstream *instruction,
int BSDRLength, bitstream *send, bitstream *recv )
{
/* move the TAP controller from the Test-Logic-Reset or
Run-Test/Idle state to the Shift-IR state */
GoThruTAPSequence( RunTestIdle, SelectDRScan,
SelectIRScan, CaptureIR, ShiftIR, -1 );
/* now load the opcode instruction into the BSIR and
enter the Exit1-IR state when this is done */
SendRcvBitstream( BSIRLength, instruction, NULL );
/* now activate the instruction by entering the Update-IR state. */
GoThruTAPSequence( UpdateIR, -1 );
/* if the BSDR length is non-zero, then select the BSDR by moving
into the Capture-DR state so that the new pin data is
parallel-loaded into the BSDR. Then move into the
Shift-DR state so that the captured data can be shifted out
while a new pattern is shifted in. Finally, output the
newly loaded data onto the parallel output of the BSDR by moving
into the Update-DR state. */
if( BSDRLength > 0 )
{
GoThruTAPSequence( SelectDRScan, CaptureDR, ShiftDR, -1 );
/* now shift out the captured data while
new data is shifted in */
SendRcvBitstream( BSDRLength, send, recv );
/* output the freshly loaded data onto the parallel output
of the BSDR */
GoThruTAPSequence( UpdateDR, -1 );
}
/* return to the idle state */
GoThruTAPSequence( RunTestIdle, -1 );
}
/* EPX780 JTAG INSTRUCTION SUBROUTINES */
/* JTAG public instruction opcodes for the EPX780 FPGA */
typedef enum
{
EXTEST = 0, /* drives outputs with pre-loaded data */
SAMPLE = 1, /* read current pins; pre-load next pin state */
IDCODE = 2, /* read manufacturers ID code */
LDVECT = 5, /* load vector into PROGRAM shift register */
FREAD = 6, /* read EPROM */
SWRITE = 15, /* write SRAM */
SREAD = 16, /* read SRAM */
PORST = 20, /* power-on reset; restarts device architecture */
FPGM = 21, /* program EPROM */
HIGHZ = 29, /* 3-state all outputs */
UESCODE = 22, /* shift out user-defined electronic signature code */
RADLOAD = 24, /* load row address */
ISCAN = 30, /* internal scan of device */
BYPASS = 31 /* bypass the device JTAG mechanism */
} EPX780JTAGOpcode;
#define EPX780OpcodeLength 5 /* the bit length of the EPX780 JTAG opcodes */
#define EPX780IDCodeLength 32 /* Device ID code register length */
#define EPX780BSDRLength 264 /* boundary-scan data register length */
#define EPX780UESLength 600 /* user-electronic-signature register length */
/*
* RTN EPX780IDCode: read the manufacturer's Device ID code.
*
* The ID code is stored into the memory pointed to by DeviceIDCode.
*/
void EPX780IDCode( bitstream *DeviceIDCode )
{
bitstream instr = IDCODE;
LoadBSIRthenBSDR( EPX780OpcodeLength, &instr,
EPX780IDCodeLength, NULL, DeviceIDCode );
}
/*
* RTN EPX780UES: read the user-loaded User Electronic Signature.
*
* The signature is stored into the memory pointed to by UESig.
*/
void EPX780UES( bitstream *UESig )
{
bitstream instr = UESCODE;
LoadBSIRthenBSDR( EPX780OpcodeLength, &instr,
EPX780UESLength, NULL, UESig );
}
/*
* RTN EPX780SamplePreload: read current pin state and preload next state.
*
* The BSDR is loaded with the data pointed to by send and the sampled pin
* values shifted out of the BSDR are stored into the memory pointed to
* by recv.
*/
void EPX780SamplePreload( bitstream *send, bitstream *recv )
{
bitstream instr = SAMPLE;
LoadBSIRthenBSDR( EPX780OpcodeLength, &instr,
EPX780BSDRLength, send, recv );
}
/*
* RTN EPX780Extest: drive outputs with preloaded data.
*
* The BSDR is loaded with the new pin values pointed to by send and the
* old pin values shifted out of the BSDR are stored into the memory
* pointed to by recv.
*/
void EPX780Extest( bitstream *send, bitstream *recv )
{
bitstream instr = EXTEST;
LoadBSIRthenBSDR( EPX780OpcodeLength, &instr,
EPX780BSDRLength, send, recv );
}
/*
* RTN EPX780HighZ: tristate all the outputs.
*/
void EPX780HighZ(void)
{
bitstream instr = HIGHZ;
LoadBSIRthenBSDR( EPX780OpcodeLength, &instr, 0, NULL, NULL );
}
/*
* RTN EPX780Bypass: bypass the data register.
*/
void EPX780Bypass(void)
{
bitstream instr = BYPASS;
LoadBSIRthenBSDR( EPX780OpcodeLength, &instr, 0, NULL, NULL );
}
/* EPX780 JTAG BSDR ASSIGNMENTS */
/*
* The following enumeration is the order of the scan cells in the
* BSDR for the EPX780 FPGA (both 84-pin and 132-pin versions).
* We got this from the I780_84.BSD file included with PLDshell.
* The list starts with the LSB and ends with the MSB of the scan path.
* Each macrocell scan cell has three bits associated with it: an
* OE cell which enables the tristate buffer when set to 1, an OUT cell
* whose value is output on the pin when the tristate buffer is enabled,
* and an IN cell which captures the value placed on the pin.
* The CLK1 and CLK2 scan cells are able to capture the values on the clock
* inputs. The IN0..IN21 scan cells can capture the values on the
* dedicated inputs, but these inputs exist only on the 132-pin
* version of the EPX780, not on the 84-pin version.
*/
typedef enum {
IO09OE, IO09OUT, IO09IN,
IO08OE, IO08OUT, IO08IN,
IO07OE, IO07OUT, IO07IN,
IO06OE, IO06OUT, IO06IN,
IO05OE, IO05OUT, IO05IN,
IO04OE, IO04OUT, IO04IN,
IO03OE, IO03OUT, IO03IN,
IO02OE, IO02OUT, IO02IN,
IO01OE, IO01OUT, IO01IN,
IO00OE, IO00OUT, IO00IN,
CLK1,
IO10OE, IO10OUT, IO10IN,
IO11OE, IO11OUT, IO11IN,
IO12OE, IO12OUT, IO12IN,
IO13OE, IO13OUT, IO13IN,
IO14OE, IO14OUT, IO14IN,
IO15OE, IO15OUT, IO15IN,
IO16OE, IO16OUT, IO16IN,
IO17OE, IO17OUT, IO17IN,
IO18OE, IO18OUT, IO18IN,
IO19OE, IO19OUT, IO19IN,
IN0, IN1, IN2, IN3, IN4, IN5,
IO39OE, IO39OUT, IO39IN,
IO38OE, IO38OUT, IO38IN,
IO37OE, IO37OUT, IO37IN,
IO36OE, IO36OUT, IO36IN,
IO35OE, IO35OUT, IO35IN,
IO34OE, IO34OUT, IO34IN,
IO33OE, IO33OUT, IO33IN,
IO32OE, IO32OUT, IO32IN,
IO31OE, IO31OUT, IO31IN,
IO30OE, IO30OUT, IO30IN,
IO50OE, IO50OUT, IO50IN,
IO51OE, IO51OUT, IO51IN,
IO52OE, IO52OUT, IO52IN,
IO53OE, IO53OUT, IO53IN,
IO54OE, IO54OUT, IO54IN,
IO55OE, IO55OUT, IO55IN,
IO56OE, IO56OUT, IO56IN,
IO57OE, IO57OUT, IO57IN,
IO58OE, IO58OUT, IO58IN,
IO59OE, IO59OUT, IO59IN,
IN6, IN7, IN8, IN9, IN10,
IO79OE, IO79OUT, IO79IN,
IO78OE, IO78OUT, IO78IN,
IO77OE, IO77OUT, IO77IN,
IO76OE, IO76OUT, IO76IN,
IO75OE, IO75OUT, IO75IN,
IO74OE, IO74OUT, IO74IN,
IO73OE, IO73OUT, IO73IN,
IO72OE, IO72OUT, IO72IN,
IO71OE, IO71OUT, IO71IN,
IO70OE, IO70OUT, IO70IN,
CLK2,
IO60OE, IO60OUT, IO60IN,
IO61OE, IO61OUT, IO61IN,
IO62OE, IO62OUT, IO62IN,
IO63OE, IO63OUT, IO63IN,
IO64OE, IO64OUT, IO64IN,
IO65OE, IO65OUT, IO65IN,
IO66OE, IO66OUT, IO66IN,
IO67OE, IO67OUT, IO67IN,
IO68OE, IO68OUT, IO68IN,
IO69OE, IO69OUT, IO69IN,
IN11, IN12, IN13, IN14, IN15, IN16,
IO49OE, IO49OUT, IO49IN,
IO48OE, IO48OUT, IO48IN,
IO47OE, IO47OUT, IO47IN,
IO46OE, IO46OUT, IO46IN,
IO45OE, IO45OUT, IO45IN,
IO44OE, IO44OUT, IO44IN,
IO43OE, IO43OUT, IO43IN,
IO42OE, IO42OUT, IO42IN,
IO41OE, IO41OUT, IO41IN,
IO40OE, IO40OUT, IO40IN,
IO20OE, IO20OUT, IO20IN,
IO21OE, IO21OUT, IO21IN,
IO22OE, IO22OUT, IO22IN,
IO23OE, IO23OUT, IO23IN,
IO24OE, IO24OUT, IO24IN,
IO25OE, IO25OUT, IO25IN,
IO26OE, IO26OUT, IO26IN,
IO27OE, IO27OUT, IO27IN,
IO28OE, IO28OUT, IO28IN,
IO29OE, IO29OUT, IO29IN,
IN17, IN18, IN19, IN20, IN21
} EPX780ScanPosition;
/*
* The following array lets us recall the names for each scan cell in the
* EPX780 BSDR.
*/
static char *EPX780ScanPosNames[] = {
"IO09OE", "IO09OUT", "IO09IN",
"IO08OE", "IO08OUT", "IO08IN",
"IO07OE", "IO07OUT", "IO07IN",
"IO06OE", "IO06OUT", "IO06IN",
"IO05OE", "IO05OUT", "IO05IN",
"IO04OE", "IO04OUT", "IO04IN",
"IO03OE", "IO03OUT", "IO03IN",
"IO02OE", "IO02OUT", "IO02IN",
"IO01OE", "IO01OUT", "IO01IN",
"IO00OE", "IO00OUT", "IO00IN",
"CLK1",
"IO10OE", "IO10OUT", "IO10IN",
"IO11OE", "IO11OUT", "IO11IN",
"IO12OE", "IO12OUT", "IO12IN",
"IO13OE", "IO13OUT", "IO13IN",
"IO14OE", "IO14OUT", "IO14IN",
"IO15OE", "IO15OUT", "IO15IN",
"IO16OE", "IO16OUT", "IO16IN",
"IO17OE", "IO17OUT", "IO17IN",
"IO18OE", "IO18OUT", "IO18IN",
"IO19OE", "IO19OUT", "IO19IN",
"IN0", "IN1", "IN2", "IN3", "IN4", "IN5",
"IO39OE", "IO39OUT", "IO39IN",
"IO38OE", "IO38OUT", "IO38IN",
"IO37OE", "IO37OUT", "IO37IN",
"IO36OE", "IO36OUT", "IO36IN",
"IO35OE", "IO35OUT", "IO35IN",
"IO34OE", "IO34OUT", "IO34IN",
"IO33OE", "IO33OUT", "IO33IN",
"IO32OE", "IO32OUT", "IO32IN",
"IO31OE", "IO31OUT", "IO31IN",
"IO30OE", "IO30OUT", "IO30IN",
"IO50OE", "IO50OUT", "IO50IN",
"IO51OE", "IO51OUT", "IO51IN",
"IO52OE", "IO52OUT", "IO52IN",
"IO53OE", "IO53OUT", "IO53IN",
"IO54OE", "IO54OUT", "IO54IN",
"IO55OE", "IO55OUT", "IO55IN",
"IO56OE", "IO56OUT", "IO56IN",
"IO57OE", "IO57OUT", "IO57IN",
"IO58OE", "IO58OUT", "IO58IN",
"IO59OE", "IO59OUT", "IO59IN",
"IN6", "IN7", "IN8", "IN9", "IN10",
"IO79OE", "IO79OUT", "IO79IN",
"IO78OE", "IO78OUT", "IO78IN",
"IO77OE", "IO77OUT", "IO77IN",
"IO76OE", "IO76OUT", "IO76IN",
"IO75OE", "IO75OUT", "IO75IN",
"IO74OE", "IO74OUT", "IO74IN",
"IO73OE", "IO73OUT", "IO73IN",
"IO72OE", "IO72OUT", "IO72IN",
"IO71OE", "IO71OUT", "IO71IN",
"IO70OE", "IO70OUT", "IO70IN",
"CLK2",
"IO60OE", "IO60OUT", "IO60IN",
"IO61OE", "IO61OUT", "IO61IN",
"IO62OE", "IO62OUT", "IO62IN",
"IO63OE", "IO63OUT", "IO63IN",
"IO64OE", "IO64OUT", "IO64IN",
"IO65OE", "IO65OUT", "IO65IN",
"IO66OE", "IO66OUT", "IO66IN",
"IO67OE", "IO67OUT", "IO67IN",
"IO68OE", "IO68OUT", "IO68IN",
"IO69OE", "IO69OUT", "IO69IN",
"IN11", "IN12", "IN13", "IN14", "IN15", "IN16",
"IO49OE", "IO49OUT", "IO49IN",
"IO48OE", "IO48OUT", "IO48IN",
"IO47OE", "IO47OUT", "IO47IN",
"IO46OE", "IO46OUT", "IO46IN",
"IO45OE", "IO45OUT", "IO45IN",
"IO44OE", "IO44OUT", "IO44IN",
"IO43OE", "IO43OUT", "IO43IN",
"IO42OE", "IO42OUT", "IO42IN",
"IO41OE", "IO41OUT", "IO41IN",
"IO40OE", "IO40OUT", "IO40IN",
"IO20OE", "IO20OUT", "IO20IN",
"IO21OE", "IO21OUT", "IO21IN",
"IO22OE", "IO22OUT", "IO22IN",
"IO23OE", "IO23OUT", "IO23IN",
"IO24OE", "IO24OUT", "IO24IN",
"IO25OE", "IO25OUT", "IO25IN",
"IO26OE", "IO26OUT", "IO26IN",
"IO27OE", "IO27OUT", "IO27IN",
"IO28OE", "IO28OUT", "IO28IN",
"IO29OE", "IO29OUT", "IO29IN",
"IN17", "IN18", "IN19", "IN20", "IN21"
};
/*
* The following array gives the positions in the BSDR bitstream for
* all the macrocell scan cells. Each macrocell is a bidirectional I/O
* pin and so has three associated scan cells: one for controlling the
* tristate buffer, one for output, and one for input. You can get the
* position of any macrocell scan cell in the BSDR by indexing this array
* with the index of the macrocell and the index of the output enable, output,
* or input cell you want.
*/
#define OE 0 /* first column lists tristate control scan cell positions */
#define OUT 1 /* next column lists output scan cell positions */
#define IN 2 /* last column lists input scan cell positions */
int EPX780MacrocellPosition[][3] =
{
/* CFB 0 macrocells */
{ IO00OE, IO00OUT, IO00IN },
{ IO01OE, IO01OUT, IO01IN },
{ IO02OE, IO02OUT, IO02IN },
{ IO03OE, IO03OUT, IO03IN },
{ IO04OE, IO04OUT, IO04IN },
{ IO05OE, IO05OUT, IO05IN },
{ IO06OE, IO06OUT, IO06IN },
{ IO07OE, IO07OUT, IO07IN },
{ IO08OE, IO08OUT, IO08IN },
{ IO09OE, IO09OUT, IO09IN },
/* CFB 1 macrocells */
{ IO10OE, IO10OUT, IO10IN },
{ IO11OE, IO11OUT, IO11IN },
{ IO12OE, IO12OUT, IO12IN },
{ IO13OE, IO13OUT, IO13IN },
{ IO14OE, IO14OUT, IO14IN },
{ IO15OE, IO15OUT, IO15IN },
{ IO16OE, IO16OUT, IO16IN },
{ IO17OE, IO17OUT, IO17IN },
{ IO18OE, IO18OUT, IO18IN },
{ IO19OE, IO19OUT, IO19IN },
/* CFB 2 macrocells */
{ IO20OE, IO20OUT, IO20IN },
{ IO21OE, IO21OUT, IO21IN },
{ IO22OE, IO22OUT, IO22IN },
{ IO23OE, IO23OUT, IO23IN },
{ IO24OE, IO24OUT, IO24IN },
{ IO25OE, IO25OUT, IO25IN },
{ IO26OE, IO26OUT, IO26IN },
{ IO27OE, IO27OUT, IO27IN },
{ IO28OE, IO28OUT, IO28IN },
{ IO29OE, IO29OUT, IO29IN },
/* CFB 3 macrocells */
{ IO30OE, IO30OUT, IO30IN },
{ IO31OE, IO31OUT, IO31IN },
{ IO32OE, IO32OUT, IO32IN },
{ IO33OE, IO33OUT, IO33IN },
{ IO34OE, IO34OUT, IO34IN },
{ IO35OE, IO35OUT, IO35IN },
{ IO36OE, IO36OUT, IO36IN },
{ IO37OE, IO37OUT, IO37IN },
{ IO38OE, IO38OUT, IO38IN },
{ IO39OE, IO39OUT, IO39IN },
/* CFB 4 macrocells */
{ IO40OE, IO40OUT, IO40IN },
{ IO41OE, IO41OUT, IO41IN },
{ IO42OE, IO42OUT, IO42IN },
{ IO43OE, IO43OUT, IO43IN },
{ IO44OE, IO44OUT, IO44IN },
{ IO45OE, IO45OUT, IO45IN },
{ IO46OE, IO46OUT, IO46IN },
{ IO47OE, IO47OUT, IO47IN },
{ IO48OE, IO48OUT, IO48IN },
{ IO49OE, IO49OUT, IO49IN },
/* CFB 5 macrocells */
{ IO50OE, IO50OUT, IO50IN },
{ IO51OE, IO51OUT, IO51IN },
{ IO52OE, IO52OUT, IO52IN },
{ IO53OE, IO53OUT, IO53IN },
{ IO54OE, IO54OUT, IO54IN },
{ IO55OE, IO55OUT, IO55IN },
{ IO56OE, IO56OUT, IO56IN },
{ IO57OE, IO57OUT, IO57IN },
{ IO58OE, IO58OUT, IO58IN },
{ IO59OE, IO59OUT, IO59IN },
/* CFB 6 macrocells */
{ IO60OE, IO60OUT, IO60IN },
{ IO61OE, IO61OUT, IO61IN },
{ IO62OE, IO62OUT, IO62IN },
{ IO63OE, IO63OUT, IO63IN },
{ IO64OE, IO64OUT, IO64IN },
{ IO65OE, IO65OUT, IO65IN },
{ IO66OE, IO66OUT, IO66IN },
{ IO67OE, IO67OUT, IO67IN },
{ IO68OE, IO68OUT, IO68IN },
{ IO69OE, IO69OUT, IO69IN },
/* CFB 7 macrocells */
{ IO70OE, IO70OUT, IO70IN },
{ IO71OE, IO71OUT, IO71IN },
{ IO72OE, IO72OUT, IO72IN },
{ IO73OE, IO73OUT, IO73IN },
{ IO74OE, IO74OUT, IO74IN },
{ IO75OE, IO75OUT, IO75IN },
{ IO76OE, IO76OUT, IO76IN },
{ IO77OE, IO77OUT, IO77IN },
{ IO78OE, IO78OUT, IO78IN },
{ IO79OE, IO79OUT, IO79IN },
};
/*
* This is similar to the previous array. It lets you get the position
* in the BSDR for the scan cells associated with the clock inputs.
*/
int EPX780ClockPosition[] =
{
-1, CLK1, CLK2
};
/*
* This is similar to the previous arrays. It lets you get the position
* in the BSDR for the scan cells associated with the dedicated inputs.
*/
int EPX780InputPosition[] =
{
IN0, IN1, IN2, IN3, IN4, IN5, IN6, IN7, IN8, IN9,
IN10, IN11, IN12, IN13, IN14, IN15, IN16, IN17, IN18, IN19,
IN20, IN21
};
/*
* RTN SetMacrocellDirection: sets the given macrocell (0..79) to be
* an output (dir=1) or an input (dir=0).
*/
void SetMacrocellDirection( bitstream *bsdr, int macrocell, int dir )
{
SetBit( bsdr, EPX780MacrocellPosition[macrocell][OE], dir );
}
/*
* RTN GetMacrocellDirection: returns the IO setting for the macrocell.
*/
int GetMacrocellDirection( bitstream *bsdr, int macrocell )
{
return GetBit( bsdr, EPX780MacrocellPosition[macrocell][OE] );
}
/*
* RTN SetMacrocellOutput: sets the value stored in the output cell of
* the BSDR for the given macrocell (0..79).
*/
void SetMacrocellOutput( bitstream *bsdr, int macrocell, int value )
{
SetBit( bsdr, EPX780MacrocellPosition[macrocell][OUT], value );
}
/*
* RTN GetMacrocellOutput: gets the value stored in the output cell of
* the BSDR for the given macrocell (0..79).
*/
int GetMacrocellOutput( bitstream *bsdr, int macrocell )
{
return GetBit( bsdr, EPX780MacrocellPosition[macrocell][OUT] );
}
/*
* RTN SetMacrocellInput: sets the value stored in the input cell of
* the BSDR for the given macrocell (0..79).
*/
void SetMacrocellInput( bitstream *bsdr, int macrocell, int value )
{
SetBit( bsdr, EPX780MacrocellPosition[macrocell][IN], value );
}
/*
* RTN GetMacrocellInput: gets the value stored in the input cell of
* the BSDR for the given macrocell (0..79).
*/
int GetMacrocellInput( bitstream *bsdr, int macrocell )
{
return GetBit( bsdr, EPX780MacrocellPosition[macrocell][IN] );
}
/*
* RTN SetSyncClock: Sets the value stored in the input cell of
* the BSDR for the given synchronous clock input (1..2).
*/
void SetSyncCLOCK( bitstream *bsdr, int clock, int value )
{
SetBit( bsdr, EPX780ClockPosition[clock], value );
}
/*
* RTN GetSyncClock: gets the value stored in the input cell of
* the BSDR for the given synchronous clock input (1..2).
*/
int GetSyncClock( bitstream *bsdr, int clock )
{
return GetBit( bsdr, EPX780ClockPosition[clock] );
}
/*
* RTN SetDedicatedInput: Sets the value stored in the input cell of the
* BSDR for the given dedicated input (0..21).
*/
void SetDedicatedInput( bitstream *bsdr, int input, int value )
{
return SetBit( bsdr, EPX780InputPosition[input], value );
}
/*
* RTN GetDedicatedInput: Gets the value stored in the input cell of the
* BSDR for the given dedicated input (0..21).
*/
int GetDedicatedInput( bitstream *bsdr, int input )
{
return GetBit( bsdr, EPX780InputPosition[input] );
}