genramvhd.c 6.06 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <math.h>
#include <unistd.h> /* getopt */

const char* program;
const char* package;
const char* filename;
long width;
int bigendian;
int verbose;

void help() {
  fprintf(stderr, "Usage: %s [OPTION] <filename>\n", program);
  fprintf(stderr, "\n");
  fprintf(stderr, "  -w <width>     width of values in bytes [1/2/4/8/16]        (4)\n");
  fprintf(stderr, "  -p <package>   name of the output package            (filename)\n");
20
  fprintf(stderr, "  -s <size>      pad the output up to size bytes       (filesize)\n");
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
  fprintf(stderr, "  -b             big-endian operation                         (*)\n");
  fprintf(stderr, "  -l             little-endian operation                         \n");
  fprintf(stderr, "  -v             verbose operation\n");
  fprintf(stderr, "  -h             display this help and exit\n");
  fprintf(stderr, "\n");
  fprintf(stderr, "Report Etherbone bugs to <white-rabbit-dev@ohwr.org>\n");
}

/* We don't want localized versions from ctype.h */
inline int my_isalpha(char c) {
  return (c >= 'a' && c <= 'z') ||
         (c >= 'A' && c <= 'Z');
}
inline int my_isok(char c) {
  return c == '_' || my_isalpha(c) ||
         (c >= '0' && c <= '9');
}

int main(int argc, char **argv) {
  int j, opt, error, i_width;
41
  long i, elements, size, columns, entry_width;
42 43 44 45 46 47 48 49 50 51 52
  char* value_end;
  unsigned char x[16]; /* Up to 128 bit */
  char buf[100];
  FILE* f;
  
  /* Default values */
  program = argv[0];
  package = 0; /* auto-detect */
  width = 4;
  bigendian = 1;
  verbose = 0;
53
  size = -1; /* file size */
54 55
  
  /* Process the command-line */
56
  while ((opt = getopt(argc, argv, "w:p:s:blvh")) != -1) {
57 58 59 60 61 62 63 64 65 66 67 68 69 70
    switch (opt) {
    case 'w':
      width = strtol(optarg, &value_end, 0);
      if (*value_end             || /* bad integer */
          ((width-1)&width) != 0 || /* not a power of 2 */
          width == 0             ||
          width > 16) {
        fprintf(stderr, "%s: invalid value width -- '%s'\n", program, optarg);
        error = 1;
      }
      break;
    case 'p':
      package = optarg;
      break;
71 72 73 74 75 76 77
    case 's':
      size = strtol(optarg, &value_end, 0);
      if (*value_end) {
        fprintf(stderr, "%s: invalid value size -- '%s'\n", program, optarg);
        error = 1;
      }
      break;
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
    case 'b':
      bigendian = 1;
      break;
    case 'l':
      bigendian = 0;
      break;
    case 'v':
      verbose = 1;
      break;
    case 'h':
      help();
      return 1;
    case ':':
    case '?':
      error = 1;
      break;
    default:
      fprintf(stderr, "%s: bad getopt result\n", program);
      return 1;
    }
  }
  
  if (optind + 1 != argc) {
    fprintf(stderr, "%s: expecting one non-optional argument: <filename>\n", program);
    return 1;
  }
  
  filename = argv[optind];
  
  /* Confirm the filename exists */
  if ((f = fopen(filename, "r")) == 0) {
    fprintf(stderr, "%s: %s while opening '%s'\n", program, strerror(errno), filename);
    return 1;
  }
  
  /* Deduce if it's aligned */
  fseek(f, 0, SEEK_END);
  elements = ftell(f);
  rewind(f);
  
118 119 120 121 122 123 124 125 126
  if (size == -1) {
    size = elements;
  }
  
  if (size < elements) {
    fprintf(stderr, "%s: length of initialization file '%s' (%ld) exceeds specified size (%ld)\n", program, filename, elements, size);
    return 1;
  }
  
127 128 129 130 131 132
  if (elements % width != 0) {
    fprintf(stderr, "%s: initialization file '%s' is not a multiple of %ld bytes\n", program, filename, width);
    return 1;
  }
  elements /= width;
  
133 134 135 136 137 138
  if (size % width != 0) {
    fprintf(stderr, "%s: specified size '%ld' is not a multiple of %ld bytes\n", program, size, width);
    return 1;
  }
  size /= width;
  
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
  /* Find a suitable package name */
  if (package == 0) {
    if (strlen(filename) >= sizeof(buf)-5) {
      fprintf(stderr, "%s: filename too long to deduce package name -- '%s'\n", program, filename);
      return 1;
    }
    
    /* Find the first alpha character */
    while (*filename && !my_isalpha(*filename)) ++filename;
    
    /* Start copying the filename to the package */
    for (i = 0; filename[i]; ++i) {
      if (my_isok(filename[i]))
        buf[i] = filename[i];
      else
        buf[i] = '_';
    }
    buf[i] = 0;
    
    if (i == 0) {
      fprintf(stderr, "%s: no appropriate characters in filename to use for package name -- '%s'\n", program, filename);
      return 1;
    }
    
    package = &buf[0];
  } else {
    /* Check for valid VHDL identifier */
    if (!my_isalpha(package[0])) {
      fprintf(stderr, "%s: invalid package name -- '%s'\n", program, package);
      return 1;
    }
    for (i = 1; package[i]; ++i) {
      if (!my_isok(package[i])) {
        fprintf(stderr, "%s: invalid package name -- '%s'\n", program, package);
        return 1;
      }
    }
  }
  
178
  /* Find how many digits it takes to fit 'size' */
179
  i_width = 1;
180
  for (i = 10; i <= size; i *= 10)
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
    ++i_width;
    
  /* How wide is an entry of the table? */
  entry_width = i_width + 6 + width*2 + 3;
  columns = 76 / entry_width;
  
  printf("-- AUTOGENERATED FILE (from genramvhd.c run on %s) --\n", argv[1]);
  printf("library IEEE;\n");
  printf("use IEEE.std_logic_1164.all;\n");
  printf("use IEEE.numeric_std.all;\n");
  printf("\n");
  printf("library work;\n");
  printf("use work.memory_loader_pkg.all;\n");
  printf("\n");
  
196
  printf("package %s_pkg is\n", package);
197
  printf("  constant %s_init : t_meminit_array(%ld downto 0, %ld downto 0) := (\n", package, size-1, (width*8)-1);
198
  
199 200
  for (i = 0; i < size; ++i) {
    if (i % columns == 0) printf("    ");
201
    
202 203 204 205 206 207 208
    if (i < elements) {
      if (fread(x, 1, width, f) != width) {
        perror("fread");
        return 1;
      }
    } else {
      memset(x, 0, sizeof(x));
209 210 211 212 213 214 215 216 217 218 219 220
    }
    
    printf("%*ld => x\"", i_width, i);
    if (bigendian) {
      for (j = 0; j < width; ++j)
        printf("%02x", x[j]);
    } else {
      for (j = width-1; j >= 0; --j)
        printf("%02x", x[j]);
    }
    printf("\"");
    
221 222
    if ((i+1) == size) printf(");\n");
    else if ((i+1) % columns == 0) printf(",\n");
223 224 225 226
    else printf(", ");
  }
  fclose(f);
  
227
  printf("end %s_pkg;\n", package);
228 229 230

  return 0;
}