summaryrefslogtreecommitdiff
path: root/build-aux
diff options
context:
space:
mode:
authorLuke T. Shumaker <lukeshu@lukeshu.com>2025-02-21 09:02:22 -0700
committerLuke T. Shumaker <lukeshu@lukeshu.com>2025-02-21 10:33:25 -0700
commit5dab625d981e0039a5d874f5d8a6f795472785bc (patch)
treea89dead6dd34f95b3e644edeb02fe1ca70a28784 /build-aux
parent3d5cb59006cf393a97ad3f87ef64fb258fd79ce9 (diff)
Make use of the generated stack.c
Diffstat (limited to 'build-aux')
-rwxr-xr-xbuild-aux/stack.c.gen124
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]