OpenCores
URL https://opencores.org/ocsvn/fixed_extensions/fixed_extensions/trunk

Subversion Repositories fixed_extensions

[/] [fixed_extensions/] [trunk/] [sw/] [gentestround.c] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 kavi
/*
2
 * File       : gentestround.c
3
 * Description: Generator for test designs for evaluating signed/unsigned
4
 *              fixed-point (sfixed/ufixed) rounding operators.
5
 * Author     : Nikolaos Kavvadias <nikolaos.kavvadias@gmail.com>
6
 * Copyright  : (C) Nikolaos Kavvadias 2011
7
 * Website    : http://www.nkavvadias.com
8
 *
9
 * This file is part of fixed_extensions, and is distributed under the terms
10
 * of the Modified BSD License.
11
 *
12
 * A copy of the Modified BSD License is included with this distrubution
13
 * in the files /doc/COPYING.BSD.
14
 * fixed_extensions is free software: you can redistribute it and/or modify
15
 * it under the terms of the Modified BSD License.
16
 * fixed_extensions is distributed in the hope that it will be useful, but
17
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18
 * or FITNESS FOR A PARTICULAR PURPOSE. See the Modified BSD License for more
19
 * details.
20
 *
21
 * You should have received a copy of the Modified BSD License along with
22
 * fixed_extensions. If not, see <http://www.gnu.org/licenses/>.
23
 */
24
 
25
#include <stdio.h>
26
#include <stdlib.h>
27
#include <string.h>
28
#include <stdarg.h>
29
 
30
/* Absolute value of an integer. */
31
#define ABS(x)            ((x) >  0 ? (x) : (-x))
32
 
33
int enable_debug=0;
34
int iw_val=4, fw_val=4;
35
double step_val=0.25;
36
int enable_signed=0, enable_unsigned=1;
37
 
38
 
39
/* print_spaces:
40
 * Print a configurable number of space characters to an output file (specified
41
 * by the given filename; the file is assumed already opened).
42
 */
43
void print_spaces(FILE *f, int nspaces)
44
{
45
  int i;
46
  for (i = 0; i < nspaces; i++)
47
  {
48
    fprintf(f, " ");
49
  }
50
}
51
 
52
/* pfprintf:
53
 * fprintf prefixed by a number of space characters.
54
 */
55
void pfprintf(FILE *f, int nspaces, char *fmt, ...)
56
{
57
  va_list args;
58
  print_spaces(f, nspaces);
59
  va_start(args, fmt);
60
  vfprintf(f, fmt, args);
61
  va_end(args);
62
}
63
 
64
/* ipowul:
65
 * Calculate integer power supporting results up to 64-bits.
66
 */
67
unsigned long long int ipowul(int base, int exponent)
68
{
69
  unsigned long long int temp;
70
  int i;
71
 
72
  temp = 1;
73
 
74
  for (i = 0; i < exponent; i++)
75
  {
76
    temp *= (unsigned int)base;
77
  }
78
 
79
  return (temp);
80
}
81
 
82
/* calculate_samples:
83
 * Calculate the number of samples needed for the test design.
84
 */
85
unsigned long long int calculate_samples(int iw, int fw, int step)
86
{
87
  unsigned long long int nsamples;
88
 
89
  /* FIXME: Should be the same for both cases! */
90
  /* Samples range: 0 to 2^IW-2^FW. */
91
  if (enable_unsigned == 1)
92
  {
93
//    nsamples = (ipowul(2, iw) - ipowul(2, -fw)) / ipowul(2, -fw) + 1;
94
    nsamples = ipowul(2, iw+fw);
95
  }
96
  /* Samples range: -2^(IW-1) to 2^(IW-1)-2^FW. */
97
  else if (enable_signed == 1)
98
  {
99
//    nsamples = ipowul(2, iw) / ipowul(2, fw);
100
    nsamples = ipowul(2, iw+fw);
101
  }
102
 
103
  return nsamples;
104
}
105
 
106
/* print_test_prologue:
107
 * Prints the prologue for the generated test design file.
108
 */
109
void print_test_prologue(FILE *infile)
110
{
111
  pfprintf(infile, 0, "library IEEE;\n");
112
  pfprintf(infile, 0, "use IEEE.std_logic_1164.all;\n");
113
  pfprintf(infile, 0, "use IEEE.numeric_std.all;\n");
114
  pfprintf(infile, 0, "use WORK.fixed_float_types.all;\n");
115
  pfprintf(infile, 0, "use WORK.fixed_pkg.all;\n");
116
  pfprintf(infile, 0, "use WORK.fixed_extensions_pkg.all;\n");
117
  fprintf(infile, "\n");
118
}
119
 
