diff options
author | Luke T. Shumaker <lukeshu@lukeshu.com> | 2025-02-21 09:02:22 -0700 |
---|---|---|
committer | Luke T. Shumaker <lukeshu@lukeshu.com> | 2025-02-21 10:33:25 -0700 |
commit | 5dab625d981e0039a5d874f5d8a6f795472785bc (patch) | |
tree | a89dead6dd34f95b3e644edeb02fe1ca70a28784 /build-aux | |
parent | 3d5cb59006cf393a97ad3f87ef64fb258fd79ce9 (diff) |
Make use of the generated stack.c
Diffstat (limited to 'build-aux')
-rwxr-xr-x | build-aux/stack.c.gen | 124 |
1 files changed, 84 insertions, 40 deletions
diff --git a/build-aux/stack.c.gen b/build-aux/stack.c.gen index af5d740..07d5cfc 100755 --- a/build-aux/stack.c.gen +++ b/build-aux/stack.c.gen @@ -131,6 +131,18 @@ def synthetic_node( return n +class AnalyzeResultGroup(typing.NamedTuple): + rows: dict[str, int] + nmax: int + nsum: int + + +class AnalyzeResult(typing.NamedTuple): + groups: dict[str, AnalyzeResultGroup] + missing: set[str] + dynamic: set[str] + + def analyze( *, ci_fnames: list[str], @@ -140,7 +152,7 @@ def analyze( app_indirect_callees: typing.Callable[[VCGElem], list[str]], app_skip_call: typing.Callable[[list[str], str], bool], cfg_max_call_depth: int, -) -> None: +) -> AnalyzeResult: re_node_label = re.compile( r"(?P<funcname>[^\n]+)\n" + r"(?P<location>[^\n]+:[0-9]+:[0-9]+)\n" @@ -281,10 +293,8 @@ def analyze( ] ) - print("/*") - + groups: dict[str, AnalyzeResultGroup] = dict() for grp_name, grp_filter in app_func_filters.items(): - # Gather the data. nmax = 0 nsum = 0 rows: dict[str, int] = {} @@ -295,28 +305,9 @@ def analyze( if n > nmax: nmax = n nsum += cnt * n + groups[grp_name] = AnalyzeResultGroup(rows=rows, nmax=nmax, nsum=nsum) - # Figure sizes. - namelen = max([len(k) for k in rows.keys()] + [len(grp_name) + 4]) - numlen = len(str(nsum)) - sep1 = ("=" * namelen) + " " + "=" * numlen - sep2 = ("-" * namelen) + " " + "-" * numlen - - # Print. - print("= " + grp_name + " " + sep1[len(grp_name) + 3 :]) - for name, num in sorted(rows.items()): - print(f"{name.ljust(namelen)} {str(num).rjust(numlen)}") - print(sep2) - print(f"{'Total'.ljust(namelen)} {str(nsum).rjust(numlen)}") - print(f"{'Maximum'.ljust(namelen)} {str(nmax).rjust(numlen)}") - print(sep1) - - for funcname in sorted(missing): - print(f"warning: missing: {funcname}") - for funcname in sorted(dynamic): - print(f"warning: dynamic-stack-usage: {funcname}") - - print("*/") + return AnalyzeResult(groups=groups, missing=missing, dynamic=dynamic) ################################################################################ @@ -434,10 +425,13 @@ def main( def sbc_is_thread(name: str) -> int: if name.endswith("_cr") and name != "lib9p_srv_read_cr": if "9p" in name: + # TODO: FIXME: Sniff these numbers from config.h + _CONFIG_9P_NUM_SOCKS = 3 + CONFIG_9P_SRV_MAX_REQS = 2 if "read" in name: - return 8 + return _CONFIG_9P_NUM_SOCKS elif "write" in name: - return 16 + return _CONFIG_9P_NUM_SOCKS * CONFIG_9P_SRV_MAX_REQS return 1 if name == "main": return True @@ -463,7 +457,7 @@ def main( # 4=just 2 levels of subdirectories # ... # - # TODO: Sniff this from config.h + # TODO: FIXME: Sniff this from config.h CONFIG_9P_SRV_MAX_DEPTH = 3 def sbc_skip_call(chain: list[str], call: str) -> bool: @@ -632,14 +626,12 @@ def main( # src/rp2040/boot_stage2/boot2_${name,,}.S for name=W25Q080, # controlled by `#define PICO_BOOT_STAGE2_{name} 1` in # src/boards/include/boards/pico.h - synthetic_node("_stage2_boot", 0), # TODO + # synthetic_node("_stage2_boot", 0), # TODO # https://github.com/raspberrypi/pico-bootrom-rp2040 - synthetic_node( - "rom_func_lookup(ROM_FUNC_CONNECT_INTERNAL_FLASH)", 0 - ), # TODO - synthetic_node("rom_func_lookup(ROM_FUNC_FLASH_EXIT_XIP)", 0), # TODO - synthetic_node("rom_func_lookup(ROM_FUNC_FLASH_FLUSH_CACHE)", 0), # TODO - synthetic_node("rom_hword_as_ptr(BOOTROM_TABLE_LOOKUP_OFFSET)", 0), # TODO + # synthetic_node("rom_func_lookup(ROM_FUNC_CONNECT_INTERNAL_FLASH)", 0), # TODO + # synthetic_node("rom_func_lookup(ROM_FUNC_FLASH_EXIT_XIP)", 0), # TODO + # synthetic_node("rom_func_lookup(ROM_FUNC_FLASH_FLUSH_CACHE)", 0), # TODO + # synthetic_node("rom_hword_as_ptr(BOOTROM_TABLE_LOOKUP_OFFSET)", 0), # TODO ] # TinyUSB device ################################################# @@ -736,10 +728,10 @@ def main( synthetic_node("realloc", 8, {"_realloc_r"}), synthetic_node("aligned_alloc", 8, {"_memalign_r"}), synthetic_node("reallocarray", 24, {"realloc", "__errno"}), - synthetic_node("_free_r", 0), # TODO - synthetic_node("_malloc_r", 0), # TODO - synthetic_node("_realloc_r", 0), # TODO - synthetic_node("_memalign_r", 0), # TODO + # synthetic_node("_free_r", 0), # TODO + # synthetic_node("_malloc_r", 0), # TODO + # synthetic_node("_realloc_r", 0), # TODO + # synthetic_node("_memalign_r", 0), # TODO # execution synthetic_node("raise", 16, {"_getpid_r"}), synthetic_node("abort", 8, {"raise", "_exit"}), @@ -816,7 +808,7 @@ def main( return True return False - analyze( + result = analyze( ci_fnames=arg_ci_fnames, extra_nodes=all_nodes, app_func_filters={ @@ -830,6 +822,58 @@ def main( cfg_max_call_depth=100, ) + def print_group(grp_name: str) -> None: + grp = result.groups[grp_name] + + # Figure sizes. + namelen = max([len(k) for k in grp.rows.keys()] + [len(grp_name) + 4]) + numlen = len(str(grp.nsum)) + sep1 = ("=" * namelen) + " " + "=" * numlen + sep2 = ("-" * namelen) + " " + "-" * numlen + + # Print. + print("= " + grp_name + " " + sep1[len(grp_name) + 3 :]) + for name, num in sorted(grp.rows.items()): + print(f"{name.ljust(namelen)} {str(num).rjust(numlen)}") + print(sep2) + print(f"{'Total'.ljust(namelen)} {str(grp.nsum).rjust(numlen)}") + print(f"{'Maximum'.ljust(namelen)} {str(grp.nmax).rjust(numlen)}") + print(sep1) + + def next_power_of_2(x: int) -> int: + return 1 << (x.bit_length()) + + print("#include <stddef.h> /* for size_t */") + print() + print("/*") + print_group("Threads") + print_group("Interrupt handlers") + print("*/") + overhead = result.groups["Interrupt handlers"].nmax + rows: list[tuple[str, int, int]] = [] + for funcname, base in result.groups["Threads"].rows.items(): + rows.append((funcname.split(":")[-1], base, next_power_of_2(base + overhead))) + namelen = max(len(r[0]) for r in rows) + baselen = max(len(str(r[1])) for r in rows) + sizelen = max(len(str(r[2])) for r in rows) + for row in sorted(rows): + if row[0] == "main": + continue + print("const size_t CONFIG_COROUTINE_STACK_SIZE_", end="") + print(f"{row[0].ljust(namelen)} =", end="") + print(f" {str(row[2]).rjust(sizelen)};", end="") + print(f" /* LM_NEXT_POWER_OF_2({str(row[1]).rjust(baselen)}+{overhead}) */") + print() + print("/*") + print_group("Misc") + + for funcname in sorted(result.missing): + print(f"warning: missing: {funcname}") + for funcname in sorted(result.dynamic): + print(f"warning: dynamic-stack-usage: {funcname}") + + print("*/") + if __name__ == "__main__": pico_platform = sys.argv[1] |