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

Subversion Repositories neorv32

[/] [neorv32/] [trunk/] [sw/] [example/] [coremark/] [ee_printf.c] - Blame information for rev 47

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 38 zero_gravi
/*
2
Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC)
3 2 zero_gravi
 
4 38 zero_gravi
Licensed under the Apache License, Version 2.0 (the "License");
5
you may not use this file except in compliance with the License.
6
You may obtain a copy of the License at
7 2 zero_gravi
 
8 38 zero_gravi
    http://www.apache.org/licenses/LICENSE-2.0
9 2 zero_gravi
 
10 38 zero_gravi
Unless required by applicable law or agreed to in writing, software
11
distributed under the License is distributed on an "AS IS" BASIS,
12
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
See the License for the specific language governing permissions and
14
limitations under the License.
15
*/
16 2 zero_gravi
 
17 38 zero_gravi
/* Modified for the NEORV32 Processor - by Stephan Nolting */
18 2 zero_gravi
 
19 38 zero_gravi
#include <coremark.h>
20
#include <stdarg.h>
21 2 zero_gravi
 
22
#include <neorv32.h>
23
 
24 38 zero_gravi
#define ZEROPAD   (1 << 0) /* Pad with zero */
25
#define SIGN      (1 << 1) /* Unsigned/signed long */
26
#define PLUS      (1 << 2) /* Show plus */
27
#define SPACE     (1 << 3) /* Spacer */
28
#define LEFT      (1 << 4) /* Left justified */
29
#define HEX_PREP  (1 << 5) /* 0x */
30
#define UPPERCASE (1 << 6) /* 'ABCDEF' */
31 2 zero_gravi
 
32
#define is_digit(c) ((c) >= '0' && (c) <= '9')
33
 
34 38 zero_gravi
static char *    digits       = "0123456789abcdefghijklmnopqrstuvwxyz";
35
static char *    upper_digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
36
static ee_size_t strnlen(const char *s, ee_size_t count);
37 2 zero_gravi
 
38 38 zero_gravi
static ee_size_t
39
strnlen(const char *s, ee_size_t count)
40 2 zero_gravi
{
41 38 zero_gravi
    const char *sc;
42
    for (sc = s; *sc != '\0' && count--; ++sc)
43
        ;
44
    return sc - s;
45 2 zero_gravi
}
46
 
47 38 zero_gravi
static int
48
skip_atoi(const char **s)
49 2 zero_gravi
{
50 38 zero_gravi
    int i = 0;
51
    while (is_digit(**s))
52
        i = i * 10 + *((*s)++) - '0';
53
    return i;
54 2 zero_gravi
}
55
 