120
/* print_test_entity:
121
 * Prints the entity of the generated test design file.
122
 */
123
void print_test_entity(FILE *infile, unsigned int iw, unsigned int fw)
124
{
125
  pfprintf(infile, 0, "entity testrounding is\n");
126
  pfprintf(infile, 2, "port (\n");
127
  pfprintf(infile, 4, "clk   : in  std_logic;\n");
128
  pfprintf(infile, 4, "reset : in  std_logic;\n");
129
  pfprintf(infile, 4, "start : in  std_logic;\n");
130
  pfprintf(infile, 4, "ok    : out sfixed(%d downto -%d)\n", iw-1, fw);
131
  pfprintf(infile, 2, ");\n");
132
  pfprintf(infile, 0, "end testrounding;\n\n");
133
}
134
 
135
/* print_test_architecture_prologue:
136
 * Prints the declaration part of the architecture for the generated test design
137
 * file.
138
 */
139
void print_test_architecture_prologue(FILE *infile, unsigned int iw, unsigned int fw, unsigned int step)
140
{
141
  long long int i;
142
  unsigned long long int nsteps = calculate_samples(iw, fw, step);
143
  char c = 'X';
144
  if (enable_unsigned == 1)
145
  {
146
    c = 'u';
147
  }
148
  else if (enable_signed == 1)
149
  {
150
    c = 's';
151
  }
152
 
153
  pfprintf(infile, 0, "architecture fsmd of testrounding is\n");
154
  pfprintf(infile, 2, "type state_type is (S_ENTRY, S_EXIT,\n");
155
 
156
  for (i = 0; i < nsteps; i++)
157
  {
158
    pfprintf(infile, 4, "S_%08d_1,", i);
159
    fprintf(infile, " S_%08d_2", i);
160
    fprintf(infile, ", S_%08d_3", i);
161
    if (enable_signed == 1)
162
    {
163
      fprintf(infile, ", S_%08d_4", i);
164
    }
165
    if (i < nsteps-1)
166
    {
167
      fprintf(infile, ",");
168
    }
169
    fprintf(infile, "\n");
170
  }
171
  pfprintf(infile, 2, ");\n");
172
  pfprintf(infile, 2, "signal current_state, next_state: state_type;\n");
173
  pfprintf(infile, 2, "signal a_reg, a_next : %cfixed(%d downto -%d);\n", c, iw-1, fw);
174
  pfprintf(infile, 2, "signal y_ceil_reg, y_ceil_next : %cfixed(%d downto -%d);\n", c, iw-1, fw);
175
  pfprintf(infile, 2, "signal y_fix_reg, y_fix_next : %cfixed(%d downto -%d);\n", c, iw-1, fw);
176
  pfprintf(infile, 2, "signal y_floor_reg, y_floor_next : %cfixed(%d downto -%d);\n", c, iw-1, fw);
177
  pfprintf(infile, 2, "signal y_round_reg, y_round_next : %cfixed(%d downto -%d);\n", c, iw-1, fw);
178
  pfprintf(infile, 2, "signal y_nearest_reg, y_nearest_next : %cfixed(%d downto -%d);\n", c, iw-1, fw);
179
  pfprintf(infile, 2, "signal y_convergent_reg, y_convergent_next : %cfixed(%d downto -%d);\n", c, iw-1, fw);
180
  pfprintf(infile, 2, "signal ok_reg, ok_next : sfixed(%d downto -%d);\n", iw-1, fw);
181
 
182
  pfprintf(infile, 0, "begin\n");
183
}
184
 
185
/* print_test_architecture_csl:
186
 * Prints the current state logic process of the architecture for the generated
187
 * test design file.
188
 */
