📄 svf2vme.c
字号:
/************************************************************************
* Copyright, 2000-2003 Lattice Semiconductor Corp. *
* SVF2VME.c *
* This Program Converts An SVF File From ASCII Source Form Into *
* Binary Form To Reduce Size And To Improve Processing Time. *
* *
* The conversion is done by converting Token into 8 bits Code. *
* The 8 bits Token are always followed by 16 bits field. *
* Some 8 bits Token has data field follows the 16 bits field. *
* SDI MASK is not supported due to its rare appearence on ISP *
* application. *
* The data field follows the SDR token are compressed when 0x00 *
* or 0xFF bytes are detected. The compression is done by replacing*
* 0xFF, 0xFF, 0xFF by 0xFF, 0x02 etc. *
* Single level Huffman encoding scheme is used to compress the *
* data and compare with the result produced above. The winner is *
* is used to compress the data. *
* Compression is done on row by row bases. *
* The RUNTEST Token is followed by a 16 bits field express in *
* uS if the most significant bit is 0, in mS if the most *
* significant bit is 1. *
* The FREQUENCY Token is followed by a 16 bits field express in *
* KHZ if the most significant bit is 0, in MHZ if the most *
* significant bit is 1. *
* *
* Note: This program must be compiled as a 32 bits application if the *
* SVF file is known to contain more than more than 64000 bits *
* in a single scan. *
* The VME filetype code is __VME1.0 *
* Howard Tang 08/08/98 Convert from svfdvr.c *
* Howard Tang 02/02/00 Update per new marketing requirement for market*
* launch of ispVM Embedded. *
* Howard Tang 05/30/00 Accept no space between TDx and (, xMASK and ( *
* Howard Tang 09/27/00 Replace tap with blank for simpler processing *
* Accept STATE RESET IDLE IRPAUSE DRPAUSE *
* multiple state construct. *
* Howard Tang 12/19/00 If the last char is already a \n, then read *
* a new line. *
* Howard Tang 01/02/01 Fix the splitting long SDR data stream problem.*
* Howard Tang 04/26/01 Support Non zero HIR, HDR, TIR and TDR. *
* Howard Tang 08/28/01 Change to VME1.1 format: *
* - The number is cascaded. *
* - Turn on/off the SDR cascading when force *
* splitting occur. *
* - Add support to FLOW opcode which shall *
* alter from the continue while pass to *
* stop if pass. *
* Howard Tang 10/02/01 Minimize file size by using repeat looping *
* feature. *
* tnt 12/03/01 Added SECUREHEAP opcode to maintain file *
* integrity when inserting the heapsize *
* tnt 12/03/01 Added switch to indicate foreign devices *
* tnt 1/07/01 Change to VME2.0 *
* tnt 9/30/02 Update to accept other vendor names. If *
* the vendor is not Altera or Xilinx, then *
* default to Lattice. *
* tnt 10/19/02 Added fix to compressToIspStream for 5512VE *
* tnt 10/21/02 Support frequency option at command line *
* tnt 4/7/03 Change version number to VME 2.0.1. Note: *
* the internal version number will still be 2.0 *
* in order for the decoder to accept files *
* generated with this version. *
* Changes include: *
* 1) In STATECom function, if a long state is *
* given, return failure. *
* 2) Change the variables MaxSize and scan_len *
* to unsigned long for easier porting to *
* 16-bit. *
* 4/28/03 Update to v2.1. v2.1 supports Continue If Fail (USERCODE *
* Verification). Also updated the command line syntax and *
* usage. *
* 2/11/04 Update to v2.1.1. Remove IEEE 1532 support. *
* *
*************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <malloc.h>
#include "vmopcode.h"
#include "svf2loopsvf.h"
#include "Utilities.h"
#include "UESVerify.h"
#include "SVF2VME.h"
FILE *fp, *fpw;
unsigned char buffer[strmax]; /*memory to store a string temporary */
unsigned char *SVF_string; /*pointer to current token string*/
unsigned int allocateFlag; /*variable to determine if we allocate memory for numBitArray*/
long int frequency = 0;
int svfline = 0; /*keeps the svfline number read*/
int *numBitArray = NULL; /*keeps track of the bits in repeat loops */
int globalBitArrayCounter = 0; /*counter used in numBitArray*/
int headIR = 0, tailIR = 0, headDR = 0, tailDR = 0;
int CurEndDR = DRPAUSE, CurEndIR = IRPAUSE;
long int MaxSize = 0; /*the maximum row size of all the SVF files*/
char pass=0; /*to keep track of the passes of the current attempt*/
/* Variables used in programming foreign devices */
int vendor = 0;
unsigned char* SDRMask = NULL;
unsigned char* SIRMask = NULL;
int previousSIRbits = 0;
int previousSDRbits = 0;
static struct stableState
{
char * text;
int state;
} stableStates[ StableStateMax ] = {
{ "RESET", RESET },
{ "IDLE", IDLE },
{ "IRPAUSE", IRPAUSE },
{ "DRPAUSE", DRPAUSE }
};
static struct scanToken
{
char *text;
int token;
} scanTokens[] =
{
/*opcode share with ispVM and SVF2VME */
{";", ENDDATA},
{"SIR", SIR},{"SDR", SDR},
{"TDI", TDI},{"TDO", TDO},{"MASK", MASK},
{"STATE", STATE},
{"TCK", TCK,}, {"WAIT", WAIT},
{"XSDR", XSDR},{"XTDI", XTDI},{"XTDO", XTDO}, /*opcode for ispVM only*/
{"ENDDR", ENDDR},
{"ENDIR", ENDIR},
{"HIR", HIR},{"TIR", TIR},{"HDR", HDR},{"TDR", TDR},
{"MEM", MEM}, /*opcode for ispVM only*/
/*opcode exist only in SVF files and is for SVF2VME only*/
{"RUNTEST", RUNTEST},
{"ENDSTATE", ENDSTATE},
{"TRST", TRST},
{"FREQUENCY", FREQUENCY},
{"SEC", SEC},
{"SMASK", SMASK},
{"MAXIMUM", MAX},
{"ON", ON},{"OFF", OFF},
{"SETFLOW",SETFLOW},{"RESETFLOW",RESETFLOW},
{"REPEAT",REPEAT},{"ENDLOOP",ENDLOOP},
{"(", LEFTPAREN},
/* 05/27/03 Nguyen added to support Dynamic IO */
{"DMASK",DMASK},
{"VUES", VUES}
};
int ScanTokenMax = sizeof( scanTokens ) / sizeof( scanTokens[ 0 ] );
/* 3 scan nodes is reserved:
0 is for SIR, 1 is for SDR and 2 is to store previous SDR */
/* 4/26/2001 ht Add 1 scan nodes to store the HIR,TIR,HDR and TDR info */
struct scanNode
{
long int numbits;
unsigned char *tdi;
unsigned char *tdo;
unsigned char *mask;
/* 05/27/03 Nguyen added to support Dynamic IO */
unsigned char *dmask;
} scanNodes[4] = {{0, NULL, NULL, NULL, NULL },
{0, NULL, NULL, NULL, NULL },
{0, NULL, NULL, NULL, NULL },
{0, NULL, NULL, NULL, NULL },
};
CFG * cfgChain = NULL;
/* Variables used in looping */
extern int iLoopVMEOption;
extern int shiftsize;
extern int iLoopIndex;
extern int totalbytecount;
extern int ** Repeat;
extern int * PatternNumArray;
extern int ** SDRValueArray;
extern int heapsize;
extern unsigned int inRepeat;
/*************************************************************************
* *
* Convert Number to VME format *
* *
* A large number is converted into cascading of bytes *
* If the most significant bit of a byte is 0, then *
* it is the last byte to form the number. *
* Input: *
* number-----the decimal number to be converted *
* fpw------write the converted number into it *
* Return: *
* the number of bytes the number is converted into. *
* *
*************************************************************************/
int ConvNumber( long int number )
{
int byte_cnt = 0;
while ( number > 0x007F ) {
byte_cnt++;
write( ( number & 0x007F ) + 0x0080 );
number = number >> 7;
}
write( ( unsigned char ) number );
byte_cnt++;
return( byte_cnt );
}
/*************************************************************************
* Token() *
* return a token when it is called. Comments are discarded. *
* To make the parser more flexible, space is inserted between the *
* following delimiters. If there are space there already, additional *
* space is added which will be discarded when strtok is used. *
* ';' *
* Var: *
* global fp--the current svfplus file pointer. *
* buffer--the temporary storage of the string *
* out SVF_string--the token obtained. *
* return 1 when EOF else 0. *
**************************************************************************/
int Token( const char * delimiters )
{
int i, j, length;
if ( ( SVF_string == NULL ) || ( ( SVF_string = strtok( NULL, delimiters ) ) == NULL ) ||
( SVF_string[ 0 ] == '!' ) || ( SVF_string[ 0 ] == '/' ) ||
( SVF_string[ 0 ] == '\n' ) /*12/19/00 ht read a new line*/ ) {
do {
if ( fgets( buffer, strmax, fp ) == NULL ) {
return ( 1 );
}
length = strlen( buffer ) + 1;
if ( length > 2 ) {
for ( i = 0; i < length; i++ ) {
switch ( buffer[ i ] ) {
case '\t':
/* Replace tab with space */
buffer[ i ] = ' '; /*9/27/00 ht*/
break;
case '\r':
/* Replace carriage return with space */
buffer[ i ] = ' ';
break;
case ';' :
case '(' :
case ')' :
for ( j = length + 2; j > i + 2; j-- ) {
buffer[ j ] = buffer[ j - 2 ];
}
buffer[ j-- ] = ' '; /*space at i + 2*/
buffer[ j-- ] = buffer[ i ]; /*shift left 1*/
buffer[ i ] = ' '; /*space at i*/
length += 2; /*real length*/
i += 2; /*2 space added*/
break;
default :
break;
}
}
}
SVF_string = strtok( buffer, delimiters ); /* Get the first token */
svfline++; /* Update the line number */
} while ( ( SVF_string == NULL ) || ( SVF_string[ 0 ] == '!' ) ||
( SVF_string[ 0 ] == '/' ) || ( SVF_string[ 0 ] == '\r' ) ); /* Ignore comments */
}
return( 0 ); /* Not yet end of file */
}
/*************************************************************************
* ispsvf_convert() *
* Read the svf file line by line and convert line by line into a token *
* based ispSTREAM file: *
* FIELD: token :size : data *
* WIDTH: 8 bits :16 bits : variable(in binary) *
* 8/28/01 define options: *
* bit 0: no compress is 0, comression is 1. *
* bit 1: stop if fail is 0, stop if pass is 1. *
*************************************************************************/
short int ispsvf_convert( int chips, CFG * chain, char * vmefilename, char options )
{
short int i, j, rcode = 0;
int device;
char filler = 0;
long int scan_len;
int arrayCounter;
char opcode;
unsigned char *dataptr;
int numOfRepeats = 0;
int *heapSizeArray = 0;
char* ispJTAG;
int temp;
char xchar;
static struct header
{
unsigned char types;
int value;
} headers[ 4 ] = { { TDR, 0 }, { TIR, 0 }, { HDR, 0 }, { HIR, 0 } };
if ( ( fpw = fopen( vmefilename, "wb" ) ) == NULL ) {
return FILE_NOT_FOUND;
}
ispJTAG = "__VME2.0";
fprintf( fpw, ispJTAG ); /*ispJTAG filetype*/
totalbytecount += strlen( ispJTAG );
if ( options & 0x01 ) {
write( 0xF1 ); /*F1: the Full VME File */
}
else {
write( 0xF2 ); /*F2: the compress VME File */
}
write( MEM ); /*the memory size token*/
ConvNumber( MaxSize );
/* if looping VME */
if (iLoopVMEOption) {
/* Count the total number of loops for all devices*/
for (i = 0; i < iLoopIndex; i++) {
for (j= 0; j < PatternNumArray[i]; j++) {
numOfRepeats += Repeat[i][j];
}
}
/* allocate space to store the size (in bytes) of each iLoopVMEOption */
if (numOfRepeats) {
heapSizeArray = (int*)calloc(numOfRepeats, sizeof(int));
numOfRepeats = 0 ;
}
}
for (device = 0; device < chips; device++) {
rcode = 0;
iLoopIndex = device;
/* set vendor */
write(VENDOR);
if (!stricmp(chain[device].Vendor, "lattice")) {
vendor = LATTICE;
write(LATTICE);
}
else if (!stricmp(chain[device].Vendor, "altera")) {
vendor = ALTERA;
write(ALTERA);
}
else if (!stricmp(chain[device].Vendor, "xilinx")) {
vendor = XILINX;
write(XILINX);
}
if (stricmp(chain[device].name, "SVF") == 0) {
if ((fp = fopen(chain[device].Svffile, "r")) == NULL) {
return FILE_NOT_FOUND;
}
/*get the frequency setting in the structure*/
if (strchr(chain[device].Frequency, 'k')) /*frequency specified in KHZ*/
frequency = atoi(chain[device].Frequency);
else if (strchr(chain[device].Frequency, 'm')) /*frequency specified in MHZ*/
frequency =(atoi(chain[device].Frequency))*1000; /*convert to KHZ*/
else
frequency = 0; /*it is default into 1MHZ*/
if (chips > 1) {
/* Multiple devices chain found */
for (i = 0; i < 4; i++) {
headers[i].value = 0;
}
for (i = 0; i < device; i++) {
/*calculate the Trailer stream*/
headers[0].value += 1;
headers[1].value += chain[i].inst;
}
for (i = device + 1; i < chips; i++) {
/*calculate the Header stream*/
headers[2].value += 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -