diff options
Diffstat (limited to 'host/utils')
18 files changed, 1069 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() diff --git a/host/utils/rfnoc_blocktool/templates/Makefile b/host/utils/rfnoc_blocktool/templates/Makefile new file mode 100644 index 000000000..25e61c05b --- /dev/null +++ b/host/utils/rfnoc_blocktool/templates/Makefile @@ -0,0 +1,48 @@ +# +# Copyright 2019 Ettus Research, A National Instruments Company +# +# SPDX-License-Identifier: LGPL-3.0-or-later +# + +#------------------------------------------------- +# Top-of-Makefile +#------------------------------------------------- +# Define BASE_DIR to point to the "top" dir +BASE_DIR = $(abspath ../../../../top) +# Include viv_sim_preample after defining BASE_DIR +include $(BASE_DIR)/../tools/make/viv_sim_preamble.mak + +#------------------------------------------------- +# Design Specific +#------------------------------------------------- +# Include makefiles and sources for the DUT and its dependencies +include $(BASE_DIR)/../lib/erfnoc/core/Makefile.srcs +include $(BASE_DIR)/../lib/erfnoc/utils/Makefile.srcs +include Makefile.srcs + +DESIGN_SRCS += $(abspath ${"\\"} +$(RFNOC_CORE_SRCS) ${"\\"} +$(RFNOC_UTIL_SRCS) ${"\\"} +$(RFNOC_BLOCK_${config.module_name.upper()}_SRCS) ${"\\"} +) + +#------------------------------------------------- +# Testbench Specific +#------------------------------------------------- +include $(BASE_DIR)/../sim/erfnoc/Makefile.srcs + +SIM_TOP = rfnoc_block_${config.module_name}_tb + +SIM_SRCS = ${"\\"} +$(abspath rfnoc_block_${config.module_name}_tb.sv) ${"\\"} +$(SIM_ERFNOC_SRCS) + +# MODELSIM_USER_DO = $(abspath wave.do) + +#------------------------------------------------- +# Bottom-of-Makefile +#------------------------------------------------- +# Include all simulator specific makefiles here +# Each should define a unique target to simulate +# e.g. xsim, vsim, etc and a common "clean" target +include $(BASE_DIR)/../tools/make/viv_simulator.mak diff --git a/host/utils/rfnoc_blocktool/templates/Makefile.srcs b/host/utils/rfnoc_blocktool/templates/Makefile.srcs new file mode 100644 index 000000000..f346007af --- /dev/null +++ b/host/utils/rfnoc_blocktool/templates/Makefile.srcs @@ -0,0 +1,13 @@ +# +# Copyright 2018 Ettus Research, A National Instruments Company +# +# SPDX-License-Identifier: LGPL-3.0-or-later +# + +${'##################################################'} +# RFNoC Utility Sources +${'##################################################'} +RFNOC_BLOCK_${config.module_name.upper()}_SRCS = $(abspath $(addprefix $(BASE_DIR)/../lib/erfnoc/blocks/${destination}/, ${"\\"} +rfnoc_block_${config.module_name}.v ${"\\"} +noc_shell_${config.module_name}.v ${"\\"} +)) diff --git a/host/utils/rfnoc_blocktool/templates/modules/axis_chdr_connect_template.mako b/host/utils/rfnoc_blocktool/templates/modules/axis_chdr_connect_template.mako new file mode 100644 index 000000000..ff619b6d9 --- /dev/null +++ b/host/utils/rfnoc_blocktool/templates/modules/axis_chdr_connect_template.mako @@ -0,0 +1,15 @@ +<%page args="num_inputs, num_outputs"/> + +%for idx, input in enumerate(config['data']['inputs']): + .m_${input}_chdr_tdata(${input}_chdr_tdata), + .m_${input}_chdr_tlast(${input}_chdr_tlast), + .m_${input}_chdr_tvalid(${input}_chdr_tvalid), + .m_${input}_chdr_tready(${input}_chdr_tready)${"," if (idx < num_inputs -1) or (num_outputs > 0) else ""} +%endfor + +%for idx, output in enumerate(config['data']['outputs']): + .s_${output}_chdr_tdata(${output}_chdr_tdata), + .s_${output}_chdr_tlast(${output}_chdr_tlast), + .s_${output}_chdr_tvalid(${output}_chdr_tvalid), + .s_${output}_chdr_tready(${output}_chdr_tready)${"," if (idx < num_outputs -1) else ""} +%endfor diff --git a/host/utils/rfnoc_blocktool/templates/modules/axis_chdr_modules_template.mako b/host/utils/rfnoc_blocktool/templates/modules/axis_chdr_modules_template.mako new file mode 100644 index 000000000..bcb23dff6 --- /dev/null +++ b/host/utils/rfnoc_blocktool/templates/modules/axis_chdr_modules_template.mako @@ -0,0 +1,41 @@ +%for idx, input in enumerate(config['data']['inputs']): + chdr_to_chdr_data #( + .CHDR_W(CHDR_W) + ) chdr_to_chdr_data_i${idx} ( + .axis_chdr_clk(rfnoc_chdr_clk), + .axis_chdr_rst(rfnoc_chdr_rst), + .s_axis_chdr_tdata(s_rfnoc_chdr_tdata[(${idx}*CHDR_W)+:CHDR_W]), + .s_axis_chdr_tlast(s_rfnoc_chdr_tlast[${idx}]), + .s_axis_chdr_tvalid(s_rfnoc_chdr_tvalid[${idx}]), + .s_axis_chdr_tready(s_rfnoc_chdr_tready[${idx}]), + .m_axis_chdr_tdata(m_${input}_chdr_tdata), + .m_axis_chdr_tlast(m_${input}_chdr_tlast), + .m_axis_chdr_tvalid(m_${input}_chdr_tvalid), + .m_axis_chdr_tready(m_${input}_chdr_tready), + .flush_en(data_i_flush_en), + .flush_timeout(data_i_flush_timeout), + .flush_active(data_i_flush_active[${idx}]), + .flush_done(data_i_flush_done[${idx}]) + ); +%endfor + +%for idx, output in enumerate(config['data']['outputs']): + chdr_to_chdr_data #( + .CHDR_W(CHDR_W) + ) chdr_to_chdr_data_o${idx} ( + .axis_chdr_clk(rfnoc_chdr_clk), + .axis_chdr_rst(rfnoc_chdr_rst), + .m_axis_chdr_tdata(m_rfnoc_chdr_tdata[(${idx}*CHDR_W)+:CHDR_W]), + .m_axis_chdr_tlast(m_rfnoc_chdr_tlast[${idx}]), + .m_axis_chdr_tvalid(m_rfnoc_chdr_tvalid[${idx}]), + .m_axis_chdr_tready(m_rfnoc_chdr_tready[${idx}]), + .s_axis_chdr_tdata(s_${output}_chdr_tdata), + .s_axis_chdr_tlast(s_${output}_chdr_tlast), + .s_axis_chdr_tvalid(s_${output}_chdr_tvalid), + .s_axis_chdr_tready(s_${output}_chdr_tready), + .flush_en(data_o_flush_en), + .flush_timeout(data_o_flush_timeout), + .flush_active(data_o_flush_active[${idx}]), + .flush_done(data_o_flush_done[${idx}]) + ); +%endfor diff --git a/host/utils/rfnoc_blocktool/templates/modules/axis_chdr_wires_template.mako b/host/utils/rfnoc_blocktool/templates/modules/axis_chdr_wires_template.mako new file mode 100644 index 000000000..9453c8fd1 --- /dev/null +++ b/host/utils/rfnoc_blocktool/templates/modules/axis_chdr_wires_template.mako @@ -0,0 +1,30 @@ +<%page args="mode, num_inputs, num_outputs"/>\ + +<% + if mode == "shell": + sl_pre = "s_" + ma_pre = "m_" + in_wire = "input " + out_wire = "output " + term = "," + elif mode == "block": + sl_pre = "" + ma_pre = "" + in_wire = "" + out_wire = "" + term=";" +%>\ +%for idx, port in enumerate(config['data']['inputs']): + // Payload Stream to User Logic: ${port} + ${out_wire}wire [CHDR_W-1:0] ${ma_pre}${port}_chdr_tdata${term} + ${out_wire}wire ${ma_pre}${port}_chdr_tlast${term} + ${out_wire}wire ${ma_pre}${port}_chdr_tvalid${term} + ${in_wire}wire ${ma_pre}${port}_chdr_tready${term if (term == ";") or (idx < num_inputs -1) or (num_outputs > 0) else ""} +%endfor + +%for idx, port in enumerate(config['data']['outputs']): + ${in_wire}wire [CHDR_W-1:0] ${sl_pre}${port}_chdr_tdata${term} + ${in_wire}wire ${sl_pre}${port}_chdr_tlast${term} + ${in_wire}wire ${sl_pre}${port}_chdr_tvalid${term} + ${out_wire}wire ${sl_pre}${port}_chdr_tready${term if (term == ";") or (idx < num_outputs -1) else ""} +%endfor diff --git a/host/utils/rfnoc_blocktool/templates/modules/axis_ctrl_connect_template.mako b/host/utils/rfnoc_blocktool/templates/modules/axis_ctrl_connect_template.mako new file mode 100644 index 000000000..cefc97a22 --- /dev/null +++ b/host/utils/rfnoc_blocktool/templates/modules/axis_ctrl_connect_template.mako @@ -0,0 +1,8 @@ + .m_axis_ctrl_tdata(m_axis_ctrl_tdata), + .m_axis_ctrl_tlast(m_axis_ctrl_tlast), + .m_axis_ctrl_tvalid(m_axis_ctrl_tvalid), + .m_axis_ctrl_tready(m_axis_ctrl_tready), + .s_axis_ctrl_tdata(s_axis_ctrl_tdata), + .s_axis_ctrl_tlast(s_axis_ctrl_tlast), + .s_axis_ctrl_tvalid(s_axis_ctrl_tvalid), + .s_axis_ctrl_tready(s_axis_ctrl_tready), diff --git a/host/utils/rfnoc_blocktool/templates/modules/axis_ctrl_modules_template.mako b/host/utils/rfnoc_blocktool/templates/modules/axis_ctrl_modules_template.mako new file mode 100644 index 000000000..4c349b11b --- /dev/null +++ b/host/utils/rfnoc_blocktool/templates/modules/axis_ctrl_modules_template.mako @@ -0,0 +1,28 @@ +<%! +import math +%> + axis_ctrl_endpoint #( + .SYNC_CLKS(${1 if config['control']['clk_domain'] == "rfnoc_ctrl" else 0}), + .SLAVE_FIFO_SIZE(${math.ceil(math.log2(config['control']['fifo_depth']))}) + ) axis_ctrl_endpoint_i ( + .rfnoc_ctrl_clk(rfnoc_ctrl_clk), + .rfnoc_ctrl_rst(rfnoc_ctrl_rst), + .axis_ctrl_clk(axis_ctrl_clk), + .axis_ctrl_rst(axis_ctrl_rst), + .s_rfnoc_ctrl_tdata(s_rfnoc_ctrl_tdata), + .s_rfnoc_ctrl_tlast(s_rfnoc_ctrl_tlast), + .s_rfnoc_ctrl_tvalid(s_rfnoc_ctrl_tvalid), + .s_rfnoc_ctrl_tready(s_rfnoc_ctrl_tready), + .m_rfnoc_ctrl_tdata(m_rfnoc_ctrl_tdata), + .m_rfnoc_ctrl_tlast(m_rfnoc_ctrl_tlast), + .m_rfnoc_ctrl_tvalid(m_rfnoc_ctrl_tvalid), + .m_rfnoc_ctrl_tready(m_rfnoc_ctrl_tready), + .s_axis_ctrl_tdata(s_axis_ctrl_tdata), + .s_axis_ctrl_tlast(s_axis_ctrl_tlast), + .s_axis_ctrl_tvalid(s_axis_ctrl_tvalid), + .s_axis_ctrl_tready(s_axis_ctrl_tready), + .m_axis_ctrl_tdata(m_axis_ctrl_tdata), + .m_axis_ctrl_tlast(m_axis_ctrl_tlast), + .m_axis_ctrl_tvalid(m_axis_ctrl_tvalid), + .m_axis_ctrl_tready(m_axis_ctrl_tready) + ); diff --git a/host/utils/rfnoc_blocktool/templates/modules/axis_ctrl_wires_template.mako b/host/utils/rfnoc_blocktool/templates/modules/axis_ctrl_wires_template.mako new file mode 100644 index 000000000..dd15bd100 --- /dev/null +++ b/host/utils/rfnoc_blocktool/templates/modules/axis_ctrl_wires_template.mako @@ -0,0 +1,23 @@ +<%page args="mode"/>\ +<% + if mode == "shell": + sl_pre = "s_" + ma_pre = "m_" + in_wire = "input " + out_wire = "output " + term = "," + elif mode == "block": + sl_pre = "s_" + ma_pre = "m_" + in_wire = "" + out_wire = "" + term = ";" +%>\ + ${out_wire}wire [31:0] ${ma_pre}axis_ctrl_tdata${term} + ${out_wire}wire ${ma_pre}axis_ctrl_tlast${term} + ${out_wire}wire ${ma_pre}axis_ctrl_tvalid${term} + ${in_wire}wire ${ma_pre}axis_ctrl_tready${term} + ${in_wire}wire [31:0] ${sl_pre}axis_ctrl_tdata${term} + ${in_wire}wire ${sl_pre}axis_ctrl_tlast${term} + ${in_wire}wire ${sl_pre}axis_ctrl_tvalid${term} + ${out_wire}wire ${sl_pre}axis_ctrl_tready${term} diff --git a/host/utils/rfnoc_blocktool/templates/modules/axis_raw_connect_template.mako b/host/utils/rfnoc_blocktool/templates/modules/axis_raw_connect_template.mako new file mode 100644 index 000000000..c78946289 --- /dev/null +++ b/host/utils/rfnoc_blocktool/templates/modules/axis_raw_connect_template.mako @@ -0,0 +1,31 @@ +<%page args="num_inputs, num_outputs"/>\ +\ +%for idx, input in enumerate(config['data']['inputs']): + // Payload Stream to User Logic: ${input} + .m_${input}_payload_tdata(${input}_payload_tdata), + .m_${input}_payload_tkeep(${input}_payload_tkeep), + .m_${input}_payload_tlast(${input}_payload_tlast), + .m_${input}_payload_tvalid(${input}_payload_tvalid), + .m_${input}_payload_tready(${input}_payload_tready), + // Context Stream to User Logic: ${input} + .m_${input}_context_tdata(${input}_context_tdata), + .m_${input}_context_tuser(${input}_context_tuser), + .m_${input}_context_tlast(${input}_context_tlast), + .m_${input}_context_tvalid(${input}_context_tvalid), + .m_${input}_context_tready(${input}_context_tready)${"," if (idx < num_inputs - 1) or (num_outputs > 0) else ""} +%endfor + +%for idx, output in enumerate(config['data']['outputs']): + // Payload Stream from User Logic: ${output} + .s_${output}_payload_tdata(${output}_payload_tdata), + .s_${output}_payload_tkeep(${output}_payload_tkeep), + .s_${output}_payload_tlast(${output}_payload_tlast), + .s_${output}_payload_tvalid(${output}_payload_tvalid), + .s_${output}_payload_tready(${output}_payload_tready), + // Context Stream from User Logic: ${output} + .s_${output}_context_tdata(${output}_context_tdata), + .s_${output}_context_tuser(${output}_context_tuser), + .s_${output}_context_tlast(${output}_context_tlast), + .s_${output}_context_tvalid(${output}_context_tvalid), + .s_${output}_context_tready(${output}_context_tready)${"," if (idx < num_outputs -1) else ""} +%endfor diff --git a/host/utils/rfnoc_blocktool/templates/modules/axis_raw_modules_template.mako b/host/utils/rfnoc_blocktool/templates/modules/axis_raw_modules_template.mako new file mode 100644 index 000000000..c181eeedd --- /dev/null +++ b/host/utils/rfnoc_blocktool/templates/modules/axis_raw_modules_template.mako @@ -0,0 +1,78 @@ + +%for idx, input in enumerate(config['data']['inputs']): + <% + port_tmp = config['data']['inputs'][input] + %> + chdr_to_axis_raw_data #( + .CHDR_W(CHDR_W), + .ITEM_W(${port_tmp['item_width']}), + .NIPC(${port_tmp['nipc']}), + .SYNC_CLKS(${1 if config['data']['clk_domain'] == "rfnoc_chdr" else 0}), + .CONTEXT_FIFO_SIZE(${port_tmp['context_fifo_depth']}), + .PAYLOAD_FIFO_SIZE(${port_tmp['payload_fifo_depth']}), + .CONTEXT_PREFETCH_EN(1) + ) chdr_to_axis_raw_data_i${idx} ( + .axis_chdr_clk(rfnoc_chdr_clk), + .axis_chdr_rst(rfnoc_chdr_rst), + .axis_data_clk(axis_data_clk), + .axis_data_rst(axis_data_rst), + .s_axis_chdr_tdata(s_rfnoc_chdr_tdata[(${idx}*CHDR_W)+:CHDR_W]), + .s_axis_chdr_tlast(s_rfnoc_chdr_tlast[${idx}]), + .s_axis_chdr_tvalid(s_rfnoc_chdr_tvalid[${idx}]), + .s_axis_chdr_tready(s_rfnoc_chdr_tready[${idx}]), + .m_axis_payload_tdata(m_${input}_payload_tdata), + .m_axis_payload_tkeep(m_${input}_payload_tkeep), + .m_axis_payload_tlast(m_${input}_payload_tlast), + .m_axis_payload_tvalid(m_${input}_payload_tvalid), + .m_axis_payload_tready(m_${input}_payload_tready), + .m_axis_context_tdata(m_${input}_context_tdata), + .m_axis_context_tuser(m_${input}_context_tuser), + .m_axis_context_tlast(m_${input}_context_tlast), + .m_axis_context_tvalid(m_${input}_context_tvalid), + .m_axis_context_tready(m_${input}_context_tready), + .flush_en(data_i_flush_en), + .flush_timeout(data_i_flush_timeout), + .flush_active(data_i_flush_active[${idx}]), + .flush_done(data_i_flush_done[${idx}]) + ); +%endfor + +%for idx, output in enumerate(config['data']['outputs']): + <% + port_tmp = config['data']['outputs'][output] + %> + axis_raw_data_to_chdr #( + .CHDR_W(CHDR_W), + .ITEM_W(${port_tmp['item_width']}), + .NIPC(${port_tmp['nipc']}), + .SYNC_CLKS(${1 if config['data']['clk_domain'] == "rfnoc_chdr" else 0}), + .CONTEXT_FIFO_SIZE(${port_tmp['context_fifo_depth']}), + .PAYLOAD_FIFO_SIZE(${port_tmp['payload_fifo_depth']}), + .CONTEXT_PREFETCH_EN(1), + .MTU(MTU) + ) axis_raw_data_to_chdr_i${idx} ( + .axis_chdr_clk(rfnoc_chdr_clk), + .axis_chdr_rst(rfnoc_chdr_rst), + .axis_data_clk(axis_data_clk), + .axis_data_rst(axis_data_rst), + .m_axis_chdr_tdata(m_rfnoc_chdr_tdata[(${idx}*CHDR_W)+:CHDR_W]), + .m_axis_chdr_tlast(m_rfnoc_chdr_tlast[${idx}]), + .m_axis_chdr_tvalid(m_rfnoc_chdr_tvalid[${idx}]), + .m_axis_chdr_tready(m_rfnoc_chdr_tready[${idx}]), + .s_axis_payload_tdata(s_${output}_payload_tdata), + .s_axis_payload_tkeep(s_${output}_payload_tkeep), + .s_axis_payload_tlast(s_${output}_payload_tlast), + .s_axis_payload_tvalid(s_${output}_payload_tvalid), + .s_axis_payload_tready(s_${output}_payload_tready), + .s_axis_context_tdata(s_${output}_context_tdata), + .s_axis_context_tuser(s_${output}_context_tuser), + .s_axis_context_tlast(s_${output}_context_tlast), + .s_axis_context_tvalid(s_${output}_context_tvalid), + .s_axis_context_tready(s_${output}_context_tready), + .framer_errors(), + .flush_en(data_o_flush_en), + .flush_timeout(data_o_flush_timeout), + .flush_active(data_o_flush_active[${idx}]), + .flush_done(data_o_flush_done[${idx}]) + ); +%endfor diff --git a/host/utils/rfnoc_blocktool/templates/modules/axis_raw_wires_template.mako b/host/utils/rfnoc_blocktool/templates/modules/axis_raw_wires_template.mako new file mode 100644 index 000000000..abb8ef5e0 --- /dev/null +++ b/host/utils/rfnoc_blocktool/templates/modules/axis_raw_wires_template.mako @@ -0,0 +1,50 @@ +<%page args="mode, num_inputs, num_outputs"/>\ +<% + if mode == "shell": + sl_pre = "s_" + ma_pre = "m_" + in_wire = "input " + out_wire = "output " + term = "," + elif mode == "block": + sl_pre = "" + ma_pre = "" + in_wire = "" + out_wire = "" + term = ";" +%>\ +%for idx, port in enumerate(config['data']['inputs']): + <% + port_tmp = config['data']['inputs'][port] + %>\ + // Payload Stream to User Logic: ${port} + ${out_wire}wire [${port_tmp['item_width']*port_tmp['nipc']-1}:0] ${ma_pre}${port}_payload_tdata${term} + ${out_wire}wire [${port_tmp['nipc']-1}:0] ${ma_pre}${port}_payload_tkeep${term} + ${out_wire}wire ${ma_pre}${port}_payload_tlast${term} + ${out_wire}wire ${ma_pre}${port}_payload_tvalid${term} + ${in_wire}wire ${ma_pre}${port}_payload_tready${term} + // Context Stream to User Logic: ${port} + ${out_wire}wire [CHDR_W-1:0] ${ma_pre}${port}_context_tdata${term} + ${out_wire}wire [3:0] ${ma_pre}${port}_context_tuser${term} + ${out_wire}wire ${ma_pre}${port}_context_tlast${term} + ${out_wire}wire ${ma_pre}${port}_context_tvalid${term} + ${in_wire}wire ${ma_pre}${port}_context_tready${term if (term == ";") or (idx < num_inputs - 1) or (num_outputs > 0) else ""} +%endfor + +%for idx, port in enumerate(config['data']['outputs']): + <% + port_tmp = config['data']['outputs'][port] + %>\ + // Payload Stream from User Logic: ${port} + ${in_wire}wire [${port_tmp['item_width'] * port_tmp['nipc'] - 1}:0] ${sl_pre}${port}_payload_tdata${term} + ${in_wire}wire [${port_tmp['nipc'] - 1}:0] ${sl_pre}${port}_payload_tkeep${term} + ${in_wire}wire ${sl_pre}${port}_payload_tlast${term} + ${in_wire}wire ${sl_pre}${port}_payload_tvalid${term} + ${out_wire}wire ${sl_pre}${port}_payload_tready${term} + // Context Stream from User Logic: ${port} + ${in_wire}wire [CHDR_W-1:0] ${sl_pre}${port}_context_tdata${term} + ${in_wire}wire [3:0] ${sl_pre}${port}_context_tuser${term} + ${in_wire}wire ${sl_pre}${port}_context_tlast${term} + ${in_wire}wire ${sl_pre}${port}_context_tvalid${term} + ${out_wire}wire ${sl_pre}${port}_context_tready${term if (term == ";") or (idx < num_outputs -1) else ""} +%endfor diff --git a/host/utils/rfnoc_blocktool/templates/modules/ctrlport_connect_template.mako b/host/utils/rfnoc_blocktool/templates/modules/ctrlport_connect_template.mako new file mode 100644 index 000000000..944f4af16 --- /dev/null +++ b/host/utils/rfnoc_blocktool/templates/modules/ctrlport_connect_template.mako @@ -0,0 +1,41 @@ + // Control Port Master + .m_ctrlport_req_wr(m_ctrlport_req_wr), + .m_ctrlport_req_rd(m_ctrlport_req_rd), + .m_ctrlport_req_addr(m_ctrlport_req_addr), + .m_ctrlport_req_data(m_ctrlport_req_data), +%if config['control']['ctrlport']['byte_mode']: + .m_ctrlport_req_byte_en(m_ctrlport_req_byte_en), +%endif +%if config['control']['ctrlport']['timed']: + .m_ctrlport_req_has_time(m_ctrlport_req_has_time), + .m_ctrlport_req_time(m_ctrlport_req_time), +%endif + .m_ctrlport_resp_ack(m_ctrlport_resp_ack), +%if config['control']['ctrlport']['has_status']: + .m_ctrlport_resp_status(m_ctrlport_resp_status), +%endif + .m_ctrlport_resp_data(m_ctrlport_resp_data), +%if config['control']['interface_direction'] != "slave": + // Control Port Slave + .s_ctrlport_req_wr(s_ctrlport_req_wr), + .s_ctrlport_req_rd(s_ctrlport_req_rd), + .s_ctrlport_req_addr(s_ctrlport_req_addr), + .s_ctrlport_req_portid(s_ctrlport_req_portid), + %if config['control']['interface_direction'] == "remote_master_slave": + .s_ctrlport_req_rem_epid(s_ctrlport_req_rem_epid), + .s_ctrlport_req_rem_portid(s_ctrlport_req_rem_portid), + %endif + .s_ctrlport_req_data(s_ctrlport_req_data), + %if config['control']['ctrlport']['byte_mode']: + .s_ctrlport_req_byte_en(s_ctrlport_req_byte_en), + %endif + %if config['control']['ctrlport']['timed']: + .s_ctrlport_req_has_time(s_ctrlport_req_has_time), + .s_ctrlport_req_time(s_ctrlport_req_time), + %endif + .s_ctrlport_resp_ack(s_ctrlport_resp_ack), + %if config['control']['ctrlport']['has_status']: + .s_ctrlport_resp_status(s_ctrlport_resp_status), + %endif + .s_ctrlport_resp_data(s_ctrlport_resp_data), +%endif diff --git a/host/utils/rfnoc_blocktool/templates/modules/ctrlport_modules_template.mako b/host/utils/rfnoc_blocktool/templates/modules/ctrlport_modules_template.mako new file mode 100644 index 000000000..9aecc2b80 --- /dev/null +++ b/host/utils/rfnoc_blocktool/templates/modules/ctrlport_modules_template.mako @@ -0,0 +1,47 @@ +<%! +import math +%> + ctrlport_endpoint #( + .THIS_PORTID(THIS_PORTID), + .SYNC_CLKS(${1 if config['control']['clk_domain'] == "rfnoc_ctrl" else 0}), + .AXIS_CTRL_MST_EN(${int(config['control']['interface_direction'] != "slave")}), + .AXIS_CTRL_SLV_EN(1), + .SLAVE_FIFO_SIZE(${math.ceil(math.log2(config['control']['fifo_depth']))}) + ) ctrlport_endpoint_i ( + .rfnoc_ctrl_clk(rfnoc_ctrl_clk), + .rfnoc_ctrl_rst(rfnoc_ctrl_rst), + .ctrlport_clk(ctrlport_clk), + .ctrlport_rst(ctrlport_rst), + .s_rfnoc_ctrl_tdata(s_rfnoc_ctrl_tdata), + .s_rfnoc_ctrl_tlast(s_rfnoc_ctrl_tlast), + .s_rfnoc_ctrl_tvalid(s_rfnoc_ctrl_tvalid), + .s_rfnoc_ctrl_tready(s_rfnoc_ctrl_tready), + .m_rfnoc_ctrl_tdata(m_rfnoc_ctrl_tdata), + .m_rfnoc_ctrl_tlast(m_rfnoc_ctrl_tlast), + .m_rfnoc_ctrl_tvalid(m_rfnoc_ctrl_tvalid), + .m_rfnoc_ctrl_tready(m_rfnoc_ctrl_tready), + .m_ctrlport_req_wr(m_ctrlport_req_wr), + .m_ctrlport_req_rd(m_ctrlport_req_rd), + .m_ctrlport_req_addr(m_ctrlport_req_addr), + .m_ctrlport_req_data(m_ctrlport_req_data), + .m_ctrlport_req_byte_en(${"m_ctrlport_req_byte_en" if config['control']['ctrlport']['byte_mode'] else ""}), + .m_ctrlport_req_has_time(${"m_ctrlport_req_has_time" if config['control']['ctrlport']['timed'] else ""}), + .m_ctrlport_req_time(${"m_ctrlport_req_time" if config['control']['ctrlport']['timed'] else ""}), + .m_ctrlport_resp_ack(m_ctrlport_resp_ack), + .m_ctrlport_resp_status(${"m_ctrlport_resp_status" if config['control']['ctrlport']['has_status'] else "'h0"}), + .m_ctrlport_resp_data(m_ctrlport_resp_data), + .s_ctrlport_req_wr(${"s_ctrlport_req_wr" if config['control']['interface_direction'] != "slave" else "'h0"}), + .s_ctrlport_req_rd(${"s_ctrlport_req_rd" if config['control']['interface_direction'] != "slave" else "'h0"}), + .s_ctrlport_req_addr(${"s_ctrlport_req_addr" if config['control']['interface_direction'] != "slave" else "'h0"}), + .s_ctrlport_req_portid(${"s_ctrlport_req_portid" if config['control']['interface_direction'] != "slave" else "'h0"}), + .s_ctrlport_req_rem_epid(${"s_ctrlport_req_rem_epid" if config['control']['interface_direction'] == "remote_master_slave" else "'h0"}), + .s_ctrlport_req_rem_portid(${"s_ctrlport_req_rem_portid" if config['control']['interface_direction'] == "remote_master_slave" else "'h0"}), + .s_ctrlport_req_data(${"s_ctrlport_req_data" if config['control']['interface_direction'] != "slave" else "'h0"}), + .s_ctrlport_req_byte_en(${"s_ctrlport_req_byte_en" if config['control']['interface_direction'] != "slave" else "'h0"}), + .s_ctrlport_req_has_time(${"s_ctrlport_req_has_time" if config['control']['interface_direction'] != "slave" else "'h0"}), + .s_ctrlport_req_time(${"s_ctrlport_req_time" if config['control']['interface_direction'] != "slave" else "'h0"}), + .s_ctrlport_resp_ack(${"s_ctrlport_resp_ack" if config['control']['interface_direction'] != "slave" else ""}), + .s_ctrlport_resp_status(${"s_ctrlport_resp_status" if config['control']['interface_direction'] != "slave" else ""}), + .s_ctrlport_resp_data(${"s_ctrlport_resp_data" if config['control']['interface_direction'] != "slave" else ""}) + ); +
\ No newline at end of file diff --git a/host/utils/rfnoc_blocktool/templates/modules/ctrlport_wires_template.mako b/host/utils/rfnoc_blocktool/templates/modules/ctrlport_wires_template.mako new file mode 100644 index 000000000..6d149ae6b --- /dev/null +++ b/host/utils/rfnoc_blocktool/templates/modules/ctrlport_wires_template.mako @@ -0,0 +1,58 @@ +<%page args="mode"/>\ +\ +<% + if mode == "shell": + sl_pre = "s_" + ma_pre = "m_" + sl_wire = "input " + ma_wire = "output " + term = "," + elif mode == "block": + sl_pre = "s_" + ma_pre = "m_" + sl_wire = "" + ma_wire = "" + term = ";" +%>\ + // Control Port Master + ${ma_wire}wire ${ma_pre}ctrlport_req_wr${term} + ${ma_wire}wire ${ma_pre}ctrlport_req_rd${term} + ${ma_wire}wire [19:0] ${ma_pre}ctrlport_req_addr${term} + ${ma_wire}wire [31:0] ${ma_pre}ctrlport_req_data${term} +%if config['control']['ctrlport']['byte_mode']: + ${ma_wire}wire [3:0] ${ma_pre}ctrlport_req_byte_en${term} +%endif +%if config['control']['ctrlport']['timed']: + ${ma_wire}wire ${ma_pre}ctrlport_req_ha${sl_pre}time${term} + ${ma_wire}wire [63:0] ${ma_pre}ctrlport_req_time${term} +%endif + ${sl_wire}wire ${ma_pre}ctrlport_resp_ack${term} +%if config['control']['ctrlport']['has_status']: + ${sl_wire}wire [1:0] ${ma_pre}ctrlport_resp_status${term} +%endif + ${sl_wire}wire [31:0] ${ma_pre}ctrlport_resp_data${term} + +%if config['control']['interface_direction'] != "slave": + // Control Port Slave + ${sl_wire}wire ${sl_pre}ctrlport_req_wr${term} + ${sl_wire}wire ${sl_pre}ctrlport_req_rd${term} + ${sl_wire}wire [19:0] ${sl_pre}ctrlport_req_addr${term} + ${sl_wire}wire [9:0] ${sl_pre}ctrlport_req_portid${term} + %if config['control']['interface_direction'] == "remote_master_slave": + ${sl_wire}wire [15:0] ${sl_pre}ctrlport_req_rem_epid${term} + ${sl_wire}wire [9:0] ${sl_pre}ctrlport_req_rem_portid${term} + %endif + ${sl_wire}wire [31:0] ${sl_pre}ctrlport_req_data${term} + %if config['control']['ctrlport']['byte_mode']: + ${sl_wire}wire [3:0] ${sl_pre}ctrlport_req_byte_en${term} + %endif + %if config['control']['ctrlport']['timed']: + ${sl_wire}wire ${sl_pre}ctrlport_req_has_time${term} + ${sl_wire}wire [63:0] ${sl_pre}ctrlport_req_time${term} + %endif + ${ma_wire}wire ${sl_pre}ctrlport_resp_ack${term} + %if config['control']['ctrlport']['has_status']: + ${ma_wire}wire [1:0] ${sl_pre}ctrlport_resp_status${term} + %endif + ${ma_wire}wire [31:0] ${sl_pre}ctrlport_resp_data${term} +%endif diff --git a/host/utils/rfnoc_blocktool/templates/noc_shell_template.v.mako b/host/utils/rfnoc_blocktool/templates/noc_shell_template.v.mako new file mode 100644 index 000000000..7fb1b17d5 --- /dev/null +++ b/host/utils/rfnoc_blocktool/templates/noc_shell_template.v.mako @@ -0,0 +1,147 @@ +<%! +import math +%> +// +// Copyright 2019 Ettus Research, A National Instruments Brand +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// +// Module: noc_shell_${config['module_name']} +// Description: +// +// Parameters: +// +// Signals: + +module noc_shell_${config['module_name']} #( + parameter CHDR_W = 64, + parameter [9:0] THIS_PORTID = 10'd0, + parameter [5:0] MTU = 0 +)( + // Framework Interface + //------------------------------------------------------------ + // RFNoC Framework Clocks and Resets +%for clock in config['clocks']: + input wire ${clock['name']}_clk, + ${"output" if clock['name'] in ["rfnoc_chdr", "rfnoc_ctrl"] else "input"} wire ${clock['name']}_rst, +% endfor + + // RFNoC Backend Interface + input wire [511:0] rfnoc_core_config, + output wire [511:0] rfnoc_core_status, + <% + num_inputs = len(config['data']['inputs']) + num_outputs = len(config['data']['outputs']) + %> + // CHDR Input Ports (from framework) + input wire [(${num_inputs}*CHDR_W)-1:0] s_rfnoc_chdr_tdata, + input wire [${num_inputs-1}:0] s_rfnoc_chdr_tlast, + input wire [${num_inputs-1}:0] s_rfnoc_chdr_tvalid, + output wire [${num_inputs-1}:0] s_rfnoc_chdr_tready, + + // CHDR Output Ports (to framework) + output wire [(${num_outputs}*CHDR_W)-1:0] m_rfnoc_chdr_tdata, + output wire [${num_outputs-1}:0] m_rfnoc_chdr_tlast, + output wire [${num_outputs-1}:0] m_rfnoc_chdr_tvalid, + input wire [${num_outputs-1}:0] m_rfnoc_chdr_tready, + // AXIS-Ctrl Input Port (from framework) + input wire [31:0] s_rfnoc_ctrl_tdata, + input wire s_rfnoc_ctrl_tlast, + input wire s_rfnoc_ctrl_tvalid, + output wire s_rfnoc_ctrl_tready, + // AXIS-Ctrl Output Port (to framework) + output wire [31:0] m_rfnoc_ctrl_tdata, + output wire m_rfnoc_ctrl_tlast, + output wire m_rfnoc_ctrl_tvalid, + input wire m_rfnoc_ctrl_tready, + + // Client Interface + //------------------------------------------------------------ + output wire ctrlport_clk, + output wire ctrlport_rst, + +%if config['control']['fpga_iface'] == "ctrlport": +<%include file="modules/ctrlport_wires_template.mako" args="mode='shell'"/> +%elif config['control']['fpga_iface'] == "axis_ctrl": +<%include file="modules/axis_ctrl_wires_template.mako" args="mode='shell'"/> +%else: +<%include file="control wires template.mako"/> +%endif + + output wire axis_data_clk, + output wire axis_data_rst, + +%if config['data']['fpga_iface'] == "axis_chdr": + <%include file="modules/axis_chdr_wires_template.mako" args="mode='shell', num_inputs=num_inputs, num_outputs=num_outputs"/> +%elif config['data']['fpga_iface'] == "axis_rawdata": + <%include file="modules/axis_raw_wires_template.mako" args="mode='shell', num_inputs=num_inputs, num_outputs=num_outputs"/> +%else: + <%include file="data wires template.mako"/> +%endif +); + + // --------------------------------------------------- + // Backend Interface + // --------------------------------------------------- + wire data_i_flush_en; + wire [31:0] data_i_flush_timeout; + wire [63:0] data_i_flush_active; + wire [63:0] data_i_flush_done; + wire data_o_flush_en; + wire [31:0] data_o_flush_timeout; + wire [63:0] data_o_flush_active; + wire [63:0] data_o_flush_done; + + + backend_iface #( + .NOC_ID(32'h${format(config['noc_id'], "08X")}), + .NUM_DATA_I(${num_inputs}), + .NUM_DATA_O(${num_outputs}), + .CTRL_FIFOSIZE(${math.ceil(math.log2(config['control']['fifo_depth']))}), + .MTU(MTU) + ) backend_iface_i ( + .rfnoc_chdr_clk(rfnoc_chdr_clk), + .rfnoc_chdr_rst(rfnoc_chdr_rst), + .rfnoc_ctrl_clk(rfnoc_ctrl_clk), + .rfnoc_ctrl_rst(rfnoc_ctrl_rst), + .rfnoc_core_config(rfnoc_core_config), + .rfnoc_core_status(rfnoc_core_status), + .data_i_flush_en(data_i_flush_en), + .data_i_flush_timeout(data_i_flush_timeout), + .data_i_flush_active(data_i_flush_active), + .data_i_flush_done(data_i_flush_done), + .data_o_flush_en(data_o_flush_en), + .data_o_flush_timeout(data_o_flush_timeout), + .data_o_flush_active(data_o_flush_active), + .data_o_flush_done(data_o_flush_done) + ); + + // --------------------------------------------------- + // Control Path + // --------------------------------------------------- + + assign ctrlport_clk = ${config['control']['clk_domain']}_clk; + assign ctrlport_rst = ${config['control']['clk_domain']}_rst; + +%if config['control']['fpga_iface'] == "axis_ctrl": +<%include file="modules/axis_ctrl_modules_template.mako"/> +%elif config['control']['fpga_iface'] == "ctrlport": +<%include file="modules/ctrlport_modules_template.mako"/> +%else: +<%include file="control module template.mako"/> +%endif + + // --------------------------------------------------- + // Data Path + // --------------------------------------------------- + assign axis_data_clk = ${config['data']['clk_domain']}_clk; + assign axis_data_rst = ${config['data']['clk_domain']}_rst; +%if config['data']['fpga_iface'] == "axis_rawdata": +<%include file="modules/axis_raw_modules_template.mako"/> +%elif config['data']['fpga_iface'] == "axis_chdr": +<%include file="modules/axis_chdr_modules_template.mako"/> +%else: +<%include file="data module template.mako"/> +%endif + +endmodule // noc_shell_${config['module_name']} diff --git a/host/utils/rfnoc_blocktool/templates/rfnoc_block_template.v.mako b/host/utils/rfnoc_blocktool/templates/rfnoc_block_template.v.mako new file mode 100644 index 000000000..a2e03ea92 --- /dev/null +++ b/host/utils/rfnoc_blocktool/templates/rfnoc_block_template.v.mako @@ -0,0 +1,151 @@ +<%! +import math +%> +// +// Copyright 2019 Ettus Research, A National Instruments Brand +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// +// Module: rfnoc_block_${config['module_name']} +// Description: +// +// Parameters: +// +// Signals: + +<% +num_inputs = len(config['data']['inputs']) +num_outputs = len(config['data']['outputs']) +%> + +module rfnoc_block_${config['module_name']} #( + parameter [9:0] THIS_PORTID = 10'd0, + parameter CHDR_W = 64, + parameter [5:0] MTU = ${math.ceil(math.log2(config['data']['mtu']))} +)( + // RFNoC Framework Clocks and Resets +%for clock in config['clocks']: + input wire ${clock['name']}_clk, + %if not clock['name'] in ["rfnoc_chdr", "rfnoc_ctrl"]: + input wire ${clock['name']}_rst, + %endif +%endfor + // RFNoC Backend Interface + input wire [511:0] rfnoc_core_config, + output wire [511:0] rfnoc_core_status, + // 2 CHDR Input Ports (from framework) + input wire [(CHDR_W*${num_inputs})-1:0] s_rfnoc_chdr_tdata, + input wire [1:0] s_rfnoc_chdr_tlast, + input wire [1:0] s_rfnoc_chdr_tvalid, + output wire [1:0] s_rfnoc_chdr_tready, + // 2 CHDR Output Ports (to framework) + output wire [(CHDR_W*${num_outputs})-1:0] m_rfnoc_chdr_tdata, + output wire [1:0] m_rfnoc_chdr_tlast, + output wire [1:0] m_rfnoc_chdr_tvalid, + input wire [1:0] m_rfnoc_chdr_tready, + // AXIS-Ctrl Input Port (from framework) + input wire [31:0] s_rfnoc_ctrl_tdata, + input wire s_rfnoc_ctrl_tlast, + input wire s_rfnoc_ctrl_tvalid, + output wire s_rfnoc_ctrl_tready, + // AXIS-Ctrl Output Port (to framework) + output wire [31:0] m_rfnoc_ctrl_tdata, + output wire m_rfnoc_ctrl_tlast, + output wire m_rfnoc_ctrl_tvalid, + input wire m_rfnoc_ctrl_tready +); + +%for clock in config['clocks']: + %if clock['name'] in ["rfnoc_chdr", "rfnoc_ctrl"]: + wire ${clock['name']}_rst; + %endif +%endfor + + wire ctrlport_clk; + wire ctrlport_rst; + + wire axis_data_clk; + wire axis_data_rst; + +%if config['control']['fpga_iface'] == "ctrlport": +<%include file="modules/ctrlport_wires_template.mako" args="mode='block'"/> +%elif config['control']['fpga_iface'] == "axis_ctrl": +<%include file="modules/axis_ctrl_wires_template.mako" args="mode='block'"/> +%else: +<%include file="control wires template.mako"/> +%endif + +%if config['data']['fpga_iface'] == "axis_chdr": +<%include file="modules/axis_chdr_wires_template.mako" args="mode='block', num_inputs=num_inputs, num_outputs=num_outputs"/> +%elif config['data']['fpga_iface'] == "axis_rawdata": +<%include file="modules/axis_raw_wires_template.mako" args="mode='block', num_inputs=num_inputs, num_outputs=num_outputs"/> +%else: +<%include file="data wires template.mako"/> +%endif + +//NoC Shell +noc_shell_${config['module_name']} #( + .CHDR_W (CHDR_W), + .THIS_PORTID (THIS_PORTID), + .MTU (MTU) +) noc_shell ( +%for clock in config['clocks']: + .${clock['name']}_clk(${clock['name']}_clk), + .${clock['name']}_rst(${clock['name']}_rst), +%endfor + + // RFNoC Backend Interface + .rfnoc_core_config(rfnoc_core_config), + .rfnoc_core_status(rfnoc_core_status), + + // CHDR Input Ports (from framework) + .s_rfnoc_chdr_tdata(s_rfnoc_chdr_tdata), + .s_rfnoc_chdr_tlast(s_rfnoc_chdr_tlast), + .s_rfnoc_chdr_tvalid(s_rfnoc_chdr_tvalid), + .s_rfnoc_chdr_tready(s_rfnoc_chdr_tready), + + // CHDR Output Ports (to framework) + .m_rfnoc_chdr_tdata(m_rfnoc_chdr_tdata), + .m_rfnoc_chdr_tlast(m_rfnoc_chdr_tlast), + .m_rfnoc_chdr_tvalid(m_rfnoc_chdr_tvalid), + .m_rfnoc_chdr_tready(m_rfnoc_chdr_tready), + // AXIS-Ctrl Input Port (from framework) + .s_rfnoc_ctrl_tdata(s_rfnoc_ctrl_tdata), + .s_rfnoc_ctrl_tlast(s_rfnoc_ctrl_tlast), + .s_rfnoc_ctrl_tvalid(s_rfnoc_ctrl_tvalid), + .s_rfnoc_ctrl_tready(s_rfnoc_ctrl_tready), + // AXIS-Ctrl Output Port (to framework) + .m_rfnoc_ctrl_tdata(m_rfnoc_ctrl_tdata), + .m_rfnoc_ctrl_tlast(m_rfnoc_ctrl_tlast), + .m_rfnoc_ctrl_tvalid(m_rfnoc_ctrl_tvalid), + .m_rfnoc_ctrl_tready(m_rfnoc_ctrl_tready), + + // Client Interface + //------------------------------------------------------------ + .ctrlport_clk(ctrlport_clk), + .ctrlport_rst(ctrlport_rst), + +%if config['control']['fpga_iface'] == "ctrlport": +<%include file="modules/ctrlport_connect_template.mako"/>\ +%elif config['control']['fpga_iface'] == "axis_ctrl": +<%include file="modules/axis_ctrl_connect_template.mako"/>\ +%else: +<%include file="control connect template.mako"/>\ +%endif + + .axis_data_clk(axis_data_clk), + .axis_data_rst(axis_data_rst), + +%if config['data']['fpga_iface'] == "axis_chdr": +<%include file="modules/axis_chdr_connect_template.mako" args="num_inputs=num_inputs, num_outputs=num_outputs"/>\ +%elif config['data']['fpga_iface'] == "axis_rawdata": +<%include file="modules/axis_raw_connect_template.mako" args="num_inputs=num_inputs, num_outputs=num_outputs"/>\ +%else: +<%include file="data connect template.mako"/>\ +%endif +); + + +//user code goes here + +endmodule // rfnoc_block_${config['module_name']} diff --git a/host/utils/rfnoc_blocktool/templates/rfnoc_block_template_tb.sv.mako b/host/utils/rfnoc_blocktool/templates/rfnoc_block_template_tb.sv.mako new file mode 100644 index 000000000..0bf4641b0 --- /dev/null +++ b/host/utils/rfnoc_blocktool/templates/rfnoc_block_template_tb.sv.mako @@ -0,0 +1,129 @@ +// +// Copyright 2019 Ettus Research, A National Instruments Company +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// +// Module: rfnoc_block_${config['module_name']}_tb +// + +`default_nettype none + + +module rfnoc_block_${config['module_name']}_tb; + + // Simulation Timing + timeunit 1ns; + timeprecision 1ps; + + import PkgTestExec::*; + import PkgChdrUtils::*; + import PkgRfnocBlockCtrlBfm::*; + import PkgRfnocItemUtils::*; + + // Parameters + localparam [9:0] THIS_PORTID = 10'h17; + localparam [15:0] THIS_EPID = 16'hDEAD; + localparam int CHDR_W = 64; + localparam int SPP = 201; + localparam int LPP = ((SPP+1)/2); + localparam int NUM_PKTS = 50; + + localparam int PORT_SRCSNK = 0; + localparam int PORT_LOOP = 1; + + //adjust clocks to testbench needs + localparam int CHDR_CLK_PER = 5; // 200 MHz +%for clock in config['clocks']: + %if clock['name'] not in ["rfnoc_chdr", "rfnoc_ctrl"]: + localparam int ${clock['name'].upper()}_CLK_PER = 5; // 200 MHz + %endif +%endfor + + // Clock and Reset Definition + bit rfnoc_chdr_clk; +%for clock in config['clocks']: + %if clock['name'] not in ["rfnoc_chdr", "rfnoc_ctrl"]: + bit ${clock['name']}_clk; + %endif +%endfor + + sim_clock_gen #(CHDR_CLK_PER) rfnoc_chdr_clk_gen (.clk(rfnoc_chdr_clk), .rst()); +%for clock in config['clocks']: + %if clock['name'] not in ["rfnoc_chdr", "rfnoc_ctrl"]: + sim_clock_gen #(${clock['name'].upper()}_CLK_PER) ${clock['name']}_clk_gen (.clk(${clock['name']}_clk), .rst()); + %endif +%endfor + + // ---------------------------------------- + // Instantiate DUT + // ---------------------------------------- + + // Connections to DUT as interfaces: + RfnocBackendIf backend (rfnoc_chdr_clk, rfnoc_chdr_clk); // Required backend iface + AxiStreamIf #(32) m_ctrl (rfnoc_chdr_clk); // Required control iface + AxiStreamIf #(32) s_ctrl (rfnoc_chdr_clk); // Required control iface + AxiStreamIf #(CHDR_W) m0_chdr (rfnoc_chdr_clk); // Optional data iface + AxiStreamIf #(CHDR_W) m1_chdr (rfnoc_chdr_clk); // Optional data iface + AxiStreamIf #(CHDR_W) s0_chdr (rfnoc_chdr_clk); // Optional data iface + AxiStreamIf #(CHDR_W) s1_chdr (rfnoc_chdr_clk); // Optional data iface + + // Bus functional model for a software block controller + RfnocBlockCtrlBfm #(.CHDR_W(CHDR_W)) blk_ctrl; + + // DUT + rfnoc_block_${config['module_name']} #( + .THIS_PORTID (THIS_PORTID), + .CHDR_W (CHDR_W), + .MTU (10) + ) dut ( + .rfnoc_chdr_clk (backend.chdr_clk), + .rfnoc_ctrl_clk (backend.ctrl_clk), +%for clock in config['clocks']: + %if clock['name'] not in ["rfnoc_chdr", "rfnoc_ctrl"]: + .${clock['name']}_clk(${clock['name']}_clk_gen.clk), + .${clock['name']}_rst(${clock['name']}_clk_gen.rst), + %endif +%endfor + .rfnoc_core_config (backend.cfg), + .rfnoc_core_status (backend.sts), + .s_rfnoc_chdr_tdata ({m1_chdr.tdata , m0_chdr.tdata }), + .s_rfnoc_chdr_tlast ({m1_chdr.tlast , m0_chdr.tlast }), + .s_rfnoc_chdr_tvalid({m1_chdr.tvalid , m0_chdr.tvalid }), + .s_rfnoc_chdr_tready({m1_chdr.tready , m0_chdr.tready }), + .m_rfnoc_chdr_tdata ({s1_chdr.tdata , s0_chdr.tdata }), + .m_rfnoc_chdr_tlast ({s1_chdr.tlast , s0_chdr.tlast }), + .m_rfnoc_chdr_tvalid({s1_chdr.tvalid, s0_chdr.tvalid}), + .m_rfnoc_chdr_tready({s1_chdr.tready, s0_chdr.tready}), + .s_rfnoc_ctrl_tdata (m_ctrl.tdata ), + .s_rfnoc_ctrl_tlast (m_ctrl.tlast ), + .s_rfnoc_ctrl_tvalid(m_ctrl.tvalid ), + .s_rfnoc_ctrl_tready(m_ctrl.tready ), + .m_rfnoc_ctrl_tdata (s_ctrl.tdata ), + .m_rfnoc_ctrl_tlast (s_ctrl.tlast ), + .m_rfnoc_ctrl_tvalid(s_ctrl.tvalid), + .m_rfnoc_ctrl_tready(s_ctrl.tready) + ); + + // ---------------------------------------- + // Test Process + // ---------------------------------------- + TestExec test; + initial begin + // Shared Variables + // ---------------------------------------- + timeout_t timeout; + ctrl_word_t rvalue; + rvalue = 0; + + // Initialize + // ---------------------------------------- + test = new("noc_block_${config['module_name']}_tb.v"); + test.start_tb(); + + // Finish Up + // ---------------------------------------- + // Display final statistics and results + test.end_tb(); + end + +endmodule |