189
void print_test_architecture_csl(FILE *infile)
190
{
191
  pfprintf(infile, 2, "-- current state logic\n");
192
  pfprintf(infile, 2, "process (clk, reset)\n");
193
  pfprintf(infile, 4, "begin\n");
194
  pfprintf(infile, 6, "if (reset = '1') then\n");
195
  pfprintf(infile, 6, "current_state <= S_ENTRY;\n");
196
  pfprintf(infile, 6, "a_reg <= (others => '0');\n");
197
  pfprintf(infile, 6, "y_ceil_reg <= (others => '0');\n");
198
  pfprintf(infile, 6, "y_fix_reg <= (others => '0');\n");
199
  pfprintf(infile, 6, "y_floor_reg <= (others => '0');\n");
200
  pfprintf(infile, 6, "y_round_reg <= (others => '0');\n");
201
  pfprintf(infile, 6, "y_nearest_reg <= (others => '0');\n");
202
  pfprintf(infile, 6, "y_convergent_reg <= (others => '0');\n");
203
  pfprintf(infile, 6, "ok_reg <= (others => '0');\n");
204
  pfprintf(infile, 4, "elsif (clk = '1' and clk'EVENT) then\n");
205
  pfprintf(infile, 6, "current_state <= next_state;\n");
206
  pfprintf(infile, 6, "a_reg <= a_next;\n");
207
  pfprintf(infile, 6, "y_ceil_reg <= y_ceil_next;\n");
208
  pfprintf(infile, 6, "y_fix_reg <= y_fix_next;\n");
209
  pfprintf(infile, 6, "y_floor_reg <= y_floor_next;\n");
210
  pfprintf(infile, 6, "y_round_reg <= y_round_next;\n");
211
  pfprintf(infile, 6, "y_nearest_reg <= y_nearest_next;\n");
212
  pfprintf(infile, 6, "y_convergent_reg <= y_convergent_next;\n");
213
  pfprintf(infile, 6, "ok_reg <= ok_next;\n");
214
  pfprintf(infile, 4, "end if;\n");
215
  pfprintf(infile, 2, "end process;\n\n");
216
}
217
 
218
/* print_test_architecture_nsol_prologue:
219
 * Prints the next state and output logic process prologue of the architecture
220
 * for the generated test design file.
221
 */
222
void print_test_architecture_nsol_prologue(FILE *infile)
223
{
224
  pfprintf(infile, 2, "-- next state and output logic\n");
225
  pfprintf(infile, 2, "process (current_state, start,\n");
226
  pfprintf(infile, 4, "ok_reg,\n");
227
  pfprintf(infile, 4, "a_reg, a_next,\n");
228
  pfprintf(infile, 4, "y_ceil_reg, y_ceil_next,\n");
229
  pfprintf(infile, 4, "y_fix_reg, y_fix_next,\n");
230
  pfprintf(infile, 4, "y_floor_reg, y_floor_next,\n");
231
  pfprintf(infile, 4, "y_round_reg, y_round_next,\n");
232
  pfprintf(infile, 4, "y_nearest_reg, y_nearest_next,\n");
233
  pfprintf(infile, 4, "y_convergent_reg, y_convergent_next\n");
234
  pfprintf(infile, 2, ")\n");
235
  pfprintf(infile, 2, "begin\n");
236
  pfprintf(infile, 4, "a_next <= a_reg;\n");
237
  pfprintf(infile, 4, "y_ceil_next <= y_ceil_reg;\n");
238
  pfprintf(infile, 4, "y_fix_next <= y_fix_reg;\n");
239
  pfprintf(infile, 4, "y_floor_next <= y_floor_reg;\n");
240
  pfprintf(infile, 4, "y_round_next <= y_round_reg;\n");
241
  pfprintf(infile, 4, "y_nearest_next <= y_nearest_reg;\n");
242
  pfprintf(infile, 4, "y_convergent_next <= y_convergent_reg;\n");
243
  pfprintf(infile, 4, "ok_next <= ok_reg;\n");
244
}
245
 
246
/* print_test_architecture_nsol_csdec:
247
 * Prints the current state decoding part. It resides in the next state and
248
 * output logic process of the architecture for the generated test design file.
249
 */
