Skip to main content
  • Home
  • Development
  • Documentation
  • Donate
  • Operational login
  • Browse the archive

swh logo
SoftwareHeritage
Software
Heritage
Archive
Features
  • Search

  • Downloads

  • Save code now

  • Add forge now

  • Help

  • 1f49178
  • /
  • genskiplist.py
Raw File Download
Permalinks

To reference or cite the objects present in the Software Heritage archive, permalinks based on SoftWare Hash IDentifiers (SWHIDs) must be used.
Select below a type of object currently browsed in order to display its associated SWHID and permalink.

  • content
  • directory
content badge Iframe embedding
swh:1:cnt:7538dc8e732640c9bcf42070cba50118f460c8ba
directory badge Iframe embedding
swh:1:dir:1f491788a8ac49f00513ac7e0e99922b07e80044
Citations

This interface enables to generate software citations, provided that the root directory of browsed objects contains a citation.cff or codemeta.json file.
Select below a type of object currently browsed in order to generate citations for them.

  • content
  • directory
Generate software citation in BibTex format (requires biblatex-software package)
Generating citation ...
Generate software citation in BibTex format (requires biblatex-software package)
Generating citation ...
genskiplist.py
#!/usr/bin/env python3
"""This script is used to generate the skiplist.py files in pqm{4,3}. It
takes the output files from the mps2-an386 target, when run via the make
script, i.e., compile pqm{4,3} with the mps2-an38{6,5} plattform and the
run-stack-tests targets (remember to backup your benchmark results, if
you want to keep them!):

    cp -r benchmarks benchmarks.bak
    make clean # Because this will delete it
    make PLATFORM=mps2-an386 -j4 run-stack-tests
    find benchmarks -name frommake -exec python3 mupq/genskiplist.py {} + > skiplist.py

You can also simply update a single scheme:

    make PLATFORM=mps2-an386 benchmarks/stack/crypto_kem/mysuperscheme/opt/frommake
    python3 mupq/genskiplist.py benchmarks/stack/crypto_kem/mysuperscheme/opt/frommake
"""

import argparse
import pprint
import re
import sys


def parse_arguments():
    parser = argparse.ArgumentParser(
        description="Generate a skiplist.py",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog=__doc__
    )
    parser.add_argument(
        "inputs",
        help="Stack benchmark output of mps2 platform",
        nargs="+",
        type=argparse.FileType("r"),
    )
    parser.add_argument(
        "-r",
        "--round",
        help="Round up the usage to N bytes",
        default=1024,
        type=int,
        metavar="N",
    )
    parser.add_argument(
        "-m",
        "--margin",
        help="Add N bytes of additional stack margin",
        default=32,
        type=int,
        metavar="M",
    )
    return parser.parse_args()


def parse_flashsize(contents):
    match = re.search(
        r"^\s+(?P<text>\d+)"
        r"\s+(?P<data>\d+)"
        r"\s+(?P<bss>\d+)"
        r"\s+(?P<dec>\d+)"
        r"\s+(?P<hex>[0-9A-Fa-f]+)"
        r"\s+(?P<filename>[a-zA-Z0-9_\-/\.]+)",
        contents,
        re.MULTILINE,
    )
    if match is None:
        raise Exception("Size output not found!")
    text = int(match.group("text"))
    data = int(match.group("data"))
    bss = int(match.group("bss"))
    return match.group("filename"), text + data, data + bss


def parse_stackusage(contents):
    match = re.search(
        r"^keypair stack usage:\s+(?P<usage>\d+)",
        contents,
        re.MULTILINE,
    )
    if match is None:
        raise Exception("keypair usage not found")
    keypair = int(match.group("usage"))
    match = re.search(
        r"^(sign|decaps) stack usage:\s+(?P<usage>\d+)",
        contents,
        re.MULTILINE,
    )
    if match is None:
        raise Exception("private-op usage not found")
    private = int(match.group("usage"))
    match = re.search(
        r"^(verify|decaps) stack usage:\s+(?P<usage>\d+)",
        contents,
        re.MULTILINE,
    )
    if match is None:
        raise Exception("public-op usage not found")
    public = int(match.group("usage"))
    return max(keypair, public, private)


def parse_filename(filename):
    match = re.match(
        r"elf/(?P<project>|mupq|mupq_pqclean)_?"
        r"crypto_(?P<type>kem|sign)_"
        r"(?P<scheme>[a-zA-Z0-9_\-]+)_"
        r"(?P<impl>[a-zA-Z0-9_\-]+)"
        r"_stack\.elf",
        filename,
    )
    if match is None:
        raise Exception("Can't parse filename!")
    project = match.group("project")
    scheme = match.group("scheme")
    impl = match.group("impl")
    return project, scheme, impl


def roundto(x, to):
    return x + (to - x % to)


def main():
    args = parse_arguments()
    schemes = []
    for f in args.inputs:
        contents = f.read()
        # Check for failed test
        try:
            filename, flashsize, ramsize = parse_flashsize(contents)
            project, scheme, impl = parse_filename(filename)
            match = re.search("HardFault", contents, re.MULTILINE)
            if match is None:
                stackusage = parse_stackusage(contents)
            else:
                stackusage = 4096 * 1024
        except Exception as e:
            if "usage not found" in str(e):
                stackusage = 4096 * 1024
            else:
                print(f"Error during parsing file {f.name}: {e}", file=sys.stderr)
                continue
        memoryusage = roundto(stackusage + ramsize + args.margin, args.round)
        print(
            f"Scheme: {scheme} Context: {project} Implementation: {impl} Flashsize: {flashsize} Memorysize: {memoryusage}",
            file=sys.stderr,
        )
        schemes.append(
            {
                "scheme": scheme,
                "implementation": impl,
                # 'project': (project + "/") if len(project) > 0 else "",
                "estmemory": memoryusage,
            }
        )
        # if project == "":
        #     del schemes[-1]['project']
    print("skip_list = [")
    for it in schemes:
        print(
            "    "
            + pprint.pformat(it, indent=4, compact=False, sort_dicts=False, width=110),
            end=",\n",
        )
    print("]")


if __name__ == "__main__":
    main()

Software Heritage — Copyright (C) 2015–2025, The Software Heritage developers. License: GNU AGPLv3+.
The source code of Software Heritage itself is available on our development forge.
The source code files archived by Software Heritage are available under their own copyright and licenses.
Terms of use: Archive access, API— Contact— JavaScript license information— Web API

back to top