56 38 zero_gravi
static char *
57
number(char *str, long num, int base, int size, int precision, int type)
58 2 zero_gravi
{
59 38 zero_gravi
    char  c, sign, tmp[66];
60
    char *dig = digits;
61
    int   i;
62 2 zero_gravi
 
63 38 zero_gravi
    if (type & UPPERCASE)
64
        dig = upper_digits;
65
    if (type & LEFT)
66
        type &= ~ZEROPAD;
67
    if (base < 2 || base > 36)
68
        return 0;
69 2 zero_gravi
 
70 38 zero_gravi
    c    = (type & ZEROPAD) ? '0' : ' ';
71
    sign = 0;
72
    if (type & SIGN)
73 2 zero_gravi
    {
74 38 zero_gravi
        if (num < 0)
75
        {
76
            sign = '-';
77
            num  = -num;
78
            size--;
79
        }
80
        else if (type & PLUS)
81
        {
82
            sign = '+';
83
            size--;
84
        }
85
        else if (type & SPACE)
86
        {
87
            sign = ' ';
88
            size--;
89
        }
90 2 zero_gravi
    }
91 38 zero_gravi
 
92
    if (type & HEX_PREP)
93 2 zero_gravi
    {
94 38 zero_gravi
        if (base == 16)
95
            size -= 2;
96
        else if (base == 8)
97
            size--;
98 2 zero_gravi
    }
99
 
100 38 zero_gravi
    i = 0;
101 2 zero_gravi
 
102 38 zero_gravi
    if (num == 0)
103
        tmp[i++] = '0';
104
    else
105 2 zero_gravi
    {
106 38 zero_gravi
        while (num != 0)
107
        {
108
            tmp[i++] = dig[((unsigned long)num) % (unsigned)base];
109
            num      = ((unsigned long)num) / (unsigned)base;
110
        }
111 2 zero_gravi
    }
112
 
113 38 zero_gravi
    if (i > precision)
114
        precision = i;
115
    size -= precision;
116
    if (!(type & (ZEROPAD | LEFT)))
117
        while (size-- > 0)
118
            *str++ = ' ';
119
    if (sign)
120
        *str++ = sign;
121 2 zero_gravi
 
122 38 zero_gravi
    if (type & HEX_PREP)
123 2 zero_gravi
    {
124 38 zero_gravi
        if (base == 8)
125
            *str++ = '0';
126
        else if (base == 16)
127
        {
128
            *str++ = '0';
129
            *str++ = digits[33];
130
        }
131 2 zero_gravi
    }
132
 
133 38 zero_gravi
    if (!(type & LEFT))
134
        while (size-- > 0)
135
            *str++ = c;
136
    while (i < precision--)
137
        *str++ = '0';
138
    while (i-- > 0)
139
        *str++ = tmp[i];
140
    while (size-- > 0)
141
        *str++ = ' ';
142 2 zero_gravi
 
143 38 zero_gravi
    return str;
144 2 zero_gravi
}
145
 
146 38 zero_gravi
static char *
147
eaddr(char *str, unsigned char *addr, int size, int precision, int type)
148 2 zero_gravi
{
149 38 zero_gravi
    char  tmp[24];
150
    char *dig = digits;
151
    int   i, len;
152 2 zero_gravi
 
153 38 zero_gravi
    if (type & UPPERCASE)
154
        dig = upper_digits;
155
    len = 0;
156
    for (i = 0; i < 6; i++)
157
    {
158
        if (i != 0)
159
            tmp[len++] = ':';
160
        tmp[len++] = dig[addr[i] >> 4];
161
        tmp[len++] = dig[addr[i] & 0x0F];
162
    }
163 2 zero_gravi
 
164 38 zero_gravi
    if (!(type & LEFT))
165
        while (len < size--)
166
            *str++ = ' ';
167
    for (i = 0; i < len; ++i)
168
        *str++ = tmp[i];
169
    while (len < size--)
170
        *str++ = ' ';
171 2 zero_gravi
 
172 38 zero_gravi
    return str;
173 2 zero_gravi
}
174
 
175 38 zero_gravi
static char *
176
iaddr(char *str, unsigned char *addr, int size, int precision, int type)
177 2 zero_gravi
{
178 38 zero_gravi
    char tmp[24];
179
    int  i, n, len;
180 2 zero_gravi
 
181 38 zero_gravi
    len = 0;
182
    for (i = 0; i < 4; i++)
183 2 zero_gravi
    {
184 38 zero_gravi
        if (i != 0)
185
            tmp[len++] = '.';
186
        n = addr[i];
187 2 zero_gravi
 
188 38 zero_gravi
        if (n == 0)
189
            tmp[len++] = digits[0];
190
        else
191
        {
192
            if (n >= 100)
193
            {
194
                tmp[len++] = digits[n / 100];
195
                n          = n % 100;
196
                tmp[len++] = digits[n / 10];
197
                n          = n % 10;
198
            }
199
            else if (n >= 10)
200
            {
201
                tmp[len++] = digits[n / 10];
202
                n          = n % 10;
203
            }
204
 
205
            tmp[len++] = digits[n];
206
        }
207 2 zero_gravi
    }
208
 
209 38 zero_gravi
    if (!(type & LEFT))
210
        while (len < size--)
211
            *str++ = ' ';
212
    for (i = 0; i < len; ++i)
213
        *str++ = tmp[i];
214
    while (len < size--)
215
        *str++ = ' ';
216 2 zero_gravi
 
217 38 zero_gravi
    return str;
218 2 zero_gravi
}
219
 