250
void print_test_architecture_nsol_csdec(FILE *infile, unsigned int iw, unsigned int fw, unsigned int step)
251
{
252
  long long int i;
253
  int k;
254
  unsigned long long int nsteps = calculate_samples(iw, fw, step);
255
  double val = 0.0;
256
  char c = 'X';
257
  if (enable_unsigned == 1)
258
  {
259
    c = 'u';
260
  }
261
  else if (enable_signed == 1)
262
  {
263
    c = 's';
264
  }
265
 
266
  pfprintf(infile, 4, "case current_state is\n");
267
  pfprintf(infile, 6, "when S_ENTRY =>\n");
268
  pfprintf(infile, 8, "if (start = '1') then\n");
269
  pfprintf(infile, 10, "next_state <= S_00000001_1;\n");
270
  pfprintf(infile, 8, "else\n");
271
  pfprintf(infile, 10, "next_state <= S_ENTRY;\n");
272
  pfprintf(infile, 8, "end if;\n");
273
 
274
  if (enable_unsigned == 1)
275
  {
276
    val = 0.0;
277
  }
278
  else if (enable_signed == 1)
279
  {
280
    val = - 1.0 * ipowul(2, iw-1);
281
  }
282
  for (i = 0; i < nsteps; i++)
283
  {
284
    pfprintf(infile, 6, "when S_%08d_1 =>\n", i);
285
    pfprintf(infile, 8, "a_next <= to_%cfixed(%lf, %d, -%d);\n", c, val, iw-1, fw);
286
    val += 1.0/(float)ipowul(2, fw);
287
    pfprintf(infile, 8, "next_state <= S_%08d_2;\n", i);
288
    //
289
    if (enable_signed == 1)
290
    {
291
      pfprintf(infile, 6, "when S_%08d_2 =>\n", i);
292
      if (val < 0.0)
293
      {
294
        pfprintf(infile, 8, "a_next <= resize(-a_reg, a_next'high, a_next'low);\n");
295
      }
296
      pfprintf(infile, 8, "next_state <= S_%08d_3;\n", i);
297
      k++;
298
    }
299
    //
300
    if (enable_unsigned == 1)
301
    {
302
      pfprintf(infile, 6, "when S_%08d_2 =>\n", i);
303
    }
304
    else if (enable_signed == 1)
305
    {
306
      pfprintf(infile, 6, "when S_%08d_3 =>\n", i);
307
    }
308
    pfprintf(infile, 8, "y_ceil_next       <= ceil(a_reg);\n");
309
    pfprintf(infile, 8, "y_fix_next        <= fix(a_reg);\n");
310
    pfprintf(infile, 8, "y_floor_next      <= floor(a_reg);\n");
311
    pfprintf(infile, 8, "y_round_next      <= round(a_reg);\n");
312
    pfprintf(infile, 8, "y_nearest_next    <= nearest(a_reg);\n");
313
    pfprintf(infile, 8, "y_convergent_next <= convergent(a_reg);\n");
314
    if (enable_unsigned == 1)
315
    {
316
      pfprintf(infile, 8, "next_state <= S_%08d_3;\n", i);
317
    }
318
    else if (enable_signed == 1)
319
    {
320
      pfprintf(infile, 8, "next_state <= S_%08d_4;\n", i);
321
    }
322
    //
323
    if (enable_unsigned == 1)
324
    {
325
      pfprintf(infile, 6, "when S_%08d_3 =>\n", i);
326
    }
327
    else if (enable_signed == 1)
328
    {
329
      pfprintf(infile, 6, "when S_%08d_4 =>\n", i);
330
    }
331
    pfprintf(infile, 8, "assert false report \"a_reg            = \" & to_bstring(a_reg) severity note;\n");
332
    pfprintf(infile, 8, "assert false report \"y_ceil_reg       = \" & to_bstring(y_ceil_reg) severity note;\n");
333
    pfprintf(infile, 8, "assert false report \"y_fix_reg        = \" & to_bstring(y_fix_reg) severity note;\n");
334
    pfprintf(infile, 8, "assert false report \"y_floor_reg      = \" & to_bstring(y_floor_reg) severity note;\n");
335
    pfprintf(infile, 8, "assert false report \"y_round_reg      = \" & to_bstring(y_round_reg) severity note;\n");
336
    pfprintf(infile, 8, "assert false report \"y_nearest_reg    = \" & to_bstring(y_nearest_reg) severity note;\n");
337
    pfprintf(infile, 8, "assert false report \"y_convergent_reg = \" & to_bstring(y_convergent_reg) severity note;\n");
338
    if (i == nsteps-1)
339
    {
340
      pfprintf(infile, 8, "next_state <= S_EXIT;\n");
341
    }
342
    else
343
    {
344
      pfprintf(infile, 8, "next_state <= S_%08d_1;\n", i+1);
345
    }
346
  }
347
  pfprintf(infile, 6, "when S_EXIT =>\n");
348
  pfprintf(infile, 8, "ok_next <= to_sfixed(%lf, %d, %d);\n", 1.0, iw-1, -fw);
349
  pfprintf(infile, 8, "assert false report \"DONE!\" severity note;\n");
350
  pfprintf(infile, 8, "next_state <= S_ENTRY;\n");
351
  pfprintf(infile, 4, "end case;\n");
352
}
353
 
354
/* print_test_architecture_epilogue:
355
 * Prints the epilogue of the architecture for the generated test design file.
356
 */
