/*------------------------------------------------------------------------
This C file was developed by Altera Corporation. It may be freely
copied and/or distributed at no cost. Any persons using this file for
any purpose do so at their own risk, and are responsible for the results
of such use. Altera Corporation does not guarantee that this file is
complete, correct, or fit for any particular purpose. NO WARRANTY OF
ANY KIND IS EXPRESSED OR IMPLIED. This notice must accompany any copy
of this file.
------------------------------------------------------------------------*/
/*------------------------------------------------------------------------
Convert Intel Hex Format to Verilog Format
------------------------------------------------------------------------
Version 1.0 Date 07/09/97
------------------------------------------------------------------------*/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include "veriuser.h"
#include "acc_user.h"
#define TRUE 1
#define FALSE 0
#define MAX_BUFFER_SZ 2048
#define MAX_NAME_SZ 128
#define OUT_FILE_EXT ".ver"
#define COLON ':'
#define OFFSET 9
#define H10 0x10L
#define AWORD 8
#define WORDS_PER_LINE 8
#define MASK15 0x000000FFL
#define EXT_STR ".ver"
typedef enum {
OK = 0,
WARNING = 1,
ERROR = 2
} STATUS;
static int line_no = 0;
/********************************************************************
* char* trimAlteraExt(char* oldName, char* newName)
* oldName : original file name.
* newName : new file name which doesnt have file extension.
*
* This function trims the file extension
* Looks for first "." and trims the file name afterwords.
********************************************************************/
char *
trimAlteraExt(oldName, newName)
char *oldName;
char *newName;
{
char tempStr[MAX_BUFFER_SZ];
char *tempPtr = NULL;
newName[0] = '\0';
if (oldName[0] == '\0')
return NULL;
strcpy(tempStr, oldName);
if (tempPtr = strstr(tempStr, ".")) {
*tempPtr = '\0';
}
strcpy(newName, tempStr);
return newName;
}
/****************************************************************/
int
display_msg(status, str, data_file)
STATUS status;
char *str;
char *data_file;
{
switch (status) {
case WARNING:
printf("WARNING: %s, %s\n\n", data_file, str);
break;
case ERROR:
printf("ERROR:%s, line %d, %s\n\n", data_file, line_no, str);
break;
default:
break;
}
return (TRUE);
}
/****************************************************************
char *ltrim(str)
char *str;
Deletes leading blanks in string 'str'
****************************************************************/
char *
ltrim(str)
char *str;
{
int i = 0, j = 0;
/* Illeagal application. Returns NULL. */
if (str == 0)
return (0);
/* Deletes leading blanks */
while (*(str + i) == ' ' || *(str + i) == '\n' || *(str + i) == '\t' || *(str + i) == '\b')
i++;
for (; *(str + i) != '\0'; i++, j++)
*(str + j) = *(str + i);
/* Appends a NULL character to the end of the string */
*(str + j) = '\0';
return (str);
}
/****************************************************************
Function: write_data
Description: Write ROM data in the verilog format so that
it can be read using readmemh(infile, rom)
Format: example data format for the 8 bit data
@1
01 02 03 04 05 06 07 08
@a
0a 0b 0c
****************************************************************/
int
write_data(ofp, nn, aaaa, off_addr, dddd, width)
FILE *ofp;
long nn, aaaa, off_addr;
char *dddd;
{
int count, i;
char data[MAX_BUFFER_SZ + 1];
int num_hexs, nibbles;
if ((width % AWORD) == 0) {
num_hexs = width / AWORD;
} else {
num_hexs = (width / AWORD) + 1;
}
fprintf(ofp, "@%x\n", aaaa + off_addr);
nibbles = num_hexs * 2;
count = 1;
while (nn > 0) {
if (nn >= num_hexs) {
strncpy(data, dddd, nibbles);
data[nibbles] = '\0';
} else {
for (i = 0; i < (num_hexs - nn); i++) {
sprintf(data + i * 2, "%s", "00");
}
strcat(data + (num_hexs - nn), dddd);
}
if (count < WORDS_PER_LINE) {
fprintf(ofp, "%s ", data);
count++;
} else {
fprintf(ofp, "%s\n", data);
count = 1;
}
dddd = dddd + nibbles;
nn -= num_hexs;
}
if (count > 1)
fprintf(ofp, "\n");
}
/****************************************************************/
/* Convert Intel-hex format data to verilog format data */
/* Intel-hex format :nnaaaaattddddcc */
/****************************************************************/
convert_hex2ver()
{
char buffer[MAX_BUFFER_SZ + 1];
char out_file[MAX_NAME_SZ + 1];
char init_filename[MAX_NAME_SZ + 1];
char dddd[MAX_BUFFER_SZ + 1];
char *in_file, *out_str;
FILE *ifp, *ofp;
int i;
int done = FALSE;
int first_rec = FALSE;
int last_rec = FALSE;
int width;
long off_addr, nn, aaaa, tt, cc, aah, aal, dd, sum;
handle wrk;
static s_setval_value user_s = {accStringVal};
static s_setval_delay delay;
off_addr = nn = aaaa = tt = cc = aah = aal = dd = sum = 0;
in_file = (char *) tf_getcstringp(1);
width = tf_getp(2);
trimAlteraExt(in_file, out_file);
strcat(out_file, OUT_FILE_EXT);
if ((ifp = fopen(in_file, "r")) == NULL) {
printf("cannot read %s\n", in_file);
fclose(ifp);
return (1);
}
if ((ofp = fopen(out_file, "w")) == NULL) {
printf("cannot write %s\n", out_file);
fclose(ofp);
return (1);
}
while (!done) {
if (fgets(buffer, MAX_BUFFER_SZ, ifp) == NULL) {
if (!first_rec)
done = display_msg(WARNING, "Intel-hex data file is empty.", in_file);
else if (!last_rec)
done = display_msg(ERROR, "Missing the last record.", in_file);
} else if (strlen(ltrim(buffer)) == 0) {
line_no++;
} else if (buffer && (buffer[0] == COLON)) {
line_no++;
first_rec = TRUE;
sscanf(buffer + 1, "%02x%04x%02x", &nn, &aaaa, &tt);
if ((tt == 2) && (nn != 2)) {
done = display_msg(ERROR, "Invalid data record.", in_file);
} else {
sscanf(buffer + 3, "%02x%02x", &aah, &aal);
sum = nn + aah + aal + tt;
for (i = 0; i < nn; i++) {
sscanf(buffer + OFFSET + i * 2, "%02x", &dd);
sprintf(dddd + i * 2, "%02x", dd);
sum += dd;
}
sscanf(buffer + OFFSET + i * 2, "%02x\n", &cc);
switch (tt) {
case 0x00: /* normal_record */
first_rec = TRUE;
if (((~sum + 1) & MASK15) == cc) {
write_data(ofp, nn, aaaa, off_addr, dddd, width);
off_addr = 0;
} else {
done = display_msg(ERROR, "Invalid checksum.", in_file);
}
break;
case 0x01: /* last record */
last_rec = TRUE;
if (((~sum + 1) & MASK15) != cc) {
display_msg(ERROR, "Invalid checksum.", in_file);
}
done = TRUE;
break;
case 0x02: /* address base record */
sscanf(dddd, "%x\n", &off_addr);
if (((~sum + 1) & MASK15) == cc) {
off_addr *= H10;
} else {
done = display_msg(ERROR, "Invalid checksum.", in_file);
}
break;
default:
done = display_msg(ERROR, "Unknown record type.", in_file);
break;
} /* switch */
}
} else {
line_no++;
display_msg(ERROR, "Invalid INTEL HEX record", in_file);
done = TRUE;
}
}
fclose(ifp);
fclose(ofp);
/* append EXT_STR to the input string and pass it back in arg 1 */
delay.model = accNoDelay;
wrk = acc_handle_tfarg(3);