You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
557 lines
16 KiB
557 lines
16 KiB
/**[txh]********************************************************************
|
|
|
|
Copyright (c) 2005 Juan Pablo D. Borgna <jpborgna en inti gov ar>
|
|
Copyright (c) 2006-2007 Salvador E. Tropea <salvador en inti gov ar>
|
|
Copyright (c) 2005-2007 Instituto Nacional de Tecnología Industrial
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; version 2.
|
|
|
|
This program 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 General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|
02111-1307, USA
|
|
|
|
Description: Commands parser and executor.
|
|
|
|
***************************************************************************/
|
|
/*****************************************************************************
|
|
|
|
Target: Any
|
|
Language: C
|
|
Compiler: gcc 3.3.5 (Debian GNU/Linux)
|
|
Text editor: SETEdit 0.5.5
|
|
|
|
*****************************************************************************/
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include "global.h"
|
|
#include "commands.h"
|
|
#include "bitshandle.h"
|
|
|
|
#define MAX_WIDTH 246
|
|
|
|
long
|
|
value_from(char *varname)
|
|
{
|
|
if (!strncasecmp("BSIZEB2",varname,7))
|
|
return strtol(bsize,NULL,0)/4;
|
|
if (!strncasecmp("BSIZEB",varname,6))
|
|
return strtol(bsize,NULL,0)/8;
|
|
if (!strncasecmp("BSIZE",varname,5))
|
|
return strtol(bsize,NULL,0);
|
|
if (!strncasecmp("MSIZE",varname,5))
|
|
return msize;
|
|
return strtol(varname,NULL,0);
|
|
}
|
|
|
|
void
|
|
fill(FILE *fp, long c, long t, int *col)
|
|
{
|
|
char b[4]="ZZ";
|
|
sprintf(b,"%02x",(unsigned int)c);
|
|
int co=*col;
|
|
|
|
for (;t>0;t--)
|
|
{
|
|
co+=fprintf(fp,"%s",b);
|
|
if (co>=MAX_WIDTH)
|
|
{
|
|
co=0;
|
|
fprintf(fp,"\n");
|
|
}
|
|
}
|
|
*col=co;
|
|
}
|
|
|
|
/* This function executes a $COMMAND$ */
|
|
int
|
|
do_command(char *cmd, FILE *dfp, FILE *ofp, int *col)
|
|
{
|
|
char *temp;
|
|
char *dbuffer;
|
|
long nbytes=0l;
|
|
long readed=0l;
|
|
long value=0l;
|
|
long times=0l;
|
|
int padded=0;
|
|
char *args_pos_s=NULL;
|
|
char *args_pos_e=NULL;
|
|
char *separator=NULL;
|
|
char args[100]; /* I dont think i need more than 100 bytes for
|
|
passing args... */
|
|
|
|
/* DATA and DATA_INV command */
|
|
|
|
if (strstr(cmd,"DATA"))
|
|
{
|
|
/* get the args inside the () */
|
|
args_pos_s=strchr(cmd,'(');
|
|
args_pos_e=strchr(cmd,')');
|
|
if( !args_pos_s || !args_pos_e)
|
|
{
|
|
fprintf(stderr,"Bad argument specification in $DATA_INV(ndatabytes)$\n");
|
|
return 1;
|
|
}
|
|
memcpy(args,args_pos_s+1,(size_t)(args_pos_e-args_pos_s)); /* Copy te command */
|
|
args[args_pos_e-args_pos_s-1]='\0'; /* Put the null terminator */
|
|
if ((nbytes=value_from(args))==0) /* Bad specification of number of bytes */
|
|
{
|
|
fprintf(stderr,"Bad specification of ndatabytes in $DATA_INV(ndatabytes)$\n");
|
|
return 2;
|
|
}
|
|
if ((nbytes=value_from(args))==-1) /* Want to process the whole stream */
|
|
{
|
|
nbytes=s_bytes;
|
|
}
|
|
if ((temp=(char *)malloc(nbytes*2+1))==NULL)
|
|
{
|
|
fprintf(stderr,"Cannot asign %li bytes in memory needed for $DATA_INV(ndatabytes)$\n",nbytes*2+1);
|
|
return 3;
|
|
}
|
|
if ((dbuffer=(char *)malloc(nbytes))==NULL)
|
|
{
|
|
free(temp);
|
|
fprintf(stderr,"Cannot asign %li bytes in memory needed for $DATA_INV(ndatabytes)$\n",nbytes);
|
|
return 3;
|
|
}
|
|
if ((readed=fread(dbuffer,1,nbytes,dfp))!=nbytes)
|
|
{
|
|
if (padded)
|
|
{
|
|
free(dbuffer);
|
|
free(temp);
|
|
fprintf(stderr,"Cannot read %li databytes for $DATA_INV(ndatabytes)$ from bitfile\n",nbytes);
|
|
return 3;
|
|
}
|
|
padded=1;
|
|
memset(dbuffer+readed,0xff,nbytes-readed);
|
|
}
|
|
|
|
if (strstr(cmd,"DATA_INV"))
|
|
pbi(temp,dbuffer,nbytes); /* Want to inver the bits*/
|
|
else
|
|
pb(temp,dbuffer,nbytes); /* Want to use the bits*/
|
|
|
|
|
|
temp[nbytes*2]='\0';
|
|
|
|
if (cutputs(temp,ofp,MAX_WIDTH,col))
|
|
{
|
|
fprintf(stderr,"Could not write $DATA to file.\n");
|
|
return 4;
|
|
}
|
|
|
|
|
|
free(temp);
|
|
free(dbuffer);
|
|
return 0;
|
|
}
|
|
/* end DATA and DATA_INV command */
|
|
|
|
/* ADDRESS command */
|
|
if (strstr(cmd,"ADDRESS"))
|
|
{
|
|
/* get the args inside the () */
|
|
args_pos_s=strchr(cmd,'(');
|
|
args_pos_e=strchr(cmd,')');
|
|
if((!args_pos_s && args_pos_e )|| (!args_pos_e && args_pos_s))
|
|
{
|
|
fprintf(stderr,"Bad argument specification in $ADDRESS(DIR)$\n");
|
|
return 1;
|
|
}
|
|
if (!args_pos_s && !args_pos_e)
|
|
{ /* Want to use the value */
|
|
if (msize<=0x10000)
|
|
*col+=fprintf(ofp,"%04x",(unsigned int)address);
|
|
else
|
|
*col+=fprintf(ofp,"%06x",(unsigned int)address);
|
|
return 0;
|
|
}
|
|
/* Want to SET the value */
|
|
memcpy(args,args_pos_s+1,(size_t)(args_pos_e-args_pos_s)); /* Copy te argument */
|
|
args[args_pos_e-args_pos_s-1]='\0'; /* Put the null terminator */
|
|
value=value_from(args);
|
|
address=value;
|
|
return 0;
|
|
}
|
|
/* end ADDRESS command */
|
|
|
|
/* SET: CUTLINES command */
|
|
if (strstr(cmd,"CUTLINES"))
|
|
{
|
|
/* get the args inside the () */
|
|
args_pos_s=strchr(cmd,'(');
|
|
args_pos_e=strchr(cmd,')');
|
|
if((!args_pos_s && args_pos_e )|| (!args_pos_e && args_pos_s))
|
|
{
|
|
fprintf(stderr,"Bad argument specification in $CUTLINES(ON)$\n");
|
|
return 1;
|
|
}
|
|
if (!args_pos_s && !args_pos_e)
|
|
{ /* Want to use the value */
|
|
*col+=fprintf(ofp,"%04x",(unsigned int)cutlines);
|
|
return 0;
|
|
}
|
|
/* Want to SET the value */
|
|
memcpy(args,args_pos_s+1,(size_t)(args_pos_e-args_pos_s)); /* Copy te argument */
|
|
args[args_pos_e-args_pos_s-1]='\0'; /* Put the null terminator */
|
|
value=value_from(args);
|
|
cutlines=value;
|
|
return 0;
|
|
}
|
|
/* end CUTLINES command */
|
|
|
|
/* STEP command */
|
|
if (strstr(cmd,"STEP"))
|
|
{
|
|
/* get the args inside the () */
|
|
args_pos_s=strchr(cmd,'(');
|
|
args_pos_e=strchr(cmd,')');
|
|
if((!args_pos_s && args_pos_e )|| (!args_pos_e && args_pos_s))
|
|
{
|
|
fprintf(stderr,"Bad argument specification in $STEP(VAL)$\n");
|
|
return 1;
|
|
}
|
|
if (!args_pos_s && !args_pos_e)
|
|
{ /* Want to use the value */
|
|
*col+=fprintf(ofp,"%04x",(unsigned int)step);
|
|
return 0;
|
|
}
|
|
/* Want to SET the value */
|
|
memcpy(args,args_pos_s+1,(size_t)(args_pos_e-args_pos_s)); /* Copy te argument */
|
|
args[args_pos_e-args_pos_s-1]='\0'; /* Put the null terminator */
|
|
value=value_from(args);
|
|
step=value;
|
|
return 0;
|
|
}
|
|
/* end STEP command */
|
|
|
|
/* REWIND command */
|
|
if (strstr(cmd,"REWIND"))
|
|
{
|
|
/* get the args inside the () */
|
|
args_pos_s=strchr(cmd,'(');
|
|
args_pos_e=strchr(cmd,')');
|
|
if(args_pos_s || args_pos_e )
|
|
{
|
|
fprintf(stderr,"No arguments needed by $REWIND$\n");
|
|
return 1;
|
|
}
|
|
fseek(dfp,stream_s,0);
|
|
return 0;
|
|
}
|
|
/* end REWIND command */
|
|
|
|
/* SBITS command */
|
|
if (strstr(cmd,"SBITS"))
|
|
{
|
|
/* get the args inside the () */
|
|
args_pos_s=strchr(cmd,'(');
|
|
args_pos_e=strchr(cmd,')');
|
|
if((!args_pos_s && args_pos_e )|| (!args_pos_e && args_pos_s))
|
|
{
|
|
fprintf(stderr,"Bad argument specification in $SBITS(VAL)$\n");
|
|
return 1;
|
|
}
|
|
if (!args_pos_s && !args_pos_e)
|
|
{ /* Want to use the value */
|
|
*col+=fprintf(ofp,"%d",(unsigned int)s_bits);
|
|
return 0;
|
|
}
|
|
/* Want to SET the value */
|
|
memcpy(args,args_pos_s+1,(size_t)(args_pos_e-args_pos_s)); /* Copy te argument */
|
|
args[args_pos_e-args_pos_s-1]='\0'; /* Put the null terminator */
|
|
value=value_from(args);
|
|
s_bits=value;
|
|
return 0;
|
|
}
|
|
/* end SBITS command */
|
|
|
|
/* SBYTES command */
|
|
if (strstr(cmd,"SBYTES"))
|
|
{
|
|
/* get the args inside the () */
|
|
args_pos_s=strchr(cmd,'(');
|
|
args_pos_e=strchr(cmd,')');
|
|
if((!args_pos_s && args_pos_e )|| (!args_pos_e && args_pos_s))
|
|
{
|
|
fprintf(stderr,"Bad argument specification in $SBYTES(VAL)$\n");
|
|
return 1;
|
|
}
|
|
if (!args_pos_s && !args_pos_e)
|
|
{ /* Want to use the value */
|
|
*col+=fprintf(ofp,"%d",(unsigned int)s_bytes);
|
|
return 0;
|
|
}
|
|
/* Want to SET the value */
|
|
memcpy(args,args_pos_s+1,(size_t)(args_pos_e-args_pos_s)); /* Copy the argument */
|
|
args[args_pos_e-args_pos_s-1]='\0'; /* Put the null terminator */
|
|
value=value_from(args);
|
|
s_bytes=value;
|
|
return 0;
|
|
}
|
|
/* end SBYTES command */
|
|
|
|
/* FILL command */
|
|
if (strstr(cmd,"FILL"))
|
|
{
|
|
/* get the args inside the () */
|
|
args_pos_s=strchr(cmd,'(');
|
|
args_pos_e=strchr(cmd,')');
|
|
separator=strchr(cmd,',');
|
|
if(!args_pos_s || !args_pos_e || !separator)
|
|
{
|
|
fprintf(stderr,"Bad argument specification in $FILL(VAL,TIMES)$\n");
|
|
return 1;
|
|
}
|
|
/* Want to SET the value */
|
|
memcpy(args,args_pos_s+1,4); /* Copy the character */
|
|
args[4]='\0'; /* Put the null terminator */
|
|
value=value_from(args);
|
|
memcpy(args,separator+1,(size_t)(args_pos_e-separator)); /* Copy the times */
|
|
times=value_from(args);
|
|
if(times==-1) times=s_bytes;
|
|
fill(ofp,value,times,col);
|
|
return 0;
|
|
}
|
|
/* end FILL command */
|
|
|
|
/* IDMASK command */
|
|
if (strstr(cmd,"IDMASK"))
|
|
{
|
|
/* get the args inside the () */
|
|
args_pos_s=strchr(cmd,'(');
|
|
args_pos_e=strchr(cmd,')');
|
|
if((!args_pos_s && args_pos_e )|| (!args_pos_e && args_pos_s))
|
|
{
|
|
fprintf(stderr,"Bad argument specification in $IDMASK(VAL)$\n");
|
|
return 1;
|
|
}
|
|
if (!args_pos_s && !args_pos_e)
|
|
{ /* Want to use the value */
|
|
*col+=fprintf(ofp,"%s",idmask);
|
|
return 0;
|
|
}
|
|
/* Want to SET the value */
|
|
memcpy(args,args_pos_s+1,(size_t)(args_pos_e-args_pos_s)); /* Copy te argument */
|
|
args[args_pos_e-args_pos_s-1]='\0'; /* Put the null terminator */
|
|
if (id) free(id);
|
|
if((id=(char *)malloc(strlen(args)))==NULL)
|
|
{
|
|
fprintf(stderr,"Cannot asign memory needed for $IDMASK$\n");
|
|
return 3;
|
|
}
|
|
strcpy(id,args);
|
|
return 0;
|
|
}
|
|
/* end IDMASK command */
|
|
|
|
|
|
/* ID command */
|
|
if (strstr(cmd,"ID"))
|
|
{
|
|
/* get the args inside the () */
|
|
args_pos_s=strchr(cmd,'(');
|
|
args_pos_e=strchr(cmd,')');
|
|
if((!args_pos_s && args_pos_e )|| (!args_pos_e && args_pos_s))
|
|
{
|
|
fprintf(stderr,"Bad argument specification in $ID(VAL)$\n");
|
|
return 1;
|
|
}
|
|
if (!args_pos_s && !args_pos_e)
|
|
{ /* Want to use the value */
|
|
*col+=fprintf(ofp,"%s",id);
|
|
return 0;
|
|
}
|
|
/* Want to SET the value */
|
|
memcpy(args,args_pos_s+1,(size_t)(args_pos_e-args_pos_s)); /* Copy te argument */
|
|
args[args_pos_e-args_pos_s-1]='\0'; /* Put the null terminator */
|
|
if (id) free(id);
|
|
if((id=(char *)malloc(strlen(args)))==NULL)
|
|
{
|
|
fprintf(stderr,"Cannot asign memory needed for $ID$\n");
|
|
return 3;
|
|
}
|
|
strcpy(id,args);
|
|
return 0;
|
|
}
|
|
/* end ID command */
|
|
|
|
/* BSIZE2 command */
|
|
if (strstr(cmd,"BSIZE2"))
|
|
{
|
|
/* get the args inside the () */
|
|
args_pos_s=strchr(cmd,'(');
|
|
args_pos_e=strchr(cmd,')');
|
|
if (args_pos_s || args_pos_e)
|
|
{
|
|
fprintf(stderr,"$BSIZE2$ is read only\n");
|
|
return 1;
|
|
}
|
|
*col+=fprintf(ofp,"%ld",strtol(bsize,NULL,0)*2);
|
|
return 0;
|
|
}
|
|
/* end BSIZE2 command */
|
|
|
|
/* BSIZE command */
|
|
if (strstr(cmd,"BSIZE"))
|
|
{
|
|
/* get the args inside the () */
|
|
args_pos_s=strchr(cmd,'(');
|
|
args_pos_e=strchr(cmd,')');
|
|
if((!args_pos_s && args_pos_e )|| (!args_pos_e && args_pos_s))
|
|
{
|
|
fprintf(stderr,"Bad argument specification in $BSIZE(VAL)$\n");
|
|
return 1;
|
|
}
|
|
if (!args_pos_s && !args_pos_e)
|
|
{ /* Want to use the value */
|
|
*col+=fprintf(ofp,"%s",bsize);
|
|
return 0;
|
|
}
|
|
/* Want to SET the value */
|
|
memcpy(args,args_pos_s+1,(size_t)(args_pos_e-args_pos_s)); /* Copy te argument */
|
|
args[args_pos_e-args_pos_s-1]='\0'; /* Put the null terminator */
|
|
if (id) free(id);
|
|
if((id=(char *)malloc(strlen(args)))==NULL)
|
|
{
|
|
fprintf(stderr,"Cannot asign memory needed for $BSIZE$\n");
|
|
return 3;
|
|
}
|
|
strcpy(bsize,args);
|
|
return 0;
|
|
}
|
|
/* end BSIZE command */
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int
|
|
repeat (FILE *ifp, FILE *ofp, FILE *dfp,long limit)
|
|
{
|
|
char line[2001];
|
|
char *cmd_pos_s=NULL;
|
|
char *cmd_pos_e=NULL;
|
|
char cmd[30];
|
|
long entry_point;
|
|
long end_address=limit; /*+step; SET: Why?*/
|
|
|
|
/* Sanity check */
|
|
if (limit>0 && address>=end_address)
|
|
{
|
|
/* SET: Not an error, the PROMs have some "fillers", when we use the full
|
|
memory the fillers must be skipped */
|
|
fprintf(stderr,"WARNING: REPEAT UNTIL 0x%lX but current address is 0x%lX\n",
|
|
limit,address);
|
|
if (fgets(line,2001,ifp)==NULL) return 1;
|
|
do
|
|
{
|
|
if (!strncasecmp(line,"--END",5))
|
|
break;
|
|
if (fgets(line,2001,ifp)==NULL) return 1; /* get a new line to parse */
|
|
}
|
|
while(1);
|
|
return 0;
|
|
}
|
|
|
|
entry_point=ftell(ifp);
|
|
|
|
if (fgets(line,2001,ifp)==NULL) return 1;
|
|
|
|
do
|
|
{
|
|
int col=0;
|
|
cmd_pos_e=NULL; /* Ending position of command, also used as flag for a command found or not */
|
|
|
|
if (!strncasecmp(line,"--END",5))
|
|
{
|
|
address+=step;
|
|
/* Repeat condition */
|
|
/* SET: XCF02S can produce address>end_address */
|
|
if ( (limit==0) || ((limit <0) && feof(dfp)) || ((limit >0) && (address>=end_address)))
|
|
break;
|
|
if (ftell(dfp)-stream_s>=s_bytes)
|
|
{
|
|
fprintf(stderr,"INFO: Bitstream limit reached\n");
|
|
//fprintf(stderr,"limit: %ld address %ld end_address %ld\n",limit,address,end_address);
|
|
break;
|
|
}
|
|
/*Sanity check*/
|
|
if ( (0 < limit) && (end_address < address))
|
|
{
|
|
fprintf(stderr,"ERROR: REPEAT UNTIL 0x%lX but current address is 0x%lX (2)\n",limit,address);
|
|
return 24;
|
|
}
|
|
fseek(ifp,entry_point,0);
|
|
if (fgets(line,2001,ifp)==NULL)
|
|
return 1; /* get a new line to parse */
|
|
continue;
|
|
}
|
|
|
|
while((cmd_pos_s=strchr(line,'$'))) /* $ character found in line */
|
|
{
|
|
|
|
if (cmd_pos_e)
|
|
{ /* There was another command on this line before */
|
|
/* Write intermedia bytes */
|
|
int size=cmd_pos_s-cmd_pos_e-1;
|
|
if (fwrite(cmd_pos_e+1,1,size,ofp)!=cmd_pos_s-cmd_pos_e-1)
|
|
{
|
|
fprintf(stderr,"There was an error writing to svf file.\n");
|
|
return 2;
|
|
}
|
|
col+=size;
|
|
}
|
|
else
|
|
{ /* write from begining of line to the starting $ char to output file */
|
|
size_t size=cmd_pos_s-line;
|
|
if (fwrite(line,1,size,ofp)!=(size_t)(cmd_pos_s-line))
|
|
{
|
|
fprintf(stderr,"There was an error writing to svf file.\n");
|
|
return 2;
|
|
}
|
|
col+=size;
|
|
}
|
|
|
|
/* clear the starting '$' simbol so i can search the next */
|
|
*cmd_pos_s='_';
|
|
if ((cmd_pos_e=strchr(line,'$'))==NULL)
|
|
{
|
|
fprintf(stderr,"Parse error: Cant find ending '$' while parsing command.\n");
|
|
return 3;
|
|
}
|
|
*cmd_pos_e='_'; /* clear the ending '$' simbol so i can search the next */
|
|
memcpy(cmd,cmd_pos_s+1,(size_t)(cmd_pos_e-cmd_pos_s-1)); /* Copy the command */
|
|
cmd[cmd_pos_e-cmd_pos_s-1]='\0'; /* Put the null terminator */
|
|
if (do_command(cmd,dfp,ofp,&col))
|
|
return 3;
|
|
}
|
|
/* No more commands */
|
|
if (cmd_pos_e)
|
|
{
|
|
if (fputs(cmd_pos_e+1,ofp)==EOF) return 2; /* Write remainig bytes */
|
|
}
|
|
else
|
|
{
|
|
/* There was no command */
|
|
if (fputs(line,ofp)==EOF) return 2; /* Write all the line */
|
|
}
|
|
|
|
if (fgets(line,2001,ifp)==NULL) return 1; /* get a new line to parse */
|
|
}
|
|
while (1);
|
|
|
|
return 0;
|
|
}
|
|
|