aboutsummaryrefslogtreecommitdiffstats
path: root/host/utils/rfnoc_blocktool/rfnoc_create_verilog.py
diff options
context:
space:
mode:
Diffstat (limited to 'host/utils/rfnoc_blocktool/rfnoc_create_verilog.py')
-rw-r--r--host/utils/rfnoc_blocktool/rfnoc_create_verilog.py131
1 files changed, 131 insertions, 0 deletions
diff --git a/host/utils/rfnoc_blocktool/rfnoc_create_verilog.py b/host/utils/rfnoc_blocktool/rfnoc_create_verilog.py
new file mode 100644
index 000000000..7b4f6cdeb
--- /dev/null
+++ b/host/utils/rfnoc_blocktool/rfnoc_create_verilog.py
@@ -0,0 +1,131 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Copyright 2013-2015 Ettus Research LLC
+# Copyright 2018 Ettus Research, a National Instruments Brand
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+#
+"""
+Create a task for each file to generate from templates. A task is based on
+a named tuple to ease future extensions.
+Each task generates on result file by utilizing the BlockGenerator class.
+"""
+
+import argparse
+import datetime
+import os
+import re
+import sys
+from collections import namedtuple
+import six
+import mako.template
+import mako.lookup
+from mako import exceptions
+from ruamel import yaml
+
+
+class BlockGenerator:
+ """
+ Generates a new file from a template utilizing a YAML configuration passed
+ as argument.
+
+ Each BlockGenerator generate one file out of one template.
+ All substitution parameter used in the template must be given in the YAML
+ configuration. Exceptions: year (generated on the fly) and destination
+ (given as argument). The root object parsed from the YAML configuration is
+ config. All configuration items are represented as object members of config
+ (YAML dictionaries are resolved recursively).
+ """
+
+ def __init__(self, template_file):
+ """
+ Initializes a new generator based on template_file
+ :param template_file: file used as root template during rendering,
+ template file is assumed to be located in folder
+ 'modules' relative to this Python file.
+ """
+ self.template_file = template_file
+ self.year = datetime.datetime.now().year
+ self.parser = None
+ self.config = None
+ self.destination = None
+
+ def setup_parser(self):
+ """
+ Setup argument parser.
+
+ ArgumentParser is able to receive destination path and a file location
+ of the YAML configuration.
+ """
+ self.parser = argparse.ArgumentParser(
+ description="Generate RFNoC module out of yml description")
+ self.parser.add_argument("-c", "--config", required=True,
+ help="Path to yml configuration file")
+ self.parser.add_argument("-d", "--destination", required=True,
+ help="Destination path to write output files")
+
+ def setup(self):
+ """
+ Prepare generator for template substitution.
+
+ Results of setup are save in member variables and are accessible for
+ further template processing.
+ self.year current year (for copyright headers)
+ self.destination root path where template generation results are placed
+ self.config everything that was passed as YAML format
+ configuration
+ """
+ args = self.parser.parse_args()
+ self.year = datetime.datetime.now().year
+ self.destination = args.destination
+ os.makedirs(self.destination, exist_ok=True)
+ with open(args.config) as stream:
+ self.config = yaml.safe_load(stream)
+
+ def run(self):
+ """
+ Do template substitution for destination template using YAML
+ configuration passed by arguments.
+
+ Template substitution is done in memory. The result is written to a file
+ where the destination folder is given by the argument parser and the
+ final filename is derived from the template file by substitute template
+ by the module name from the YAML configuration.
+ """
+ lookup = mako.lookup.TemplateLookup(directories=['.'])
+ filename = os.path.join("templates", self.template_file)
+ tpl = mako.template.Template(filename=filename, lookup=lookup,
+ strict_undefined=True)
+ # Render and return
+ try:
+ block = tpl.render(**{"config": self.config,
+ "year": self.year,
+ "destination": self.destination,})
+ except:
+ print(exceptions.text_error_template().render())
+ sys.exit(1)
+
+ filename = self.template_file
+ # pylint: disable=no-member
+ filename = re.sub(r"template(.*)\.mako",
+ r"%s\1" % self.config['module_name'],
+ filename)
+ fullpath = os.path.join(self.destination, filename)
+
+ with open(fullpath, "w") as stream:
+ stream.write(block)
+
+
+if __name__ == "__main__":
+ Task = namedtuple("Task", "name")
+ TASKS = [Task(name="noc_shell_template.v.mako"),
+ Task(name="rfnoc_block_template.v.mako"),
+ Task(name="rfnoc_block_template_tb.sv.mako"),
+ Task(name="Makefile"),
+ Task(name="Makefile.srcs")]
+ for task in TASKS:
+ generator = BlockGenerator(task.name)
+ generator.setup_parser()
+ generator.setup()
+ generator.run()