⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ivm_core.c

📁 在嵌入式系统中对Lattice CPLD软件升级时所需的VME文件生成所需源代码。基于E2PROM存储
💻 C
📖 第 1 页 / 共 3 页
字号:

/****************************************************************************
                 ispVM Core Of Embedded Version Of ispVM
              Lattice Semiconductor Corp. Copyright 1998 - 2001.           
      ispVME for Embedded Applications Where Resources is A Premium.

  This is the scale down version of the full ispVM target for embedded
  applications. The footprint of this VM is less than 8K bytes in size.    
  Huffman encoding is used to minimize the Virtual Machine Format file size
  without increasing the VM footprint and addtional RAM for decompression  
  is not required.                                                         

  Typically only 100 bytes of RAM is required to hold one row of data when
  processing the VMF file. The VM itself also need less than 100 bytes of  
  RAM to hold all the variables it needs.                                  
  This is the core of the ispVM Embedded. All the high level opcode of the
  ispVM required to support all industry standard SVF constructs are included.

  All ispVM opcodes for decision branching, math and low level bit banging
  are not included to reduce the ispVM Embedded footprint to the minimum.
  Decision branching and math operations are still carried out by ispVM
  Embedded by using native code instead. It is to achieve the highest
  efficiency possible for ispVM Embedded. For example:
  Using native code to add A and B is:  sum=a+b;
  Using ispVM opcode is: PUSH a; PUSH b; ADD sum;
  It is obvious that the ispVM actually interprets the compiled opcode
  and call the appropriate function to perform the action in native code.
  Native code vs ispVM opcode represents respectively the efficiency and
  flexibility trade off. The priority number one for ispVM Embedded is
  efficiency. 
  The functional blocks:
  ispVMCode()        Extract and interpret the ispVM high level opcodes.
  ispVMDataCode()    Extract and interpret ispVM data type opcode.
  ispVMDataSize()    Extract the operand of size (a 16 bit number).
  ispVMData()        Extract and decompress one row of data stream.

4/26/01  Add support to a non-zero HIR, HDR, TIR and TDR for multiple devices
         in one SVF file. 
8/23/01  Add support to cascading turn on and off.
         Add some sort of flow control to support the program the part if usercode 
         verify fail requirement.
         Add support of repeat looping for vme file size reduction.
12/03/01 Checks for SECUREHEAP opcode immediately following HEAP opcode to 
         maintain VME integrity
tnt 03/13/02 New opcodes added CRC, CMASK, READ, and RMASK to calculate data
			 CRC and perform Read and Save.
3/25/02	tnt	No longer issue DRPAUSE/IRPAUSE to the state machine after sending
			or receiving data
1/15/04 Support cascade by checking is current state is SHIFTDR.  If SHIFTDR is active,
        then do not step into DRPAUSE.
2/11/04	Remove IEEE 1532 support.
*****************************************************************************/
#include <stdio.h>
#include "vmopcode.h"
#include "hardware.h"

#ifdef VME_DEBUG
#include "debug.h"
#endif

unsigned short usFlowControl = 0x0000,   /*Flow control register*/
               usDataType = 0x0000;      /*holds the data type of the current row
                                         default is all operations selected*/
extern unsigned char * OutMaskData,    /*holds Mask data*/
                     * InData,      /*holds data to be shift into device*/
					 * OutData,     /*holds data to be compared with those read from device*/
					 * HIRData,     /*holds data of SIR header*/
					 * TIRData,     /*holds data of SIR trailer*/
					 * HDRData,     /*holds data of SDR header*/
					 * TDRData,     /*holds data of SDR trailer*/
					 * OutDMaskData;/*holds DMask data*/

extern char cCurrentJTAGState;
extern unsigned char * pucHeapMemory;     /*holds the repeat loop*/
extern unsigned short iHeapCounter;   /*holds the current byte address of the Heap*/

/*set all to default*/
static unsigned char
      End_DR = DRPAUSE,   /*after shift data, part at PAUSE DR by default*/
      End_IR = IRPAUSE;   /*after shift IR, part at PAUSE IR by default */
static unsigned short
      HeadDR = 0,         /*the number of lead devices in bypass*/
      HeadIR = 0,         /*the sum of IR length of lead devices*/
      TailDR = 0,         /*the number of tail devices in bypass*/
      TailIR = 0;         /*the sum of IR length of tail devices*/

static unsigned short usiDataSize = 0; /*the number(bits) of data or instruction
                                         to be shifted into or out from devices*/
extern unsigned short iHEAPSize;                   /*the number of bytes in the HEAP*/
unsigned short Frequency = 1000;        
static unsigned short MaxSize = 0;          /*the maximum amount of rams(bytes) needed to
                                                  hold a row of data*/
