diff --git a/docs/conf.py b/docs/conf.py index ea7f8a02d..7b66c26f6 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -20,15 +20,14 @@ # Updated documentation of the configuration options is available at # https://www.sphinx-doc.org/en/master/usage/configuration.html -import sys, os +from sys import path as sys_path from pathlib import Path from tabulate import tabulate ROOT = Path(__file__).resolve().parent -#sys.path.insert(0, os.path.abspath('.')) -sys.path.insert(0, str(ROOT)) +sys_path.insert(0, str(ROOT)) from changes import generate_changes_inc @@ -69,6 +68,7 @@ extensions = [ 'sphinx.ext.extlinks', 'sphinx.ext.intersphinx', + "sphinxcontrib.autoprogram", 'sphinx_verilog_domain', 'sphinxcontrib.bibtex', 'myst_parser' diff --git a/docs/f4pga/Reference.rst b/docs/f4pga/Reference.rst new file mode 100644 index 000000000..396f9f76c --- /dev/null +++ b/docs/f4pga/Reference.rst @@ -0,0 +1,6 @@ +Reference +######### + +.. autoprogram:: f4pga.cli:CLI().MainParser + :prog: f4pga + :groups: diff --git a/docs/index.rst b/docs/index.rst index 4ef3e126d..16a2a5ca2 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -66,6 +66,7 @@ Table of Contents f4pga/Usage f4pga/modules/index f4pga/DevNotes + f4pga/Reference f4pga/Deprecated diff --git a/docs/requirements.txt b/docs/requirements.txt index 44c25a31f..1398ef3ff 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,6 +1,8 @@ +-r ../f4pga/requirements.txt myst-parser pyyaml sphinx>=4.5.0 +sphinxcontrib-autoprogram sphinxcontrib-bibtex https://github.com/f4pga/sphinx_f4pga_theme/archive/f4pga.zip#sphinx-f4pga-theme https://github.com/SymbiFlow/sphinx-verilog-domain/archive/master.zip#sphinx-verilog-domain diff --git a/f4pga/cli.py b/f4pga/cli.py new file mode 100644 index 000000000..6ef7828d3 --- /dev/null +++ b/f4pga/cli.py @@ -0,0 +1,228 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# Copyright (C) 2022 F4PGA Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 + +from pyAttributes.ArgParseAttributes import ( + ArgParseMixin, + ArgumentAttribute, + Attribute, + CommandAttribute, + CommonSwitchArgumentAttribute, + DefaultAttribute, + SwitchArgumentAttribute, +) + + +class CLI(ArgParseMixin): + HeadLine = "FOSS Flows For FPGA (F4PGA) command-line tool" + + def __init__(self): + import argparse + import textwrap + + # Call constructor of the main interitance tree + super().__init__() + # Call constructor of the ArgParseMixin + ArgParseMixin.__init__( + self, + description=textwrap.dedent( + """ + Long description... + """ + ), + epilog=textwrap.fill("Happy hacking!"), + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + add_help=False, + ) + + def PrintHeadline(self): + print("{line}".format(line="=" * 80)) + print("{headline: ^80s}".format(headline=self.HeadLine)) + print("{line}".format(line="=" * 80)) + + @CommonSwitchArgumentAttribute( + "-n", + "--noexec", + dest="noexec", + help="Print commands but do not execute them.", + default=False, + ) + def Run(self): + ArgParseMixin.Run(self) + + @DefaultAttribute() + def HandleDefault(self, args): + self.PrintHeadline() + self.MainParser.print_help() + + @CommandAttribute("help", help="Display help page(s) for the given command name.") + @ArgumentAttribute( + dest="Command", + type=str, + nargs="?", + help="Print help page(s) for a command.", + ) + def HandleHelp(self, args): + if args.Command == "help": + print("This is a recursion ...") + return + if args.Command is None: + self.PrintHeadline() + self.MainParser.print_help() + else: + try: + self.PrintHeadline() + self.SubParsers[args.Command].print_help() + except KeyError: + print("command {0} is unknown.".format(args.Command)) + + @CommandAttribute( + "analysis", + help="???.", + description="???." + ) + def HandleAnalysis(self, args): + print("ANALYSIS!") + + @CommandAttribute( + "synth", + help="???.", + description="???." + ) + def HandleSynth(self, args): + print("SYNTH!") + + @CommandAttribute( + "pack", + help="???.", + description="???." + ) + def HandlePack(self, args): + print("PACK!") + + @CommandAttribute( + "generate", + help="???.", + description="???." + ) + def HandleGenerate(self, args): + print("GENERATE!") + + # FIXME This is a subcommand of 'generate' + @CommandAttribute( + "constraints", + help="???.", + description="???." + ) + def HandleGenerateConstraints(self, args): + print("GENERATE CONSTRAINTS!") + + # FIXME This is a subcommand of 'generate' + @CommandAttribute( + "fasm2bels", + help="???.", + description="???." + ) + def HandleGenerateFASM2Bells(self, args): + print("GENERATE FASM2BELLS!") + + @CommandAttribute( + "write", + help="???.", + description="???." + ) + def HandleWrite(self, args): + print("WRITE!") + + # FIXME This is a subcommand of 'write' + @CommandAttribute( + "fasm", + help="???.", + description="???." + ) + def HandleWriteFASM(self, args): + print("WRITE FASM!") + + # FIXME This is a subcommand of 'write' + @CommandAttribute( + "bitstream", + help="???.", + description="???." + ) + def HandleWriteBitstream(self, args): + print("WRITE BITSTREAM!") + + # FIXME This is a subcommand of 'write' + @CommandAttribute( + "bitheader", + help="???.", + description="???." + ) + def HandleWriteBitheader(self, args): + print("WRITE BITHEADER!") + +# # FIXME This is a subcommand of 'write' +# @CommandAttribute( +# "fasm2bels", +# help="???.", +# description="???." +# ) +# def HandleWriteFASM2Bells(self, args): +# print("WRITE FASM2BELLS!") + + # FIXME This is a subcommand of 'write' + @CommandAttribute( + "jlink", + help="???.", + description="???." + ) + def HandleWriteJlink(self, args): + print("WRITE JLINK!") + + # FIXME This is a subcommand of 'write' + @CommandAttribute( + "openocd", + help="???.", + description="???." + ) + def HandleWriteOpenOCD(self, args): + print("WRITE OPENOCD!") + + @CommandAttribute( + "vpr", + help="???.", + description="???." + ) + def HandleVPR(self, args): + print("VPR!") + + @CommandAttribute( + "ql", + help="???.", + description="???." + ) + def HandleQL(self, args): + print("QL!") + + +def main(): + CLI().Run() + + +if __name__ == "__main__": + main() diff --git a/f4pga/requirements.txt b/f4pga/requirements.txt index cdb1c2f53..1709cde01 100644 --- a/f4pga/requirements.txt +++ b/f4pga/requirements.txt @@ -1 +1,2 @@ -r ./flows/requirements.txt +pyAttributes