357
void print_test_architecture_epilogue(FILE *infile)
358
{
359
  pfprintf(infile, 2, "end process;\n\n");
360
  pfprintf(infile, 2, "ok <= ok_reg;\n\n");
361
  pfprintf(infile, 0, "end fsmd;\n");
362
}
363
 
364
/* print_test_design:
365
 * Prints the generated test design file.
366
 */
367
void print_test_design(FILE *infile, unsigned int iw, unsigned int fw, unsigned step)
368
{
369
  print_test_prologue(infile);
370
  print_test_entity(infile, iw, fw);
371
  print_test_architecture_prologue(infile, iw, fw, step);
372
  print_test_architecture_csl(infile);
373
  print_test_architecture_nsol_prologue(infile);
374
  print_test_architecture_nsol_csdec(infile, iw, fw, step);
375
  print_test_architecture_epilogue(infile);
376
}
377
 
378
/* print_usage:
379
 * Print usage instructions for the "gentestround" program.
380
 */
381
static void print_usage()
382
{
383
  printf("\n");
384
  printf("* Usage:\n");
385
  printf("* gentestround [options]\n");
386
  printf("* \n");
387
  printf("* Options:\n");
388
  printf("* \n");
389
  printf("*   -h:\n");
390
  printf("*         Print this help.\n");
391
  printf("*   -d:\n");
392
  printf("*         Enable debug/diagnostic output.\n");
393
  printf("*   -iw <num>:\n");
394
  printf("*         Set the integral part width of the fixed-point numbers. Default: 4.\n");
395
  printf("*   -fw <num>:\n");
396
  printf("*         Set the fractional part width of the fixed-point numbers. Default: 4.\n");
397
  printf("*   -step <num>:\n");
398
  printf("*         Set the step value indicating the difference between two consecutive\n");
399
  printf("*         samples. Default: 0.25\n");
400
  printf("*   -signed:\n");
401
  printf("*         Generate test design for sfixed vectors.\n");
402
  printf("*   -unsigned:\n");
403
  printf("*         Generate test design for ufixed vectors (default).\n");
404
  printf("* \n");
405
  printf("* For further information, please refer to the website:\n");
406
  printf("* http://www.nkavvadias.com\n");
407
}
408
 
409
/* main:
410
 * Program entry.
411
 */
412
int main(int argc, char *argv[])
413
{
414
  int i;
415
  FILE *file_o;
416
 
417
  // Read input arguments
418
  for (i=1; i < argc; i++)
419
  {
420
    if (strcmp("-h", argv[i]) == 0)
421
    {
422
      print_usage();
423
      exit(1);
424
    }
425
    else if (strcmp("-d", argv[i]) == 0)
426
    {
427
      enable_debug = 1;
428
    }
429
    else if (strcmp("-unsigned", argv[i]) == 0)
430
    {
431
      enable_unsigned = 1;
432
      enable_signed   = 0;
433
    }
434
    else if (strcmp("-signed", argv[i]) == 0)
435
    {
436
      enable_unsigned = 0;
437
      enable_signed   = 1;
438
    }
439
    else if (strcmp("-iw",argv[i]) == 0)
440
    {
441
      if ((i+1) < argc)
442
      {
443
        i++;
444
        iw_val = atoi(argv[i]);
445
      }
446
    }
447
    else if (strcmp("-fw",argv[i]) == 0)
448
    {
449
      if ((i+1) < argc)
450
      {
451
        i++;
452
        fw_val = atoi(argv[i]);
453
      }
454
    }
455
    else if (strcmp("-step",argv[i]) == 0)
456
    {
457
      if ((i+1) < argc)
458
      {
459
        i++;
460
        step_val = atof(argv[i]);
461
      }
462
    }
463
    else
464
    {
465
      if (argv[i][0] != '-')
466
      {
467
        file_o = fopen(argv[i], "wb");
468
        if (file_o == NULL)
469
        {
470
          fprintf(stderr,"Error: Can't write %s!\n", argv[i]);
471
          return -1;
472
        }
473
      }
474
    }
475
  }
476
 
477
  if (iw_val <= 0)
478
  {
479
    fprintf(stderr, "Error: IW must be greater than zero.\n");
480
    exit(1);
481
  }
482
  if (fw_val < 0)
483
  {
484
    fprintf(stderr, "Error: FW must be greater than or equal to zero.\n");
485
    exit(1);
486
  }
487
 
488
  /* Generate the test design. */
489
  print_test_design(file_o, iw_val, fw_val, step_val);
490
  fclose(file_o);
491
 
492
  return 0;
493
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.