unsigned short iShiftValue = 0;           /*holds the updated value of LSH or RSH*/
unsigned short RepeatLoops= 0;            /*holds the current repeat loop value*/
unsigned short rightShift = 0;   /*holds permission to rightShift or not*/
char cVendor;                  /*holds the name of the vendor*/

extern char GetByte(void);
extern void ispVMMemManager(char types, unsigned short size);

/*prototypes*/
char ispVMCode(void);
char ispVMDataCode(void);
unsigned short ispVMDataSize(void);
void ispVMData(unsigned char *Data);
char ispVMShift(char Code);
char ispVMAmble(char Code);
char ispVMLoop( unsigned short a_usLoopCount );
char ispVMBitShift(char mode, unsigned short bits);

/****************************************************************************
                     ispVMDataSize                       
 Extract the data size of the current row from the VME file.  
 Return                                                                
     usiDataSize-----------The data bit length of the current row.     
*****************************************************************************/
unsigned short ispVMDataSize()
{
	unsigned short usiSize = 0;
	char cCurrentByte, cIndex;
	
	cIndex = 0;
	while ( ( cCurrentByte = GetByte() ) & 0x80 ) {
		usiSize |= ( ( unsigned short ) ( cCurrentByte & 0x7F ) ) << cIndex;
		cIndex += 7;
	}
	usiSize |= ( ( unsigned short ) ( cCurrentByte & 0x7F ) ) << cIndex;
	return usiSize;
}

/****************************************************************************
                     ispVMCode                                
 This is the core of ispVM Embedded. The ispVM opcodes are extracted and
 interpreted in this module. The ispVM opcodes supported here are only
 high level ispVM opcodes. High level opcodes simplify users' task in
 creating the VME files. For example:
 To scan an instruction into the targeted device(s), the VME program is:
 SVF:  SIR 5 TDI (0x0A);
 VME:  0x01,0x00,0x05,0x03,0x50,0x00;
       SIR opcode = 0x01;
       size = 0x00, 0x05;
       TDI opcode = 0x03;
       data = 0x50 which is reverse of 0x0A;
       ENDDATA opcode = 0x00;
 The high level opcode is splitted into multiple low level tasks by the ispVM
 Embedded:
  task 1: Fetch and keep all the operands, size and data stream etc.
          Allocate memory if necessary to keep the operands.
  task 2: Move the BSCAN state of the device to IRPAUSE.
  task 3: Put the leading and trailing devices into BYPASS mode.
  task 4: Move the BSCAN state machine to Shift-IR state.
  task 5: Shift the data stream into the target device(s);
  task 6: Move the BSCAN state machine to IRPAUSE.
  task 7: Move the BSCAN state machine to state as specified by ENDDR opcode.
  task 8: Put the leading and trailing devices into BYPASS mode.
 If low level opcodes are used instead, each task will require an opcode.
 This will go against the objective of having a small VME file size and
 fast programming time.
 Return                       
 Global var:                            
  compression --read instruction without compression read data with
                compression  
  tdodata     --true if TDO opcode is detected to indicate reading is
                necessary
  express     --true if EXPRESS SDR(XSDR) token is detected.
                XSDR will be carried out with Input data transferred to
                Output data buffer for next verify against. The XTDO opcode
                does not have data. The effect is to reduce the VME file
                size by half.                                
  usiDataSize    --the number of bits of data to be processed   
*****************************************************************************/
char ispVMCode()
{
	unsigned short iRepeatSize;
	char cOpcode;
	char cRetCode = 0;

#ifdef VME_DEBUG
	unsigned short siDebugRow = 0;
	unsigned short iOpcodeIndex;
#endif
	
	while ( ( cOpcode = GetByte() ) >= 0 ) { /* All opcode except ENDFILE are all positive */
#ifdef VME_DEBUG
		siDebugRow++;
		for ( iOpcodeIndex = 0; iOpcodeIndex < iOpcodeCount; iOpcodeIndex++ ) {
            if ( ispVMOpcodes[ iOpcodeIndex ].token == cOpcode ) {
				break;
			}
		}
		printf( "Row = %d Opcode = %s\n", siDebugRow, ispVMOpcodes[ iOpcodeIndex ].text );        
#endif
		switch ( cOpcode ) {
		case STATE: /*step BSCAN state machine to specified state*/
			ispVMStateMachine( GetByte() );
			break;
		case SIR:   /*shift instruction stream into devices*/
		case SDR:   /*shift data stream into devices*/
		case XSDR:
			cRetCode = ispVMShift( cOpcode );
			if ( cRetCode != 0 ) {
				return ( cRetCode );
			}
			break;
		case WAIT:  /*opcode to wait for specified time in us or ms*/      
			ispVMDelay( ispVMDataSize() );
			break;
		case TCK:   /*pulse TCK signal the specified time*/
			ispVMClocks( ispVMDataSize() );
			break;
		case ENDDR: /*modify the BSCAN state after SDR opcode*/
			End_DR = GetByte();
			break;
		case ENDIR: /*modify the BSCAN state after SIR opcode*/
			End_IR = GetByte();
			break;
		case HIR:   /*modify the IR length of lead devices*/
		case TIR:   /*modify the IR length of the trailing devices*/
		case HDR:   /*modify the DATA length of the lead devices*/
		case TDR:   /*modify the DATA length of the trailing devices*/
			cRetCode = ispVMAmble( cOpcode );
			if ( cRetCode != 0 ) {
				return ( cRetCode );
			}
			break;
		case MEM:   /*The maximum RAM required for current VME file*/
			MaxSize = ispVMDataSize();
			break;
		case VENDOR:
			cOpcode = GetByte();
			switch ( cOpcode ) {
			case LATTICE:
				cVendor = LATTICE;
				break;
			case ALTERA:
				cVendor = ALTERA;
				break;
			case XILINX:
				cVendor = XILINX;
				break;
			default:
				break;
			}
			break;
		case SETFLOW:
			usFlowControl |= ispVMDataSize();
			break;
		case RESETFLOW: /*Clear the continue if fail flag*/
			usFlowControl &= ~( ispVMDataSize() );
			break;
		case HEAP: /*the size of HEAP memory to store loops*/
			cRetCode = GetByte();
			if ( cRetCode != SECUREHEAP ) {
				return -4;
			}
			iHEAPSize = ispVMDataSize();  /*HEAP size in bytes*/
			ispVMMemManager( HEAP, ( unsigned short ) iHEAPSize );
			break;
		case REPEAT:   /*the begin of a monolithic loop*/
			RepeatLoops = 0;
			iRepeatSize = ispVMDataSize();
			
			cRetCode = ispVMLoop( ( unsigned short ) iRepeatSize );
#ifndef VME_DEBUG
			if ( cRetCode != 0 ) {
				return ( cRetCode );
			}
#endif
			break;
		case ENDLOOP:
			return ( cRetCode );  /*force a return*/
		case ENDVME: 
		case ENDFILE:  /*reach end of the current VME file*/ 
			return( cRetCode );    /*return the result*/
		case SHR:
			usFlowControl |= SHIFTRIGHT;
			iShiftValue = RepeatLoops * GetByte();
			break;
		case SHL:
			usFlowControl |= SHIFTLEFT;
			iShiftValue = RepeatLoops * GetByte();
			break;
		case FREQUENCY:
			Frequency = ispVMDataSize();
			break;
		case VUES:
			usFlowControl |= VERIFYUES;
			break;
		default: /* Invalid opcode encountered */
#ifdef VME_DEBUG
			printf( "Illegal opcode (%02X)!\n", cOpcode );
#endif
			return -4;
		}
	}
	
	if ( ( cOpcode < 0 ) && ( cOpcode != ( char ) ENDFILE ) ) {
		return ( -4 ); 
	}
	else {
		return ( cRetCode );
	}
}