220 38 zero_gravi
#if HAS_FLOAT
221 2 zero_gravi
 
222 38 zero_gravi
char *      ecvtbuf(double arg, int ndigits, int *decpt, int *sign, char *buf);
223
char *      fcvtbuf(double arg, int ndigits, int *decpt, int *sign, char *buf);
224 2 zero_gravi
static void ee_bufcpy(char *d, char *s, int count);
225
 
226 38 zero_gravi
void
227
ee_bufcpy(char *pd, char *ps, int count)
228
{
229
    char *pe = ps + count;
230
    while (ps != pe)
231
        *pd++ = *ps++;
232 2 zero_gravi
}
233
 
234 38 zero_gravi
static void
235
parse_float(double value, char *buffer, char fmt, int precision)
236 2 zero_gravi
{
237 38 zero_gravi
    int   decpt, sign, exp, pos;
238
    char *digits = NULL;
239
    char  cvtbuf[80];
240
    int   capexp = 0;
241
    int   magnitude;
242 2 zero_gravi
 
243 38 zero_gravi
    if (fmt == 'G' || fmt == 'E')
244 2 zero_gravi
    {
245 38 zero_gravi
        capexp = 1;
246
        fmt += 'a' - 'A';
247 2 zero_gravi
    }
248 38 zero_gravi
 
249
    if (fmt == 'g')
250 2 zero_gravi
    {
251 38 zero_gravi
        digits    = ecvtbuf(value, precision, &decpt, &sign, cvtbuf);
252
        magnitude = decpt - 1;
253
        if (magnitude < -4 || magnitude > precision - 1)
254
        {
255
            fmt = 'e';
256
            precision -= 1;
257
        }
258
        else
259
        {
260
            fmt = 'f';
261
            precision -= decpt;
262
        }
263 2 zero_gravi
    }
264
 
265 38 zero_gravi
    if (fmt == 'e')
266
    {
267
        digits = ecvtbuf(value, precision + 1, &decpt, &sign, cvtbuf);
268 2 zero_gravi
 
269 38 zero_gravi
        if (sign)
270
            *buffer++ = '-';
271
        *buffer++ = *digits;
272
        if (precision > 0)
273
            *buffer++ = '.';
274
        ee_bufcpy(buffer, digits + 1, precision);
275
        buffer += precision;
276
        *buffer++ = capexp ? 'E' : 'e';
277 2 zero_gravi
 
278 38 zero_gravi
        if (decpt == 0)
279
        {
280
            if (value == 0.0)
281
                exp = 0;
282
            else
283
                exp = -1;
284
        }
285
        else
286
            exp = decpt - 1;
287
 
288
        if (exp < 0)
289
        {
290
            *buffer++ = '-';
291
            exp       = -exp;
292
        }
293
        else
294
            *buffer++ = '+';
295
 
296
        buffer[2] = (exp % 10) + '0';
297
        exp       = exp / 10;
298
        buffer[1] = (exp % 10) + '0';
299
        exp       = exp / 10;
300
        buffer[0] = (exp % 10) + '0';
301
        buffer += 3;
302
    }
303
    else if (fmt == 'f')
304 2 zero_gravi
    {
305 38 zero_gravi
        digits = fcvtbuf(value, precision, &decpt, &sign, cvtbuf);
306
        if (sign)
307
            *buffer++ = '-';
308
        if (*digits)
309
        {
310
            if (decpt <= 0)
311
            {
312
                *buffer++ = '0';
313
                *buffer++ = '.';
314
                for (pos = 0; pos < -decpt; pos++)
315
                    *buffer++ = '0';
316
                while (*digits)
317
                    *buffer++ = *digits++;
318
            }
319
            else
320
            {
321
                pos = 0;
322
                while (*digits)
323
                {
324
                    if (pos++ == decpt)
325
                        *buffer++ = '.';
326
                    *buffer++ = *digits++;
327
                }
328
            }
329
        }
330
        else
331
        {
332
            *buffer++ = '0';
333
            if (precision > 0)
334
            {
335
                *buffer++ = '.';
336
                for (pos = 0; pos < precision; pos++)
337
                    *buffer++ = '0';
338
            }
339
        }
340 2 zero_gravi
    }
341
 
342 38 zero_gravi
    *buffer = '\0';
343
}
344
 
345
static void
346
decimal_point(char *buffer)
347
{
348
    while (*buffer)
349 2 zero_gravi
    {
350 38 zero_gravi
        if (*buffer == '.')
351
            return;
352
        if (*buffer == 'e' || *buffer == 'E')
353
            break;
354
        buffer++;
355 2 zero_gravi
    }
356
 
357 38 zero_gravi
    if (*buffer)
358 2 zero_gravi
    {
359 38 zero_gravi
        int n = strnlen(buffer, 256);
360
        while (n > 0)
361 2 zero_gravi
        {
362 38 zero_gravi
            buffer[n + 1] = buffer[n];
363
            n--;
364 2 zero_gravi
        }
365 38 zero_gravi
 
366
        *buffer = '.';
367 2 zero_gravi
    }
368
    else
369
    {
370
        *buffer++ = '.';
371 38 zero_gravi
        *buffer   = '\0';
372 2 zero_gravi
    }
373
}
374
 
375 38 zero_gravi
static void
376
cropzeros(char *buffer)
377 2 zero_gravi
{
378 38 zero_gravi
    char *stop;
379 2 zero_gravi
 
380 38 zero_gravi
    while (*buffer && *buffer != '.')
381
        buffer++;
382
    if (*buffer++)
383 2 zero_gravi
    {
384 38 zero_gravi
        while (*buffer && *buffer != 'e' && *buffer != 'E')
385
            buffer++;
386
        stop = buffer--;
387
        while (*buffer == '0')
388
            buffer--;
389
        if (*buffer == '.')
390
            buffer--;
391
        while (buffer != stop)
392
            *++buffer = 0;
393 2 zero_gravi
    }
394
}
395
 
396 38 zero_gravi
static char *
397
flt(char *str, double num, int size, int precision, char fmt, int flags)
398 2 zero_gravi
{
399 38 zero_gravi
    char tmp[80];
400
    char c, sign;
401
    int  n, i;
402 2 zero_gravi
 
403 38 zero_gravi
    // Left align means no zero padding
404
    if (flags & LEFT)
405
        flags &= ~ZEROPAD;
406 2 zero_gravi
 
407 38 zero_gravi
    // Determine padding and sign char
408
    c    = (flags & ZEROPAD) ? '0' : ' ';
409
    sign = 0;
410
    if (flags & SIGN)
411 2 zero_gravi
    {
412 38 zero_gravi
        if (num < 0.0)
413
        {
414
            sign = '-';
415
            num  = -num;
416
            size--;
417
        }
418
        else if (flags & PLUS)
419
        {
420
            sign = '+';
421
            size--;
422
        }
423
        else if (flags & SPACE)
424
        {
425
            sign = ' ';
426
            size--;
427
        }
428 2 zero_gravi
    }
429
 
430 38 zero_gravi
    // Compute the precision value
431
    if (precision < 0)
432
        precision = 6; // Default precision: 6
433 2 zero_gravi
 
434 38 zero_gravi
    // Convert floating point number to text
435
    parse_float(num, tmp, fmt, precision);
436 2 zero_gravi
 
437 38 zero_gravi
    if ((flags & HEX_PREP) && precision == 0)
438
        decimal_point(tmp);
439
    if (fmt == 'g' && !(flags & HEX_PREP))
440
        cropzeros(tmp);
441 2 zero_gravi
 
442 38 zero_gravi
    n = strnlen(tmp, 256);
443 2 zero_gravi
 
444 38 zero_gravi
    // Output number with alignment and padding
445
    size -= n;
446
    if (!(flags & (ZEROPAD | LEFT)))
447
        while (size-- > 0)
448
            *str++ = ' ';
449
    if (sign)
450
        *str++ = sign;
451
    if (!(flags & LEFT))
452
        while (size-- > 0)
453
            *str++ = c;
454
    for (i = 0; i < n; i++)
455
        *str++ = tmp[i];
456
    while (size-- > 0)
457
        *str++ = ' ';
458 2 zero_gravi
 
459 38 zero_gravi
    return str;
460 2 zero_gravi
}
461
 
