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

Subversion Repositories steelcore

[/] [coremark/] [steel/] [ee_printf.c] - Blame information for rev 11

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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