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

/**[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;
}