/****************************************************************************
                     ispVM Data Code          
This routine is to extract the data operator which follows the TDI, TDO
 and MASK and perform operations on the data stream. The possible
 operator codes are:

 if the data follows has compression, then add 0x80 to the opcode shown

 LOCAL         0x00     the data follows immediately
 SHR           0x01     from data follows immediately
 SHL           0x02     from data follows immediately
 ROMARRAY      0x03     from read only array follows
 RAMARRAY      0x04     from a read and write array
 CPYDATARRAY   0x05     copy to data array (i.e. $addr=1;)
 CPYDATAVAR    0x06     copy to data variable 
 SHLARRAY      0x07     from data array with shift left operation
 SHRARRAY      0x08     from data array with shift right operation
 INVARRAY      0x09     from data array with complement operation
 INCDATA       0x0A     from variable array with increment operation 
 DECDATA       0x0B     from variable array with decement operation 
 INVDATA       0x0C     from variable array with complement operation 
 SHLDATA       0x0D     from variable array with shift left operation
 SHRDATA       0x0E     from varaible array with shift right operation

 This version V9.001 supports only LOCAL and ROMARRAY data operator.
 If other operators are desired, contact Lattice's Application for
 the library functions.

                  
 Extract tdi tdo or mask from the VME file.                     
 Return                                                         
     usDataType------------Set EXPRESS bit true if XTDI, XTDO found. 
                         Set TDI_DATA, TDO_DATA, MASK_DATA bit true if found.
*****************************************************************************/
char ispVMDataCode()
{
	char cDataByte;
	char siDataSource = 0;  /*source of data from file by default*/
 
#ifdef VME_DEBUG
	unsigned short iOpcodeIndex;
#endif
	

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -