diff --git a/litex/soc/software/include/base/progress.h b/litex/soc/software/include/base/progress.h new file mode 100644 index 000000000..75aa9c4f8 --- /dev/null +++ b/litex/soc/software/include/base/progress.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef __PROGRSS_H +#define __PROGRSS_H + +/* Initialize a progress bar. If max > 0 a one line progress + * bar is printed where 'max' corresponds to 100%. If max == 0 + * a multi line progress bar is printed. + */ +void init_progression_bar(int max); + +/* update a progress bar to a new value. If now < 0 then a + * spinner is printed. + */ +void show_progress(int now); + +#endif /* __PROGRSS_H */ diff --git a/litex/soc/software/libbase/Makefile b/litex/soc/software/libbase/Makefile index dff9f7188..107c87364 100755 --- a/litex/soc/software/libbase/Makefile +++ b/litex/soc/software/libbase/Makefile @@ -2,7 +2,8 @@ include ../include/generated/variables.mak include $(SOC_DIRECTORY)/software/common.mak OBJECTS = exception.o libc.o errno.o crc16.o crc32.o console.o \ - system.o id.o uart.o time.o qsort.o strtod.o spiflash.o strcasecmp.o i2c.o + system.o id.o uart.o time.o qsort.o strtod.o spiflash.o strcasecmp.o i2c.o \ + progress.o all: crt0-ctr.o crt0-xip.o libbase.a libbase-nofloat.a diff --git a/litex/soc/software/libbase/progress.c b/litex/soc/software/libbase/progress.c new file mode 100644 index 000000000..c13b2dad4 --- /dev/null +++ b/litex/soc/software/libbase/progress.c @@ -0,0 +1,114 @@ +/* + * show_progress.c - simple progress bar functions + * + * Copyright (c) 2010 Sascha Hauer , Pengutronix + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include + +#define FILESIZE_MAX 100000000 +#define HASHES_PER_LINE 65 + +static int printed; +static int progress_max; +static int spin; + +uint32_t __div64_32(uint64_t *n, uint32_t base) +{ + uint64_t rem = *n; + uint64_t b = base; + uint64_t res, d = 1; + uint32_t high = rem >> 32; + + /* Reduce the thing a bit first */ + res = 0; + if (high >= base) { + high /= base; + res = (uint64_t) high << 32; + rem -= (uint64_t) (high*base) << 32; + } + + while ((int64_t)b > 0 && b < rem) { + b = b+b; + d = d+d; + } + + do { + if (rem >= b) { + rem -= b; + res += d; + } + b >>= 1; + d >>= 1; + } while (d); + + *n = res; + return rem; +} + + +/* The unnecessary pointer compare is there + * to check for type safety (n must be 64bit) + */ +# define do_div(n,base) ({ \ + uint32_t __base = (base); \ + uint32_t __rem; \ + (void)(((typeof((n)) *)0) == ((uint64_t *)0)); \ + if (((n) >> 32) == 0) { \ + __rem = (uint32_t)(n) % __base; \ + (n) = (uint32_t)(n) / __base; \ + } else \ + __rem = __div64_32(&(n), __base); \ + __rem; \ + }) + + +void show_progress(int now) +{ + char spinchr[] = "\\|/-"; + + if (now < 0) { + printf("%c\b", spinchr[spin++ % (sizeof(spinchr) - 1)]); + return; + } + + if (progress_max && progress_max != FILESIZE_MAX) { + uint64_t tmp = (int64_t)now * HASHES_PER_LINE; + do_div(tmp, progress_max); + now = tmp; + } + + while (printed < now) { + if (!(printed % HASHES_PER_LINE) && printed) + printf("\n\t"); + printf("#"); + printed++; + } +} + +void init_progression_bar(int max) +{ + printed = 0; + progress_max = max; + spin = 0; + if (progress_max && progress_max != FILESIZE_MAX) + printf("\t[%*s]\r\t[", HASHES_PER_LINE, ""); + else + printf("\t"); +}