/******************************************************************* * Copyright (c) 2011 -2021 Anlogic Inc. * This file is strictly confidential. All rights reserved. *******************************************************************/ /*********************************************************************** Filename: vec.c Description: generate vec Log: initial version, July 2019 ***********************************************************************/ #define _CRT_SECURE_NO_WARNINGS #include #include #include #include #include #include "Jtag.h" #include "opcode.h" /* global variables about hdr/hir/tdr/tir */ unsigned int g_hdr_size = 0; unsigned int g_hir_size = 0; unsigned int g_tdr_size = 0; unsigned int g_tir_size = 0; unsigned char* g_hdr_data = NULL; unsigned char* g_hir_data = NULL; unsigned char* g_tdr_data = NULL; unsigned char* g_tir_data = NULL; static Jtag jtag_burning; /* function declared in ajeutil.c */ extern int Anlogic_GetBit(unsigned char* data, int id); extern void Anlogic_SetBit(unsigned char* data, int id, int val); extern unsigned char Anlogic_ReverseChar(unsigned char byte); /* Function forward declaration */ void Anlogic_WritePulseTck(void); /* Tap Opcode To TAP_STATE */ enum TAP_STATE Anlogic_TapState(unsigned char opcode) { enum TAP_STATE state = TAP_RESET; switch (opcode) { case RESET: state = TAP_RESET; break; case IDLE: state = TAP_IDLE; break; case DRSELECT: state = TAP_DRSELECT; break; case DRCAPTURE: state = TAP_DRCAPTURE; break; case DRSHIFT: state = TAP_DRSHIFT; break; case DREXIT1: state = TAP_DREXIT1; break; case DRPAUSE: state = TAP_DRPAUSE; break; case DREXIT2: state = TAP_DREXIT2; break; case DRUPDATE: state = TAP_DRUPDATE; break; case IRSELECT: state = TAP_IRSELECT; break; case IRCAPTURE: state = TAP_IRCAPTURE; break; case IRSHIFT: state = TAP_IRSHIFT; break; case IREXIT1: state = TAP_IREXIT1; break; case IRPAUSE: state = TAP_IRPAUSE; break; case IREXIT2: state = TAP_IREXIT2; break; case IRUPDATE: state = TAP_IRUPDATE; break; default: printf("Error: Illegal tap state opcode %u\n", (unsigned int)opcode); } return state; } /* TAP_STATE to TapState String */ const char* Anlogic_TapState2Str(enum TAP_STATE tap_state) { #define X(_w) if (tap_state == TAP_ ## _w) return #_w X(RESET); X(IDLE); X(DRSELECT); X(DRCAPTURE); X(DRSHIFT); X(DREXIT1); X(DRPAUSE); X(DREXIT2); X(DRUPDATE); X(IRSELECT); X(IRCAPTURE); X(IRSHIFT); X(IREXIT1); X(IRPAUSE); X(IREXIT2); X(IRUPDATE); #undef X return "TapState2Str: unkown state"; } static enum TAP_STATE cur_tap_state = TAP_RESET; /* current tap state */ static enum TAP_STATE end_dr_state = TAP_IDLE; /* the tap state that device goes after sdr */ static enum TAP_STATE end_ir_state = TAP_IDLE; /* the tap state that device goes after sir */ /* Tap State Transistions */ int Anlogic_TapTransist(enum TAP_STATE state) { int id = 0; int count = 0; // printf("Anlogic_TapTransist start...\n"); if (cur_tap_state == state && state == TAP_RESET) { for (id = 0; id < 6; ++id) { jtag_burning.TMS_Wr(1); Anlogic_WritePulseTck(); } // printf("Anlogic_TapTransist 107 end...\n"); return 0; } while (cur_tap_state != state) { switch (cur_tap_state) { case TAP_RESET: jtag_burning.TMS_Wr(0); cur_tap_state = TAP_IDLE; break; case TAP_IDLE: jtag_burning.TMS_Wr(1); cur_tap_state = TAP_DRSELECT; break; /* DR STATE Transistion */ case TAP_DRSELECT: if (state >= TAP_IRSELECT || state == TAP_RESET) { jtag_burning.TMS_Wr(1); cur_tap_state = TAP_IRSELECT; } else { jtag_burning.TMS_Wr(0); cur_tap_state = TAP_DRCAPTURE; } break; case TAP_DRCAPTURE: if (state == TAP_DRSHIFT) { jtag_burning.TMS_Wr(0); cur_tap_state = TAP_DRSHIFT; } else { jtag_burning.TMS_Wr(1); cur_tap_state = TAP_DREXIT1; } break; case TAP_DRSHIFT: jtag_burning.TMS_Wr(1); cur_tap_state = TAP_DREXIT1; break; case TAP_DREXIT1: if (state == TAP_DRPAUSE) { jtag_burning.TMS_Wr(0); cur_tap_state = TAP_DRPAUSE; } else { jtag_burning.TMS_Wr(1); cur_tap_state = TAP_DRUPDATE; } break; case TAP_DRPAUSE: jtag_burning.TMS_Wr(1); cur_tap_state = TAP_DREXIT2; break; case TAP_DREXIT2: if (state == TAP_DRSHIFT) { jtag_burning.TMS_Wr(0); cur_tap_state = TAP_DRSHIFT; } else { jtag_burning.TMS_Wr(1); cur_tap_state = TAP_DRUPDATE; } break; case TAP_DRUPDATE: if (state == TAP_IDLE) { jtag_burning.TMS_Wr(0); cur_tap_state = TAP_IDLE; } else { jtag_burning.TMS_Wr(1); cur_tap_state = TAP_DRSELECT; } break; /* IR STATE Transistion */ case TAP_IRSELECT: if (state == TAP_RESET) { jtag_burning.TMS_Wr(1); cur_tap_state = TAP_RESET; } else { jtag_burning.TMS_Wr(0); cur_tap_state = TAP_IRCAPTURE; } break; case TAP_IRCAPTURE: if (state == TAP_IRSHIFT) { jtag_burning.TMS_Wr(0); cur_tap_state = TAP_IRSHIFT; } else { jtag_burning.TMS_Wr(1); cur_tap_state = TAP_IREXIT1; } break; case TAP_IRSHIFT: jtag_burning.TMS_Wr(1); cur_tap_state = TAP_IREXIT1; break; case TAP_IREXIT1: if (state == TAP_IRPAUSE) { jtag_burning.TMS_Wr(0); cur_tap_state = TAP_IRPAUSE; } else { jtag_burning.TMS_Wr(1); cur_tap_state = TAP_IRUPDATE; } break; case TAP_IRPAUSE: jtag_burning.TMS_Wr(1); cur_tap_state = TAP_IREXIT2; break; case TAP_IREXIT2: if (state == TAP_IRSHIFT) { jtag_burning.TMS_Wr(0); cur_tap_state = TAP_IRSHIFT; } else { jtag_burning.TMS_Wr(1); cur_tap_state = TAP_IRUPDATE; } break; case TAP_IRUPDATE: if (state == TAP_IDLE) { jtag_burning.TMS_Wr(0); cur_tap_state = TAP_IDLE; } else { jtag_burning.TMS_Wr(1); cur_tap_state = TAP_IRSELECT; } break; default: printf("Error: invalid tap sate.\n"); return -1; } Anlogic_WritePulseTck(); if (++count > 10) { printf("Error: Loop in Tap Transistion."); return -1; } } jtag_burning.TDI_Wr(0); // printf("Anlogic_TapTransist 240 end...\n"); return 0; } /* Init function, set current tap state to reset */ void Anlogic_Init(void) { cur_tap_state = TAP_RESET; Anlogic_TapTransist(TAP_RESET); } /* set the tap state that deevice goes after sdr */ void Anlogic_SetEndDRState(enum TAP_STATE end_st) { end_dr_state = end_st; #ifdef AJE_DEBUG printf("ENDDR %s;\n", Anlogic_TapState2Str(end_st)); #endif } /* set the tap state that deevice goes after sir */ void Anlogic_SetEndIRState(enum TAP_STATE end_st) { end_ir_state = end_st; #ifdef AJE_DEBUG printf("ENDIR %s;\n", Anlogic_TapState2Str(end_st)); #endif } /* Send HIR/HDR/TIR/TDR data to device */ void Anlogic_SendBypassData(unsigned int op_code) { unsigned char* data = NULL; unsigned int size = 0; unsigned int index = 0; unsigned int bit = 0; switch (op_code) { case HIR: size = g_hir_size; data = g_hir_data; break; case HDR: size = g_hdr_size; data = g_hdr_data; break; case TIR: size = g_tir_size; data = g_tir_data; break; case TDR: size = g_tdr_size; data = g_tdr_data; break; default: break; } /* no value set, use default */ if (data == NULL) { bit = (op_code == HIR || op_code == TIR) ? 1 : 0; } for (index = 0; index < size-1; ++index) { if (data != NULL) { bit = Anlogic_GetBit(data, index); } jtag_burning.TDI_Wr(bit); Anlogic_WritePulseTck(); } bit = Anlogic_GetBit(data, index); jtag_burning.TDI_Wr(bit); } /* Send TDI data to device */ int Anlogic_SendData(unsigned char* tdi_data, unsigned int bin_size, int cascade) { unsigned int index = 0; unsigned int bit = 0; for (index = 0; index < bin_size-1; ++index) { bit = Anlogic_GetBit(tdi_data, index); jtag_burning.TDI_Wr(bit); Anlogic_WritePulseTck(); } bit = Anlogic_GetBit(tdi_data, index); jtag_burning.TDI_Wr(bit); if (cascade == 1) { Anlogic_WritePulseTck(); } return 0; } /* Send TDI data and read TDO, Verify */ int Anlogic_ReadData(unsigned char* tdi_data, unsigned char* tdo_data, unsigned char* mask, unsigned int data_size, int cascade) { unsigned int index = 0; int tdi_bit = 0; int tdo_bit = 0; int mask_bit = 0; for (index = 0; index < data_size-1; ++index) { tdi_bit = Anlogic_GetBit(tdi_data, index); tdo_bit = Anlogic_GetBit(tdo_data, index); mask_bit = Anlogic_GetBit(mask, index); if (mask_bit == 1 && tdo_bit != jtag_burning.TDO_RD()) { return AJE_VERIFY_FAIL; } jtag_burning.TDI_Wr(tdi_bit); Anlogic_WritePulseTck(); } tdi_bit = Anlogic_GetBit(tdi_data, index); tdo_bit = Anlogic_GetBit(tdo_data, index); mask_bit = Anlogic_GetBit(mask, index); if (mask_bit == 1 && tdo_bit != jtag_burning.TDO_RD()) { return AJE_VERIFY_FAIL; } jtag_burning.TDI_Wr(tdi_bit); if (cascade == 1) { Anlogic_WritePulseTck(); } return AJE_OK; } /* Send TDI Data and Save TDO */ int Anlogic_SaveData(unsigned char* tdi_data, unsigned int data_size, unsigned char** tdo_data) { unsigned int index = 0; unsigned int tdi_bit = 0; unsigned int tdo_bit = 0; for (index = 0; index < data_size-1; ++index) { tdo_bit = jtag_burning.TDO_RD(); Anlogic_SetBit(*tdo_data, index, tdo_bit); tdi_bit = Anlogic_GetBit(tdi_data, index); jtag_burning.TDI_Wr(tdi_bit); Anlogic_WritePulseTck(); } tdo_bit = jtag_burning.TDO_RD(); Anlogic_SetBit(*tdo_data, index, tdo_bit); tdi_bit = Anlogic_GetBit(tdi_data, index); jtag_burning.TDI_Wr(tdi_bit); return AJE_OK; } /* Process SIR/SDR */ int Anlogic_ProcessShiftCmd(unsigned int op_code, unsigned int cascade, unsigned int read, unsigned int data_size, unsigned char* tdi_data, unsigned char* tdo_data, unsigned char* mask) { int rtn_val = AJE_OK; // process header data switch (op_code) { case SIR: if (cascade != 1) { Anlogic_TapTransist(TAP_IRSHIFT); if (g_hir_size > 0) { Anlogic_SendBypassData(HIR); Anlogic_WritePulseTck(); } } break; case SDR: if (cascade != 1) { Anlogic_TapTransist(TAP_DRSHIFT); if (g_hdr_size > 0) { Anlogic_SendBypassData(HDR); Anlogic_WritePulseTck(); } } break; default: break; } if (read == 1) { rtn_val =Anlogic_SaveData(tdi_data, data_size, &tdo_data); } else if (mask == NULL) { rtn_val =Anlogic_SendData(tdi_data, data_size, cascade); } else { rtn_val =Anlogic_ReadData(tdi_data, tdo_data, mask, data_size, cascade); } // process tailer data switch (op_code) { case SIR: if (cascade != 1) { if (g_tir_size > 0) { Anlogic_WritePulseTck(); Anlogic_SendBypassData(TIR); } Anlogic_TapTransist(end_ir_state); } break; case SDR: if (cascade != 1) { if (g_tdr_size > 0) { Anlogic_WritePulseTck(); Anlogic_SendBypassData(TDR); } Anlogic_TapTransist(end_dr_state); } break; default: break; } return rtn_val; } /* process single sir command, do not use bypass data (hir/tir) */ int Anlogic_ExeSirCommand(unsigned char command, int cur_lvl, int total_lvl) { int rtn_val = AJE_OK; unsigned char* tdi_data = NULL; int id = 0; Anlogic_TapTransist(TAP_IRSHIFT); tdi_data = (unsigned char*)calloc((total_lvl*8+1), sizeof(unsigned char)); for(id = 0; id < total_lvl; ++id) { if (id == (total_lvl - cur_lvl)) { tdi_data[id] = Anlogic_ReverseChar(command); } else { tdi_data[id] = 0xFF; } } rtn_val = Anlogic_SendData(tdi_data, total_lvl*8, 0 /*cascade*/); Anlogic_TapTransist(end_ir_state); return rtn_val; } /* process sdr command, do not use bypass data (hdr/tdr) */ int Anlogic_ExeSdrCommand(unsigned int bit_size, int cur_lvl, int total_lvl, unsigned char* tdi_data, unsigned char* tdo_data) { int rtn_val = AJE_OK; int head_num = total_lvl - cur_lvl; int tailer_num = cur_lvl-1; int id = 0; unsigned int byte_size = (bit_size + 7)/8; Anlogic_TapTransist(TAP_DRSHIFT); if (head_num > 0) { for (id = 0; id < head_num; ++id) { jtag_burning.TDI_Wr(0); Anlogic_WritePulseTck(); } } if (tdi_data == NULL) { tdi_data = (unsigned char*)calloc((byte_size+1), sizeof(unsigned char)); } if (tdo_data == NULL) { rtn_val = Anlogic_SendData(tdi_data, bit_size, 0 /*cascade*/); } else { /* read and save tdo readback data */ rtn_val = Anlogic_SaveData(tdi_data, bit_size, &tdo_data /*cascade*/); } if (tailer_num > 0) { for (id = 0; id < tailer_num; ++id) { Anlogic_WritePulseTck(); jtag_burning.TDI_Wr(0); } } Anlogic_TapTransist(end_dr_state); return rtn_val; } /* process runtest num tck */ void Anlogic_ProcessRunTestTck(int num) { volatile int i = 0; jtag_burning.TDI_Wr(0); jtag_burning.TMS_Wr(0); for(i = 0; i < num; ++i) { jtag_burning.TCK_Wr(1); jtag_burning.TCK_Wr(0); } #ifdef AJE_DEBUG printf("RUNTEST %d TCK;\n", num); #endif } void Anlogic_WritePulseTck(void) { static unsigned int i = 0; jtag_burning.TCK_Wr(1); jtag_burning.TCK_Wr(0); }