462
#endif
463
 
464 38 zero_gravi
static int
465
ee_vsprintf(char *buf, const char *fmt, va_list args)
466 2 zero_gravi
{
467 38 zero_gravi
    int           len;
468
    unsigned long num;
469
    int           i, base;
470
    char *        str;
471
    char *        s;
472 2 zero_gravi
 
473 38 zero_gravi
    int flags; // Flags to number()
474 2 zero_gravi
 
475 38 zero_gravi
    int field_width; // Width of output field
476
    int precision;   // Min. # of digits for integers; max number of chars for
477
                     // from string
478
    int qualifier;   // 'h', 'l', or 'L' for integer fields
479 2 zero_gravi
 
480 38 zero_gravi
    for (str = buf; *fmt; fmt++)
481 2 zero_gravi
    {
482 38 zero_gravi
        if (*fmt != '%')
483
        {
484
            *str++ = *fmt;
485
            continue;
486
        }
487 2 zero_gravi
 
488 38 zero_gravi
        // Process flags
489
        flags = 0;
490
    repeat:
491
        fmt++; // This also skips first '%'
492
        switch (*fmt)
493
        {
494
            case '-':
495
                flags |= LEFT;
496
                goto repeat;
497
            case '+':
498
                flags |= PLUS;
499
                goto repeat;
500
            case ' ':
501
                flags |= SPACE;
502
                goto repeat;
503
            case '#':
504
                flags |= HEX_PREP;
505
                goto repeat;
506
            case '0':
507
                flags |= ZEROPAD;
508
                goto repeat;
509
        }
510 2 zero_gravi
 
511 38 zero_gravi
        // Get field width
512
        field_width = -1;
513
        if (is_digit(*fmt))
514
            field_width = skip_atoi(&fmt);
515
        else if (*fmt == '*')
516
        {
517
            fmt++;
518
            field_width = va_arg(args, int);
519
            if (field_width < 0)
520
            {
521
                field_width = -field_width;
522
                flags |= LEFT;
523
            }
524
        }
525 2 zero_gravi
 
526 38 zero_gravi
        // Get the precision
527
        precision = -1;
528
        if (*fmt == '.')
529
        {
530
            ++fmt;
531
            if (is_digit(*fmt))
532
                precision = skip_atoi(&fmt);
533
            else if (*fmt == '*')
534
            {
535
                ++fmt;
536
                precision = va_arg(args, int);
537
            }
538
            if (precision < 0)
539
                precision = 0;
540
        }
541 2 zero_gravi
 
542 38 zero_gravi
        // Get the conversion qualifier
543
        qualifier = -1;
544
        if (*fmt == 'l' || *fmt == 'L')
545
        {
546
            qualifier = *fmt;
547
            fmt++;
548
        }
549 2 zero_gravi
 
550 38 zero_gravi
        // Default base
551
        base = 10;
552 2 zero_gravi
 
553 38 zero_gravi
        switch (*fmt)
554
        {
555
            case 'c':
556
                if (!(flags & LEFT))
557
                    while (--field_width > 0)
558
                        *str++ = ' ';
559
                *str++ = (unsigned char)va_arg(args, int);
560
                while (--field_width > 0)
561
                    *str++ = ' ';
562
                continue;
563 2 zero_gravi
 
564 38 zero_gravi
            case 's':
565
                s = va_arg(args, char *);
566
                if (!s)
567
                    s = "<NULL>";
568
                len = strnlen(s, precision);
569
                if (!(flags & LEFT))
570
                    while (len < field_width--)
571
                        *str++ = ' ';
572
                for (i = 0; i < len; ++i)
573
                    *str++ = *s++;
574
                while (len < field_width--)
575
                    *str++ = ' ';
576
                continue;
577 2 zero_gravi
 
578 38 zero_gravi
            case 'p':
579
                if (field_width == -1)
580
                {
581
                    field_width = 2 * sizeof(void *);
582
                    flags |= ZEROPAD;
583
                }
584
                str = number(str,
585
                             (unsigned long)va_arg(args, void *),
586
                             16,
587
                             field_width,
588
                             precision,
589
                             flags);
590
                continue;
591 2 zero_gravi
 
592 38 zero_gravi
            case 'A':
593
                flags |= UPPERCASE;
594 2 zero_gravi
 
595 38 zero_gravi
            case 'a':
596
                if (qualifier == 'l')
597
                    str = eaddr(str,
598
                                va_arg(args, unsigned char *),
599
                                field_width,
600
                                precision,
601
                                flags);
602
                else
603
                    str = iaddr(str,
604
                                va_arg(args, unsigned char *),
605
                                field_width,
606
                                precision,
607
                                flags);
608
                continue;
609 2 zero_gravi
 
610 38 zero_gravi
            // Integer number formats - set up the flags and "break"
611
            case 'o':
612
                base = 8;
613
                break;
614 2 zero_gravi
 
615 38 zero_gravi
            case 'X':
616
                flags |= UPPERCASE;
617 2 zero_gravi
 
618 38 zero_gravi
            case 'x':
619
                base = 16;
620
                break;
621 2 zero_gravi
 
622 38 zero_gravi
            case 'd':
623
            case 'i':
624
                flags |= SIGN;
625 2 zero_gravi
 
626 38 zero_gravi
            case 'u':
627
                break;
628 2 zero_gravi
 
629 38 zero_gravi
#if HAS_FLOAT
630 2 zero_gravi
 
631 38 zero_gravi
            case 'f':
632
                str = flt(str,
633
                          va_arg(args, double),
634
                          field_width,
635
                          precision,
636
                          *fmt,
637
                          flags | SIGN);
638
                continue;
639 2 zero_gravi
 
640
#endif
641
 
642 38 zero_gravi
            default:
643
                if (*fmt != '%')
644
                    *str++ = '%';
645
                if (*fmt)
646
                    *str++ = *fmt;
647
                else
648
                    --fmt;
649
                continue;
650
        }
651
 
652
        if (qualifier == 'l')
653
            num = va_arg(args, unsigned long);
654
        else if (flags & SIGN)
655
            num = va_arg(args, int);
656 2 zero_gravi
        else
657 38 zero_gravi
            num = va_arg(args, unsigned int);
658
 
659
        str = number(str, num, base, field_width, precision, flags);
660 2 zero_gravi
    }
661
 
662 38 zero_gravi
    *str = '\0';
663
    return str - buf;
664
}
665 2 zero_gravi
 
