1525 lines
32 KiB
C
1525 lines
32 KiB
C
/*
|
|
* JTAG Core library
|
|
* Copyright (c) 2008 - 2024 Viveris Technologies
|
|
*
|
|
* JTAG Core library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* JTAG Core library 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
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with JTAG Core library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
/**
|
|
* @file bsdl_loader.c
|
|
* @brief bsdl file parser
|
|
* @author Jean-François DEL NERO <Jean-Francois.DELNERO@viveris.fr>
|
|
*/
|
|
|
|
#include <stdint.h>
|
|
#include <ctype.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "drivers/drv_loader.h"
|
|
#include "jtag_core/jtag_core_internal.h"
|
|
#include "jtag_core/jtag_core.h"
|
|
|
|
#include "bsdl_loader.h"
|
|
#include "bsdl_strings.h"
|
|
|
|
#include "natsort/strnatcmp.h"
|
|
|
|
#include "os_interface/os_interface.h"
|
|
|
|
#include "jtag_core/dbg_logs.h"
|
|
#define DEBUG 1
|
|
|
|
char *string_upper(char *str)
|
|
{
|
|
while (*str != '\0')
|
|
{
|
|
*str = toupper((unsigned char)*str);
|
|
str++;
|
|
}
|
|
return str;
|
|
}
|
|
|
|
int strcmp_nocase(char *str1,char *str2)
|
|
{
|
|
int d;
|
|
|
|
for(;; str1++, str2++)
|
|
{
|
|
d = tolower(*str1) - tolower(*str2);
|
|
|
|
if(d != 0 || !*str1)
|
|
return d;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int getnextvalidline(char *buffer,int buffersize,int * offset)
|
|
{
|
|
int l_offset;
|
|
int current_line_offset;
|
|
|
|
l_offset = *offset;
|
|
current_line_offset = *offset;
|
|
|
|
do
|
|
{
|
|
// Skip all the blank characters
|
|
while( (l_offset < buffersize) && (buffer[l_offset] == ' ' || buffer[l_offset] == '\t') )
|
|
{
|
|
l_offset++;
|
|
}
|
|
|
|
// End of buffer reached ?
|
|
if(l_offset == buffersize)
|
|
{
|
|
*offset = l_offset;
|
|
|
|
return 1;
|
|
}
|
|
|
|
// Is it a return or comment ?
|
|
if( buffer[l_offset] != '\r' && buffer[l_offset] != '\n' && (buffer[l_offset] != '-' || buffer[l_offset+1] != '-'))
|
|
{
|
|
// No. There is something interesting into this line.
|
|
*offset = current_line_offset;
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
// Is it a comment ?
|
|
if(buffer[l_offset] == '-' && buffer[l_offset+1] == '-')
|
|
{
|
|
// Yes. Go to the end of the line...
|
|
while(buffer[l_offset] != 0 && buffer[l_offset] != '\r' && buffer[l_offset] != '\n')
|
|
{
|
|
l_offset += 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( buffer[l_offset] == '\r' || buffer[l_offset] == '\n')
|
|
{
|
|
l_offset++;
|
|
|
|
if(l_offset < buffersize)
|
|
{
|
|
if( buffer[l_offset] == '\n' )
|
|
{
|
|
l_offset++;
|
|
}
|
|
}
|
|
|
|
current_line_offset = l_offset;
|
|
}
|
|
}while ( (l_offset < buffersize) && buffer[l_offset] );
|
|
|
|
*offset = l_offset;
|
|
|
|
return 1;
|
|
}
|
|
|
|
char getnextchar(char *buffer,int buffersize,int * offset)
|
|
{
|
|
char c;
|
|
|
|
if (*offset < buffersize)
|
|
{
|
|
c = buffer[*offset];
|
|
|
|
switch (c)
|
|
{
|
|
case 0:
|
|
return 0;
|
|
break;
|
|
|
|
case '\r':
|
|
*offset += 1;
|
|
|
|
if (*offset < buffersize)
|
|
{
|
|
if (buffer[*offset] == '\n')
|
|
{
|
|
*offset += 1;
|
|
}
|
|
|
|
getnextvalidline(buffer, buffersize, offset);
|
|
}
|
|
|
|
return ' ';
|
|
break;
|
|
case '\t':
|
|
*offset += 1;
|
|
return ' ';
|
|
break;
|
|
case '\n':
|
|
*offset += 1;
|
|
getnextvalidline(buffer, buffersize, offset);
|
|
return ' ';
|
|
break;
|
|
case '-':
|
|
if (buffer[*offset + 1] == '-')
|
|
{
|
|
while ((*offset < buffersize) && buffer[*offset] != 0 && buffer[*offset] != '\r' && buffer[*offset] != '\n')
|
|
{
|
|
*offset += 1;
|
|
}
|
|
|
|
if (*offset < buffersize)
|
|
{
|
|
if (buffer[*offset] == '\r')
|
|
{
|
|
*offset += 1;
|
|
if (buffer[*offset] == '\n')
|
|
{
|
|
*offset += 1;
|
|
}
|
|
|
|
getnextvalidline(buffer, buffersize, offset);
|
|
|
|
return ' ';
|
|
}
|
|
|
|
if (buffer[*offset] == '\n')
|
|
{
|
|
*offset += 1;
|
|
getnextvalidline(buffer, buffersize, offset);
|
|
|
|
return ' ';
|
|
}
|
|
}
|
|
else
|
|
return 0;
|
|
|
|
return ' ';
|
|
}
|
|
else
|
|
{
|
|
*offset += 1;
|
|
return '-';
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
*offset += 1;
|
|
return c;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int extract_bsdl_lines(char * bsdl_txt, char ** lines)
|
|
{
|
|
int offset;
|
|
int line_start_offset;
|
|
int line_end_offset;
|
|
int endofline;
|
|
int parenthesis_number;
|
|
int inside_quote;
|
|
int number_of_lines;
|
|
|
|
offset = 0;
|
|
number_of_lines = 0;
|
|
|
|
do
|
|
{
|
|
// Find the first word offset into the line...
|
|
while( bsdl_txt[offset] ==' ' && bsdl_txt[offset] )
|
|
{
|
|
offset++;
|
|
}
|
|
|
|
line_start_offset = offset;
|
|
|
|
parenthesis_number = 0;
|
|
endofline = 0;
|
|
inside_quote = 0;
|
|
|
|
// Scan the line
|
|
while( !endofline )
|
|
{
|
|
switch( bsdl_txt[offset] )
|
|
{
|
|
case 0:
|
|
endofline = 1;
|
|
break;
|
|
|
|
case '(':
|
|
if( !inside_quote )
|
|
parenthesis_number++;
|
|
offset++;
|
|
break;
|
|
case ')':
|
|
if(parenthesis_number && !inside_quote)
|
|
parenthesis_number--;
|
|
offset++;
|
|
break;
|
|
case ';':
|
|
if( !parenthesis_number && !inside_quote )
|
|
{
|
|
line_end_offset = offset;
|
|
|
|
if( line_end_offset - line_start_offset > 0 )
|
|
{
|
|
if(lines)
|
|
{
|
|
lines[number_of_lines] = malloc( (line_end_offset - line_start_offset) + 2 );
|
|
if( lines[number_of_lines] )
|
|
{
|
|
memset(lines[number_of_lines],0, (line_end_offset - line_start_offset) + 2 );
|
|
memcpy(lines[number_of_lines],&bsdl_txt[line_start_offset], (line_end_offset - line_start_offset) );
|
|
}
|
|
}
|
|
|
|
number_of_lines++;
|
|
}
|
|
|
|
endofline = 1;
|
|
|
|
}
|
|
offset++;
|
|
break;
|
|
|
|
case '"':
|
|
if(!inside_quote)
|
|
inside_quote = 1;
|
|
else
|
|
inside_quote = 0;
|
|
|
|
offset++;
|
|
break;
|
|
|
|
default:
|
|
offset++;
|
|
break;
|
|
}
|
|
}
|
|
}while(bsdl_txt[offset]);
|
|
|
|
return number_of_lines;
|
|
}
|
|
|
|
void preprocess_line(char * line)
|
|
{
|
|
int inside_quote;
|
|
int read_offset,write_offset;
|
|
int is_string;
|
|
int number_of_spaces;
|
|
|
|
inside_quote = 0;
|
|
read_offset = 0;
|
|
write_offset = 0;
|
|
number_of_spaces = 0;
|
|
|
|
if(!line)
|
|
return;
|
|
|
|
// first pass : remove extra blank
|
|
while( line[read_offset] )
|
|
{
|
|
switch( line[read_offset] )
|
|
{
|
|
case ' ':
|
|
|
|
if(!number_of_spaces || inside_quote)
|
|
{
|
|
line[write_offset] = line[read_offset];
|
|
write_offset++;
|
|
}
|
|
|
|
read_offset++;
|
|
number_of_spaces++;
|
|
|
|
break;
|
|
|
|
case '"':
|
|
if(!inside_quote)
|
|
inside_quote = 1;
|
|
else
|
|
inside_quote = 0;
|
|
|
|
line[write_offset] = line[read_offset];
|
|
write_offset++;
|
|
read_offset++;
|
|
number_of_spaces = 0;
|
|
|
|
break;
|
|
|
|
default:
|
|
line[write_offset] = line[read_offset];
|
|
number_of_spaces = 0;
|
|
|
|
write_offset++;
|
|
read_offset++;
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
line[write_offset] = 0;
|
|
|
|
// second pass : concatenate strings.
|
|
|
|
inside_quote = 0;
|
|
read_offset = 0;
|
|
write_offset = 0;
|
|
number_of_spaces = 0;
|
|
is_string = 0;
|
|
|
|
while( line[read_offset] )
|
|
{
|
|
switch( line[read_offset] )
|
|
{
|
|
|
|
case '&':
|
|
if( inside_quote || !is_string)
|
|
{
|
|
line[write_offset] = line[read_offset];
|
|
write_offset++;
|
|
}
|
|
read_offset++;
|
|
break;
|
|
|
|
case ' ':
|
|
if( inside_quote || !is_string)
|
|
{
|
|
line[write_offset] = line[read_offset];
|
|
write_offset++;
|
|
}
|
|
read_offset++;
|
|
break;
|
|
|
|
case '"':
|
|
if(!inside_quote)
|
|
{
|
|
inside_quote = 1;
|
|
if( !is_string )
|
|
{
|
|
line[write_offset] = line[read_offset];
|
|
write_offset++;
|
|
}
|
|
|
|
is_string = 1;
|
|
}
|
|
else
|
|
{
|
|
inside_quote = 0;
|
|
|
|
}
|
|
|
|
read_offset++;
|
|
break;
|
|
|
|
default:
|
|
if( !inside_quote )
|
|
{
|
|
if( is_string )
|
|
{
|
|
line[write_offset] = '"';
|
|
write_offset++;
|
|
}
|
|
is_string = 0;
|
|
}
|
|
|
|
line[write_offset] = line[read_offset];
|
|
|
|
write_offset++;
|
|
read_offset++;
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
if( is_string )
|
|
{
|
|
line[write_offset] = '"';
|
|
write_offset++;
|
|
line[write_offset] = 0;
|
|
}
|
|
};
|
|
|
|
char * check_next_keyword(char * buffer, char * keyword, char sep)
|
|
{
|
|
int i;
|
|
char sep_list[16];
|
|
|
|
sep_list[0] = sep;
|
|
sep_list[1] = '\0';
|
|
strcat((char*)sep_list,"\"() ");
|
|
|
|
if( !buffer )
|
|
return 0;
|
|
|
|
// skip the current word
|
|
i = 0;
|
|
while (buffer[i] && !strchr(sep_list, buffer[i]) )
|
|
{
|
|
i++;
|
|
}
|
|
|
|
// skip the following blank
|
|
while (buffer[i] && strchr(sep_list, buffer[i]) )
|
|
{
|
|
i++;
|
|
}
|
|
|
|
if( !strncmp(&buffer[i],keyword,strlen(keyword)) )
|
|
{
|
|
return &buffer[i + strlen(keyword)];
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int get_next_keyword(jtag_core * jc,char * buffer, char * keyword)
|
|
{
|
|
int i,j;
|
|
|
|
if( !buffer )
|
|
return 0;
|
|
|
|
// skip the current word
|
|
i = 0;
|
|
while (buffer[i] && !strchr("\"():, ", buffer[i]) )
|
|
{
|
|
i++;
|
|
}
|
|
|
|
// skip the following blank
|
|
while (buffer[i] && strchr("\"():, ", buffer[i]))
|
|
{
|
|
i++;
|
|
}
|
|
|
|
// copy the word
|
|
j = 0;
|
|
while (buffer[i] && !strchr("\"():;, ", buffer[i]))
|
|
{
|
|
if(j < MAX_ELEMENT_SIZE-1)
|
|
{
|
|
keyword[j] = buffer[i];
|
|
j++;
|
|
}
|
|
i++;
|
|
}
|
|
|
|
keyword[j] = 0;
|
|
|
|
if( j >= (MAX_ELEMENT_SIZE-1) )
|
|
{
|
|
jtagcore_logs_printf(jc,MSG_WARNING,"BSDL loader / get_next_keyword : element too long / truncated : %s\r\n",keyword);
|
|
}
|
|
|
|
return i;
|
|
}
|
|
|
|
int get_next_parameter(jtag_core * jc,char * buffer, char * parameter)
|
|
{
|
|
int i,j;
|
|
|
|
if( !buffer )
|
|
return 0;
|
|
|
|
// skip the current word
|
|
i = 0;
|
|
while (buffer[i] && !strchr("\":, ", buffer[i]))
|
|
{
|
|
i++;
|
|
}
|
|
|
|
// skip the following blank
|
|
while (buffer[i] && strchr("\":, ", buffer[i]))
|
|
{
|
|
i++;
|
|
}
|
|
|
|
// copy the word
|
|
j = 0;
|
|
while (buffer[i] && !strchr("\":, ;", buffer[i]))
|
|
{
|
|
if(j < MAX_ELEMENT_SIZE-1)
|
|
{
|
|
parameter[j] = buffer[i];
|
|
j++;
|
|
}
|
|
i++;
|
|
}
|
|
|
|
parameter[j] = 0;
|
|
|
|
if( j >= (MAX_ELEMENT_SIZE-1) )
|
|
{
|
|
jtagcore_logs_printf(jc,MSG_WARNING,"BSDL loader / get_next_parameter : element too long / truncated : %s\r\n",parameter);
|
|
}
|
|
|
|
return i;
|
|
}
|
|
|
|
int check_next_symbol(char * buffer, char c )
|
|
{
|
|
int i;
|
|
|
|
if( !buffer )
|
|
return 0;
|
|
|
|
// skip the current word
|
|
i = 0;
|
|
while (buffer[i] && !strchr("\"(): ", buffer[i]) && buffer[i] != c)
|
|
{
|
|
i++;
|
|
}
|
|
|
|
// skip the following blank
|
|
while(buffer[i] && ( buffer[i] == ' ') )
|
|
{
|
|
i++;
|
|
}
|
|
|
|
if( buffer[i] == c )
|
|
{
|
|
return i;
|
|
}
|
|
else
|
|
{
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
char * get_attribut(char ** lines,char * name, char * entity)
|
|
{
|
|
int i,j;
|
|
char * ptr;
|
|
i = 0;
|
|
|
|
while( lines[i] )
|
|
{
|
|
if(!strncmp(lines[i],"attribute ",10))
|
|
{
|
|
if(!strncmp(&lines[i][10],name,strlen(name)))
|
|
{
|
|
ptr = check_next_keyword(&lines[i][10], "of", '\0');
|
|
ptr = check_next_keyword(ptr, entity, ':');
|
|
|
|
if( ptr )
|
|
{
|
|
j = 0;
|
|
while( ptr[j] && ptr[j] != ':' && ptr[j] == ' ')
|
|
{
|
|
j++;
|
|
}
|
|
|
|
if( ptr[j] == ':' )
|
|
{
|
|
ptr = check_next_keyword(&ptr[j], "entity", ':');
|
|
ptr = check_next_keyword(ptr, "is", '\0');
|
|
|
|
return ptr;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
}
|
|
i++;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
char * get_attribut_txt(char ** lines,char * name, char * entity)
|
|
{
|
|
int i;
|
|
char * attribut_data;
|
|
|
|
attribut_data = get_attribut(lines,name, entity);
|
|
|
|
if( attribut_data )
|
|
{
|
|
i = 0;
|
|
while( attribut_data[i] && attribut_data[i]!='"')
|
|
{
|
|
i++;
|
|
}
|
|
|
|
if( attribut_data[i] == '"' )
|
|
{
|
|
return &attribut_data[i];
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int get_attribut_int(char ** lines,char * name, char * entity)
|
|
{
|
|
int i;
|
|
char * attribut_data;
|
|
|
|
attribut_data = get_attribut(lines,name, entity);
|
|
|
|
if( attribut_data )
|
|
{
|
|
i = 0;
|
|
while( attribut_data[i] && !( attribut_data[i]>='0' && attribut_data[i]<='9' ) )
|
|
{
|
|
i++;
|
|
}
|
|
|
|
if( ( attribut_data[i]>='0' && attribut_data[i]<='9' ) )
|
|
{
|
|
return atoi(&attribut_data[i]);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int get_next_pin(jtag_core * jc,char * name,int * type, char *line, int * start_index, int * end_index )
|
|
{
|
|
int i;
|
|
int io_list_offset;
|
|
char tmp_str[256];
|
|
int line_parsed,inside_block;
|
|
|
|
i = get_next_keyword(jc,line,name);
|
|
|
|
io_list_offset = 0;
|
|
|
|
while(line[i] == ' ')
|
|
i++;
|
|
|
|
if( line[i] == ':' || line[i] == ',' )
|
|
{
|
|
*start_index = 0;
|
|
*end_index = 0;
|
|
|
|
if( line[i] == ',' )
|
|
{
|
|
io_list_offset = i + 1;
|
|
|
|
while(line[i] != ':' && line[i] != ';' && line[i])
|
|
i++;
|
|
if( line[i] != ':' )
|
|
return 0;
|
|
}
|
|
|
|
i += get_next_keyword(jc,&line[i],(char*)&tmp_str);
|
|
|
|
string_upper(tmp_str);
|
|
|
|
*type = get_typecode(pintype_str,tmp_str);
|
|
|
|
i += get_next_keyword(jc,&line[i],(char*)&tmp_str);
|
|
|
|
if (!strcmp_nocase("bit_vector",tmp_str))
|
|
{
|
|
while(line[i] != '(' && line[i] != ')' && line[i] != ';')
|
|
{
|
|
i++;
|
|
}
|
|
|
|
line_parsed = 0;
|
|
inside_block = 0;
|
|
|
|
do
|
|
{
|
|
|
|
switch( line[i] )
|
|
{
|
|
case '(':
|
|
inside_block++;
|
|
if(!line_parsed)
|
|
{
|
|
i += get_next_keyword(jc,&line[i],(char*)&tmp_str);
|
|
*start_index = atoi(tmp_str);
|
|
|
|
i += get_next_keyword(jc,&line[i],(char*)&tmp_str);
|
|
|
|
i += get_next_keyword(jc,&line[i],(char*)&tmp_str);
|
|
*end_index = atoi(tmp_str);
|
|
|
|
line_parsed = 1;
|
|
|
|
}
|
|
break;
|
|
case ')':
|
|
if ( !inside_block )
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
inside_block--;
|
|
break;
|
|
case ';':
|
|
if( io_list_offset )
|
|
return io_list_offset;
|
|
else
|
|
return i;
|
|
break;
|
|
case 0:
|
|
break;
|
|
|
|
}
|
|
i++;
|
|
}while (line[i]);
|
|
|
|
return 0;
|
|
}
|
|
|
|
if (!strcmp_nocase("bit",tmp_str))
|
|
{
|
|
do
|
|
{
|
|
switch( line[i] )
|
|
{
|
|
case ';':
|
|
if( io_list_offset )
|
|
return io_list_offset;
|
|
else
|
|
return i;
|
|
break;
|
|
case 0:
|
|
break;
|
|
}
|
|
i++;
|
|
}while (line[i]);
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int get_pins_list(jtag_core * jc,jtag_bsdl * bsdl_desc,char ** lines)
|
|
{
|
|
int i,j,k,inc,offset, number_of_pins,vector_size;
|
|
char tmp_str[MAX_ELEMENT_SIZE];
|
|
int tmp_type,tmp_start,tmp_end;
|
|
i = 0;
|
|
|
|
while( lines[i] )
|
|
{
|
|
if( !strncmp(lines[i],"port ",5) || !strncmp(lines[i],"port(",5))
|
|
{
|
|
j = 0;
|
|
number_of_pins = 0;
|
|
|
|
while( lines[i][j] != '(' && lines[i][j])
|
|
{
|
|
j++;
|
|
}
|
|
|
|
do
|
|
{
|
|
offset = get_next_pin(jc,(char*)&tmp_str,&tmp_type, &lines[i][j], &tmp_start, &tmp_end );
|
|
|
|
if( tmp_start <=tmp_end)
|
|
{
|
|
number_of_pins += ( (tmp_end - tmp_start) + 1 );
|
|
}
|
|
else
|
|
{
|
|
number_of_pins += ( (tmp_start - tmp_end) + 1 );
|
|
}
|
|
|
|
j += offset;
|
|
|
|
} while( offset);
|
|
|
|
if (number_of_pins == 0 || ( number_of_pins > MAX_NUMBER_PINS_PER_DEV ) )
|
|
{
|
|
jtagcore_logs_printf(jc, MSG_ERROR, "get_pins_list : bad number of pin found ! : %d\r\n", number_of_pins);
|
|
return -1;
|
|
}
|
|
|
|
bsdl_desc->pins_list = malloc (sizeof(pin_ctrl) * (number_of_pins+1));
|
|
if( bsdl_desc->pins_list )
|
|
{
|
|
memset( bsdl_desc->pins_list, 0, sizeof(pin_ctrl) * (number_of_pins+1) );
|
|
|
|
j = 0;
|
|
number_of_pins = 0;
|
|
|
|
while( lines[i][j] != '(' && lines[i][j])
|
|
{
|
|
j++;
|
|
}
|
|
|
|
do
|
|
{
|
|
offset = get_next_pin(jc,(char*)&tmp_str,&tmp_type, &lines[i][j], &tmp_start, &tmp_end );
|
|
|
|
if( tmp_start <= tmp_end )
|
|
{
|
|
vector_size = ( (tmp_end - tmp_start) + 1 );
|
|
inc = 1;
|
|
}
|
|
else
|
|
{
|
|
vector_size = ( (tmp_start - tmp_end) + 1 );
|
|
inc = -1;
|
|
}
|
|
|
|
j += offset;
|
|
|
|
for(k = 0;k < vector_size; k++)
|
|
{
|
|
snprintf((char*)&bsdl_desc->pins_list[number_of_pins].pinname,sizeof(((pin_ctrl *)0)->pinname),"%s",(char*)tmp_str);
|
|
|
|
if( vector_size > 1 )
|
|
{
|
|
char digistr[32];
|
|
snprintf((char*)digistr,sizeof(digistr),"(%d)",tmp_start);
|
|
genos_strndstcat((char*)&bsdl_desc->pins_list[number_of_pins].pinname,digistr,sizeof(((pin_ctrl *)0)->pinname));
|
|
}
|
|
bsdl_desc->pins_list[number_of_pins].pinname[sizeof(((pin_ctrl *)0)->pinname)-1] = '\0';
|
|
|
|
bsdl_desc->pins_list[number_of_pins].pintype = tmp_type;
|
|
number_of_pins++;
|
|
tmp_start += inc;
|
|
}
|
|
|
|
} while( offset );
|
|
|
|
bsdl_desc->number_of_pins = number_of_pins;
|
|
|
|
return number_of_pins;
|
|
}
|
|
}
|
|
i++;
|
|
};
|
|
|
|
return 0;
|
|
}
|
|
|
|
int get_jtag_chain(jtag_core * jc,jtag_bsdl * bsdl_desc,char ** lines, char * entityname)
|
|
{
|
|
char * jtagchain_str;
|
|
int i,j,bit_count,end_parse;
|
|
char tmp_str[MAX_ELEMENT_SIZE];
|
|
int bit_index;
|
|
|
|
bit_count = 0;
|
|
bsdl_desc->number_of_chainbits = get_attribut_int(lines,"BOUNDARY_LENGTH", entityname);
|
|
if ( ( bsdl_desc->number_of_chainbits > 0 ) && ( bsdl_desc->number_of_chainbits < MAX_NUMBER_BITS_IN_CHAIN ) )
|
|
{
|
|
jtagcore_logs_printf(jc,MSG_DEBUG,"Number of bit in the chain = %d\r\n",bsdl_desc->number_of_chainbits);
|
|
|
|
bsdl_desc->chain_list = malloc( sizeof(jtag_chain) * bsdl_desc->number_of_chainbits );
|
|
if( !bsdl_desc->chain_list )
|
|
{
|
|
jtagcore_logs_printf(jc,MSG_ERROR,"get_jtag_chain : memory alloc error !\r\n");
|
|
return -1;
|
|
}
|
|
|
|
memset(bsdl_desc->chain_list,0, sizeof(jtag_chain) * bsdl_desc->number_of_chainbits );
|
|
|
|
jtagchain_str = get_attribut_txt(lines,"BOUNDARY_REGISTER", entityname);
|
|
|
|
end_parse = 0;
|
|
|
|
if(jtagchain_str)
|
|
{
|
|
if( jtagchain_str[0] == '"' )
|
|
{
|
|
i = 0;
|
|
while( jtagchain_str[i] && !end_parse )
|
|
{
|
|
jtagcore_logs_printf(jc,MSG_DEBUG,"--------------\r\n");
|
|
|
|
// Get index
|
|
i += get_next_keyword(jc,&jtagchain_str[i], tmp_str);
|
|
bit_index = atoi(tmp_str);
|
|
if (bit_index >= 0 && bit_index < bsdl_desc->number_of_chainbits)
|
|
{
|
|
bsdl_desc->chain_list[bit_index].bit_index = bit_index;
|
|
|
|
jtagcore_logs_printf(jc, MSG_DEBUG, "%d\r\n", bsdl_desc->chain_list[bit_index].bit_index);
|
|
|
|
// Look for (
|
|
while (jtagchain_str[i] != '(' && jtagchain_str[i])
|
|
i++;
|
|
|
|
// Get the pin type
|
|
i += get_next_keyword(jc,&jtagchain_str[i], tmp_str);
|
|
string_upper(tmp_str);
|
|
bsdl_desc->chain_list[bit_index].bit_cell_type = get_typecode(celltype_str, tmp_str);
|
|
|
|
jtagcore_logs_printf(jc, MSG_DEBUG, "%d\r\n", bsdl_desc->chain_list[bit_index].bit_cell_type);
|
|
|
|
// ,
|
|
j = check_next_symbol(&jtagchain_str[i], ',');
|
|
if (j < 0)
|
|
return -1;
|
|
i += j;
|
|
|
|
// Get the name
|
|
i += get_next_parameter(jc,&jtagchain_str[i], bsdl_desc->chain_list[bit_index].pinname);
|
|
|
|
jtagcore_logs_printf(jc, MSG_DEBUG, "%s\r\n", bsdl_desc->chain_list[bit_index].pinname);
|
|
|
|
// ,
|
|
j = check_next_symbol(&jtagchain_str[i], ',');
|
|
if (j < 0)
|
|
return -1;
|
|
i += j;
|
|
|
|
// Get the type
|
|
i += get_next_keyword(jc,&jtagchain_str[i], tmp_str);
|
|
string_upper(tmp_str);
|
|
bsdl_desc->chain_list[bit_index].bit_type = get_typecode(bittype_str, tmp_str);
|
|
|
|
jtagcore_logs_printf(jc, MSG_DEBUG, "%s , %d\r\n", tmp_str, bsdl_desc->chain_list[bit_index].bit_type);
|
|
|
|
// ,
|
|
j = check_next_symbol(&jtagchain_str[i], ',');
|
|
if (j < 0)
|
|
return -1;
|
|
i += j;
|
|
|
|
// Get the default state
|
|
i += get_next_keyword(jc,&jtagchain_str[i], tmp_str);
|
|
string_upper(tmp_str);
|
|
bsdl_desc->chain_list[bit_index].safe_state = get_typecode(statetype_str, tmp_str);
|
|
|
|
bsdl_desc->chain_list[bit_index].control_bit_index = -1;
|
|
|
|
// If no ) Get the ctrl index
|
|
j = check_next_symbol(&jtagchain_str[i], ')');
|
|
|
|
if (jtagchain_str[i]==',' || j < 0)
|
|
{
|
|
// ,
|
|
j = check_next_symbol(&jtagchain_str[i], ',');
|
|
if (j < 0)
|
|
return -1;
|
|
i += j;
|
|
|
|
// Get the control bit
|
|
i += get_next_keyword(jc,&jtagchain_str[i], tmp_str);
|
|
|
|
bsdl_desc->chain_list[bit_index].control_bit_index = atoi(tmp_str);
|
|
|
|
j = check_next_symbol(&jtagchain_str[i], ',');
|
|
if (j < 0)
|
|
return -1;
|
|
i += j;
|
|
|
|
// Get the polarity
|
|
i += get_next_keyword(jc,&jtagchain_str[i], tmp_str);
|
|
string_upper(tmp_str);
|
|
bsdl_desc->chain_list[bit_index].control_disable_state = get_typecode(statetype_str, tmp_str);
|
|
|
|
j = check_next_symbol(&jtagchain_str[i], ',');
|
|
if (j < 0)
|
|
return -1;
|
|
i += j;
|
|
|
|
// Get the off state
|
|
i += get_next_keyword(jc,&jtagchain_str[i], tmp_str);
|
|
string_upper(tmp_str);
|
|
bsdl_desc->chain_list[bit_index].control_disable_result = get_typecode(statetype_str, tmp_str);
|
|
|
|
// Find and skip )
|
|
j = check_next_symbol(&jtagchain_str[i], ')');
|
|
if (j < 0)
|
|
return -1;
|
|
}
|
|
|
|
i += j;
|
|
|
|
// Find , (Next bit) or " (End of the chain)
|
|
i++;
|
|
bit_count++;
|
|
|
|
if (check_next_symbol(&jtagchain_str[i], '"') >= 0)
|
|
{
|
|
end_parse = 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
jtagcore_logs_printf(jc, MSG_ERROR, "get_jtag_chain : Error bit index overrun !\r\n");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if( ( bit_count == bsdl_desc->number_of_chainbits ) && ( bsdl_desc->number_of_chainbits != 0 ) )
|
|
{
|
|
jtagcore_logs_printf(jc,MSG_DEBUG,"Jtag chain parsing Ok !\r\n");
|
|
|
|
for( i = 0 ; i < (long)bsdl_desc->number_of_pins ; i++ )
|
|
{
|
|
|
|
bsdl_desc->pins_list[i].in_bit_number = -1;
|
|
bsdl_desc->pins_list[i].out_bit_number = -1;
|
|
bsdl_desc->pins_list[i].ctrl_bit_number = -1;
|
|
|
|
switch( bsdl_desc->pins_list[i].pintype)
|
|
{
|
|
case IO_IN:
|
|
case IO_OUT:
|
|
case IO_INOUT:
|
|
|
|
for( j = 0 ; j < (long)bsdl_desc->number_of_chainbits ; j++ )
|
|
{
|
|
if(!strcmp(bsdl_desc->chain_list[j].pinname, bsdl_desc->pins_list[i].pinname))
|
|
{
|
|
switch( bsdl_desc->chain_list[j].bit_type)
|
|
{
|
|
case BITTYPE_INPUT:
|
|
bsdl_desc->pins_list[i].in_bit_number = bsdl_desc->chain_list[j].bit_index;
|
|
break;
|
|
case BITTYPE_OUTPUT:
|
|
bsdl_desc->pins_list[i].out_bit_number = bsdl_desc->chain_list[j].bit_index;
|
|
break;
|
|
case BITTYPE_TRISTATE_OUTPUT:
|
|
bsdl_desc->pins_list[i].out_bit_number = bsdl_desc->chain_list[j].bit_index;
|
|
bsdl_desc->pins_list[i].ctrl_bit_number = bsdl_desc->chain_list[j].control_bit_index;
|
|
break;
|
|
case BITTYPE_INOUT:
|
|
bsdl_desc->pins_list[i].in_bit_number = bsdl_desc->chain_list[j].bit_index;
|
|
bsdl_desc->pins_list[i].out_bit_number = bsdl_desc->chain_list[j].bit_index;
|
|
bsdl_desc->pins_list[i].ctrl_bit_number = bsdl_desc->chain_list[j].control_bit_index;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
jtagcore_logs_printf(jc,MSG_DEBUG,"JTAG chain parsing error : %d - %d !\r\n",bit_count,bsdl_desc->number_of_chainbits);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
static int compare_pin_name(const void *a, const void *b)
|
|
{
|
|
int ret;
|
|
pin_ctrl const *pa = (pin_ctrl const *)a;
|
|
pin_ctrl const *pb = (pin_ctrl const *)b;
|
|
|
|
ret = strnatcmp(pa->pinname, pb->pinname);
|
|
|
|
return ret;
|
|
}
|
|
|
|
jtag_bsdl * load_bsdlfile(jtag_core * jc,char *filename)
|
|
{
|
|
FILE * bsdl_file;
|
|
jtag_bsdl * bsdl;
|
|
int file_size,offset;
|
|
char * bsdl_txt,*tmp_bsdl_txt;
|
|
char * tmp_ptr;
|
|
int i,number_of_bsdl_lines;
|
|
char entityname[256];
|
|
char * chipid_str,* instruct_str;
|
|
char * instruct_strchr;
|
|
char ** lines;
|
|
|
|
jtagcore_logs_printf(jc,MSG_INFO_0,"Open BSDL file %s\r\n",filename);
|
|
|
|
bsdl = 0;
|
|
|
|
bsdl_file = fopen(filename,"rb");
|
|
if (bsdl_file)
|
|
{
|
|
fseek(bsdl_file, 0, SEEK_END);
|
|
file_size = ftell(bsdl_file);
|
|
fseek(bsdl_file, 0, SEEK_SET);
|
|
|
|
if ( file_size <= 0 || file_size > MAX_BSDL_FILE_SIZE )
|
|
{
|
|
jtagcore_logs_printf(jc, MSG_ERROR, "Bad BSDL File size ! : %d\r\n", file_size);
|
|
fclose(bsdl_file);
|
|
return 0;
|
|
}
|
|
|
|
jtagcore_logs_printf(jc, MSG_DEBUG, "BSDL file size : %d\r\n", file_size);
|
|
|
|
bsdl_txt = malloc(file_size + 1);
|
|
if (bsdl_txt)
|
|
{
|
|
memset(bsdl_txt, 0, file_size + 1);
|
|
if( fread(bsdl_txt, file_size, 1, bsdl_file) != 1 )
|
|
{
|
|
free(bsdl_txt);
|
|
jtagcore_logs_printf(jc, MSG_ERROR, "BSDL File read error !\r\n");
|
|
fclose(bsdl_file);
|
|
return 0;
|
|
}
|
|
|
|
tmp_bsdl_txt = malloc(file_size + 1);
|
|
if (tmp_bsdl_txt)
|
|
{
|
|
memset(tmp_bsdl_txt, 0, file_size + 1);
|
|
offset = 0;
|
|
|
|
i = 0;
|
|
while (offset < file_size && i < file_size)
|
|
{
|
|
tmp_bsdl_txt[i] = getnextchar(bsdl_txt, file_size, &offset);
|
|
i++;
|
|
}
|
|
|
|
free(bsdl_txt);
|
|
|
|
if (offset < i)
|
|
{
|
|
jtagcore_logs_printf(jc, MSG_ERROR, "Preprocessing error !\r\n");
|
|
free(tmp_bsdl_txt);
|
|
return 0;
|
|
}
|
|
|
|
bsdl_txt = tmp_bsdl_txt;
|
|
}
|
|
else
|
|
{
|
|
jtagcore_logs_printf(jc, MSG_ERROR, "Can't allocate file memory !\r\n");
|
|
free(bsdl_txt);
|
|
fclose(bsdl_file);
|
|
return 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
jtagcore_logs_printf(jc, MSG_ERROR, "Can't allocate file memory !\r\n");
|
|
fclose(bsdl_file);
|
|
return 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
jtagcore_logs_printf(jc, MSG_ERROR, "Can't open %s !\r\n", filename);
|
|
return 0;
|
|
}
|
|
|
|
fclose(bsdl_file);
|
|
|
|
// Get the first entity offset
|
|
tmp_ptr = strstr(bsdl_txt,"entity");
|
|
if (!tmp_ptr)
|
|
{
|
|
jtagcore_logs_printf(jc, MSG_ERROR, "entry \"entity\" not found !\r\n");
|
|
free(bsdl_txt);
|
|
return 0;
|
|
}
|
|
|
|
offset = tmp_ptr - bsdl_txt;
|
|
|
|
// skip the entity keyword
|
|
while( bsdl_txt[offset] !=' ' && bsdl_txt[offset] )
|
|
offset++;
|
|
|
|
// skip the blank spaces
|
|
while( bsdl_txt[offset] ==' ' && bsdl_txt[offset] )
|
|
offset++;
|
|
|
|
// copy the entity name
|
|
i = 0;
|
|
memset(entityname,0,sizeof(entityname));
|
|
while( bsdl_txt[offset] !=' ' && bsdl_txt[offset] && i < ( sizeof(entityname) - 1 ))
|
|
{
|
|
entityname[i] = bsdl_txt[offset];
|
|
|
|
offset++;
|
|
i++;
|
|
}
|
|
|
|
// skip the blank spaces
|
|
while( bsdl_txt[offset] ==' ' && bsdl_txt[offset] )
|
|
offset++;
|
|
|
|
// Check the "is" keyword presence
|
|
if( strncmp(&bsdl_txt[offset],"is",2) )
|
|
{
|
|
jtagcore_logs_printf(jc, MSG_ERROR, "Bad entity entry (\"is\" not found)\r\n");
|
|
free(bsdl_txt);
|
|
return 0;
|
|
}
|
|
|
|
jtagcore_logs_printf(jc,MSG_DEBUG,"Entity : %s\r\n",entityname);
|
|
|
|
offset += 2;
|
|
|
|
// extract and separate each bsdl line
|
|
number_of_bsdl_lines = extract_bsdl_lines(&bsdl_txt[offset],0);
|
|
jtagcore_logs_printf(jc,MSG_DEBUG,"lines :%d\r\n",number_of_bsdl_lines);
|
|
|
|
if (number_of_bsdl_lines <= 0 || number_of_bsdl_lines > MAX_NUMBER_OF_BSDL_LINES)
|
|
{
|
|
jtagcore_logs_printf(jc, MSG_ERROR, "No line found !\r\n");
|
|
free(bsdl_txt);
|
|
return 0;
|
|
}
|
|
|
|
lines = malloc( sizeof(char*) * ( number_of_bsdl_lines + 1 ) );
|
|
if( !lines )
|
|
{
|
|
jtagcore_logs_printf(jc,MSG_ERROR,"load_bsdlfile : memory alloc error !\r\n");
|
|
free(tmp_bsdl_txt);
|
|
return 0;
|
|
}
|
|
|
|
memset( lines, 0, sizeof(char*) * ( number_of_bsdl_lines + 1 ) );
|
|
|
|
extract_bsdl_lines(&bsdl_txt[offset],lines);
|
|
|
|
for(i= 0 ;i< number_of_bsdl_lines;i++)
|
|
{
|
|
preprocess_line(lines[i]);
|
|
}
|
|
|
|
bsdl = malloc ( sizeof(jtag_bsdl) );
|
|
if (!bsdl)
|
|
{
|
|
jtagcore_logs_printf(jc, MSG_ERROR, "load_bsdlfile : memory alloc error !\r\n");
|
|
for( i = 0 ;i < number_of_bsdl_lines ; i++ )
|
|
{
|
|
if(lines[i])
|
|
{
|
|
free(lines[i]);
|
|
lines[i] = 0;
|
|
}
|
|
}
|
|
free(lines);
|
|
|
|
free(bsdl_txt);
|
|
|
|
return 0;
|
|
}
|
|
|
|
memset( bsdl , 0 , sizeof(jtag_bsdl) );
|
|
|
|
///////////////////////
|
|
// copy the entity name & the file name
|
|
strncpy(bsdl->entity_name,entityname,sizeof(((jtag_bsdl *)0)->entity_name) - 1);
|
|
bsdl->entity_name[ sizeof(((jtag_bsdl *)0)->entity_name) - 1 ] = '\0';
|
|
|
|
i = strlen(filename);
|
|
while(i && filename[i] != '\\')
|
|
{
|
|
i--;
|
|
}
|
|
|
|
if(filename[i] == '\\')
|
|
i++;
|
|
|
|
strncpy(bsdl->src_filename,&filename[i],sizeof(bsdl->src_filename) - 1);
|
|
bsdl->src_filename[ sizeof(bsdl->src_filename) - 1 ] = '0';
|
|
|
|
///////////////////////
|
|
// Extract the chip ID
|
|
bsdl->chip_id = 0x00000000;
|
|
bsdl->chip_id_mask = 0xFFFFFFFF;
|
|
|
|
chipid_str = get_attribut_txt(lines,"IDCODE_REGISTER", entityname);
|
|
if(chipid_str)
|
|
{
|
|
if( chipid_str[0] == '"' )
|
|
{
|
|
chipid_str++;
|
|
i = 0;
|
|
while(chipid_str[i]!='"' && chipid_str[i]!=';' && chipid_str[i] && i < 32)
|
|
{
|
|
switch( chipid_str[i] )
|
|
{
|
|
case '0':
|
|
bsdl->chip_id &= ~(0x80000000 >> i);
|
|
break;
|
|
|
|
case '1':
|
|
bsdl->chip_id |= (0x80000000 >> i);
|
|
break;
|
|
|
|
case 'x':
|
|
case 'X':
|
|
bsdl->chip_id_mask &= ~(0x80000000 >> i);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
i++;
|
|
}
|
|
}
|
|
}
|
|
|
|
jtagcore_logs_printf(jc,MSG_INFO_0,"ID Code: 0x%.8X\r\n",bsdl->chip_id);
|
|
|
|
///////////////////////
|
|
// Extract the pins list
|
|
get_pins_list(jc,bsdl,lines);
|
|
|
|
///////////////////////
|
|
// Extract the JTAG Chain
|
|
if(get_jtag_chain(jc,bsdl,lines,entityname)<0)
|
|
{
|
|
jtagcore_logs_printf(jc,MSG_ERROR,"load_bsdlfile : Error during jtag chain parsing !\r\n");
|
|
}
|
|
|
|
if(jtagcore_getEnvVarValue( jc, "BSDL_LOADER_SORT_PINS_NAME" ) > 0)
|
|
{
|
|
// Count the pins
|
|
i = 0;
|
|
while(bsdl->pins_list[i].pinname[0])
|
|
{
|
|
i++;
|
|
}
|
|
|
|
// Sort them
|
|
qsort(bsdl->pins_list, i, sizeof bsdl->pins_list[0], compare_pin_name);
|
|
}
|
|
|
|
if(bsdl->pins_list)
|
|
{
|
|
i = 0;
|
|
while(bsdl->pins_list[i].pinname[0])
|
|
{
|
|
char dbg_str[512];
|
|
int namelen,j,k;
|
|
char disval;
|
|
|
|
namelen = strlen(bsdl->pins_list[i].pinname);
|
|
|
|
sprintf(dbg_str,"Pin %s",bsdl->pins_list[i].pinname);
|
|
for(j=0;j<(16 - namelen);j++)
|
|
{
|
|
strcat(dbg_str," ");
|
|
}
|
|
|
|
k = strlen(dbg_str);
|
|
|
|
disval = 'X';
|
|
|
|
if(bsdl->pins_list[i].out_bit_number >=0 )
|
|
{
|
|
if( bsdl->chain_list[bsdl->pins_list[i].out_bit_number].control_disable_state >= 0 )
|
|
{
|
|
disval = '0' + bsdl->chain_list[bsdl->pins_list[i].out_bit_number].control_disable_state;
|
|
}
|
|
}
|
|
|
|
sprintf(&dbg_str[k]," type %.2d, ctrl %.3d (disval:%c), out %.3d, in %.3d\r\n",
|
|
bsdl->pins_list[i].pintype,
|
|
bsdl->pins_list[i].ctrl_bit_number,
|
|
disval,
|
|
bsdl->pins_list[i].out_bit_number,
|
|
bsdl->pins_list[i].in_bit_number);
|
|
|
|
jtagcore_logs_printf(jc,MSG_DEBUG,dbg_str);
|
|
|
|
i++;
|
|
}
|
|
}
|
|
|
|
///////////////////////
|
|
// Get the instruction code
|
|
|
|
bsdl->number_of_bits_per_instruction = get_attribut_int(lines,"INSTRUCTION_LENGTH", entityname);
|
|
|
|
jtagcore_logs_printf(jc,MSG_INFO_0,"Instructions lenght : %d\r\n",bsdl->number_of_bits_per_instruction);
|
|
|
|
instruct_str = get_attribut_txt(lines,"INSTRUCTION_OPCODE", entityname);
|
|
if(instruct_str)
|
|
{
|
|
instruct_strchr = strstr(instruct_str,"IDCODE");
|
|
if(!instruct_strchr)
|
|
instruct_strchr = strstr(instruct_str,"idcode");
|
|
if(instruct_strchr)
|
|
{
|
|
get_next_keyword(jc,instruct_strchr, bsdl->IDCODE_Instruction);
|
|
jtagcore_logs_printf(jc,MSG_DEBUG,"IDCODE : %s\r\n",bsdl->IDCODE_Instruction);
|
|
}
|
|
|
|
instruct_strchr = strstr(instruct_str,"EXTEST");
|
|
if(!instruct_strchr)
|
|
instruct_strchr = strstr(instruct_str,"extest");
|
|
|
|
if(instruct_strchr)
|
|
{
|
|
get_next_keyword(jc,instruct_strchr, bsdl->EXTEST_Instruction);
|
|
jtagcore_logs_printf(jc,MSG_DEBUG,"EXTEST : %s\r\n",bsdl->EXTEST_Instruction);
|
|
}
|
|
|
|
instruct_strchr = strstr(instruct_str,"BYPASS");
|
|
if(!instruct_strchr)
|
|
instruct_strchr = strstr(instruct_str,"bypass");
|
|
|
|
if(instruct_strchr)
|
|
{
|
|
get_next_keyword(jc,instruct_strchr, bsdl->BYPASS_Instruction);
|
|
jtagcore_logs_printf(jc,MSG_DEBUG,"BYPASS : %s\r\n",bsdl->BYPASS_Instruction);
|
|
}
|
|
|
|
instruct_strchr = strstr(instruct_str,"SAMPLE");
|
|
if(!instruct_strchr)
|
|
instruct_strchr = strstr(instruct_str,"sample");
|
|
if(instruct_strchr)
|
|
{
|
|
get_next_keyword(jc,instruct_strchr, bsdl->SAMPLE_Instruction);
|
|
jtagcore_logs_printf(jc,MSG_DEBUG,"SAMPLE : %s\r\n",bsdl->SAMPLE_Instruction);
|
|
}
|
|
}
|
|
|
|
free( bsdl_txt );
|
|
|
|
for( i = 0 ;i < number_of_bsdl_lines ; i++ )
|
|
{
|
|
if(lines[i])
|
|
{
|
|
free(lines[i]);
|
|
lines[i] = 0;
|
|
}
|
|
}
|
|
|
|
free(lines);
|
|
|
|
jtagcore_logs_printf(jc,MSG_INFO_0,"BSDL file %s loaded and parsed\r\n",filename);
|
|
|
|
return bsdl;
|
|
}
|
|
|
|
void unload_bsdlfile(jtag_core * jc, jtag_bsdl * bsdl)
|
|
{
|
|
if( bsdl )
|
|
{
|
|
if(bsdl->chain_list)
|
|
free(bsdl->chain_list);
|
|
|
|
if(bsdl->pins_list)
|
|
free(bsdl->pins_list);
|
|
|
|
free( bsdl );
|
|
}
|
|
}
|