666 38 zero_gravi
void
667
uart_send_char(char c)
668
{
669
//#error "You must implement the method uart_send_char to use this file!\n";
670
    /*  Output of a char to a UART usually follows the following model:
671
            Wait until UART is ready
672
            Write char to UART
673
            Wait until UART is done
674 2 zero_gravi
 
675 38 zero_gravi
            Or in code:
676
            while (*UART_CONTROL_ADDRESS != UART_READY);
677
            *UART_DATA_ADDRESS = c;
678
            while (*UART_CONTROL_ADDRESS != UART_READY);
679 2 zero_gravi
 
680 38 zero_gravi
            Check the UART sample code on your platform or the board
681
       documentation.
682
    */
683
 
684
  /* NEORV32-specific */
685
  if (c == '\n') {
686 2 zero_gravi
    neorv32_uart_putc('\r');
687 38 zero_gravi
  }
688 2 zero_gravi
  neorv32_uart_putc(c);
689
}
690
 
691 38 zero_gravi
int
692
ee_printf(const char *fmt, ...)
693 2 zero_gravi
{
694 38 zero_gravi
    char    buf[256], *p;
695
    va_list args;
696
    int     n = 0;
697 2 zero_gravi
 
698 38 zero_gravi
    va_start(args, fmt);
699
    ee_vsprintf(buf, fmt, args);
700
    va_end(args);
701
    p = buf;
702
    while (*p)
703
    {
704
        uart_send_char(*p);
705
        n++;
706
        p++;
707
    }
708 2 zero_gravi
 
709 38 zero_gravi
    return n;
710 2 zero_gravi
}

powered by: WebSVN 2.1.0

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