aboutsummaryrefslogtreecommitdiffstats
path: root/host/utils/rfnoc
diff options
context:
space:
mode:
authorWade Fife <wade.fife@ettus.com>2019-10-23 19:50:34 -0500
committerMartin Braun <martin.braun@ettus.com>2019-11-26 12:21:32 -0800
commit4e6177ed5564180fe7a0da705490087e736371b6 (patch)
tree34896baea16d0e7cf6d5101ac91a2e28fdb5b0d4 /host/utils/rfnoc
parentea89fd0dd4e7bd9a4050f6ae2b79d3b359c60a9a (diff)
downloaduhd-4e6177ed5564180fe7a0da705490087e736371b6.tar.gz
uhd-4e6177ed5564180fe7a0da705490087e736371b6.tar.bz2
uhd-4e6177ed5564180fe7a0da705490087e736371b6.zip
utils: image_builder: Support parameterized number of ports on blocks
Diffstat (limited to 'host/utils/rfnoc')
-rwxr-xr-xhost/utils/rfnoc/image_builder.py64
-rw-r--r--host/utils/rfnoc/templates/modules/drive_unused_ports.v.mako38
-rw-r--r--host/utils/rfnoc/templates/modules/rfnoc_block.v.mako17
-rw-r--r--host/utils/rfnoc/templates/rfnoc_image_core.v.mako4
4 files changed, 76 insertions, 47 deletions
diff --git a/host/utils/rfnoc/image_builder.py b/host/utils/rfnoc/image_builder.py
index 965b2d454..19740c211 100755
--- a/host/utils/rfnoc/image_builder.py
+++ b/host/utils/rfnoc/image_builder.py
@@ -18,6 +18,7 @@ import sys
import six
import mako.lookup
import mako.template
+from mako import exceptions
from ruamel import yaml
# Adapted from code found at
@@ -100,7 +101,7 @@ class IOConfig:
Class containing configuration from a yml file.
Each top level entry is translated into a class member variable. If the
- configuration contains an io_ports section the ports get an wire list which
+ configuration contains an io_ports section the ports get a wire list which
is derived from the signature file. This allows easier processing of IO
ports in the mako templates and failures from yml configuration files fail
in this script rather than during template processing which is easier to
@@ -173,16 +174,12 @@ class ImageBuilderConfig:
def _collect_noc_ports(self):
"""
Create lookup table for noc blocks. The key is a tuple of block
- name, port name and flow direction.
+ name, port name and flow direction. If any block port has num_ports > 1
+ then unroll that port into multiple ports of the same name plus a
+ number to make its name unique.
"""
for name, block in six.iteritems(self.noc_blocks):
desc = self.blocks[block["block_desc"]]
- ports = desc.data["inputs"]
- self.block_ports.update({(name, port, "input"):
- ports[port] for port in ports})
- ports = desc.data["outputs"]
- self.block_ports.update({(name, port, "output"):
- ports[port] for port in ports})
# Update per-instance parameters
if not hasattr(desc, "parameters"):
setattr(desc, "parameters", {})
@@ -195,6 +192,43 @@ class ImageBuilderConfig:
for param, value in six.iteritems(desc.parameters):
if param not in block["parameters"]:
block["parameters"][param] = value
+ # Generate list of block ports, adding 'index' to each port's dict
+ for direction in ("inputs", "outputs"):
+ index = 0
+ for port_name, port_info in desc.data[direction].items():
+ num_ports = 1
+ if "num_ports" in port_info:
+ parameter = port_info["num_ports"]
+ num_ports = parameter
+ if parameter in block["parameters"]:
+ num_ports = block["parameters"][parameter]
+ # Make sure the parameter resolved to a number
+ if not isinstance(num_ports, int):
+ logging.error(
+ "'num_ports' of port '%s' on block '%s' "
+ "resolved to invalid value of '%s'",
+ port_name, name, str(num_ports))
+ sys.exit(1)
+ if num_ports < 1 or num_ports > 64:
+ logging.error(
+ "'num_ports' of port '%s' on block '%s' "
+ "has invalid value '%s', must be in [1, 64]",
+ port_name, name, str(num_ports))
+ sys.exit(1)
+ if "num_ports" in port_info:
+ # If num_ports was a variable in the YAML, unroll into
+ # multiple ports
+ for i in range(num_ports):
+ new_port_info = port_info.copy()
+ new_port_info['index'] = index
+ index = index + 1
+ self.block_ports.update({(name, port_name + "_" \
+ + str(i), direction[:-1]) : new_port_info})
+ else:
+ port_info['index'] = index
+ self.block_ports.update(
+ {(name, port_name, direction[:-1]) : port_info})
+ index = index + 1
ports = self.stream_endpoints
for sep in self.stream_endpoints:
inputs = {(sep, "in%d" % port, "input") :
@@ -578,11 +612,15 @@ def write_verilog(config, destination, source, source_hash):
lookup=lookup,
strict_undefined=True)
- block = tpl.render(**{
- "config": config,
- "source": source,
- "source_hash": source_hash,
- })
+ try:
+ block = tpl.render(**{
+ "config": config,
+ "source": source,
+ "source_hash": source_hash,
+ })
+ except:
+ print(exceptions.text_error_template().render())
+ sys.exit(1)
logging.info("Writing image core to %s", destination)
with open(destination, "w") as image_core_file:
diff --git a/host/utils/rfnoc/templates/modules/drive_unused_ports.v.mako b/host/utils/rfnoc/templates/modules/drive_unused_ports.v.mako
index e6df532f0..dfa1e7eb6 100644
--- a/host/utils/rfnoc/templates/modules/drive_unused_ports.v.mako
+++ b/host/utils/rfnoc/templates/modules/drive_unused_ports.v.mako
@@ -1,5 +1,4 @@
-<%page args="connections, blocks, block_descs, seps"/>\
-\
+<%page args="connections, block_ports"/>\
<%
sources = []
destinations = []
@@ -7,31 +6,16 @@
sources.append((connection["srcblk"], connection["srcport"]))
destinations.append((connection["dstblk"], connection["dstport"]))
%>\
-%for sep in seps:
- %for input in range(seps[sep]["num_data_i"]):
- %if not (sep, "in%d" % (input)) in destinations:
- assign s_${sep}_in${input}_tdata = 'h0;
- assign s_${sep}_in${input}_tlast = 1'b0;
- assign s_${sep}_in${input}_tvalid = 1'b0;
+%for (block_name, port_name, direction) in block_ports:
+ %if direction == "input":
+ %if not (block_name, port_name) in destinations:
+ assign s_${block_name}_${port_name}_tdata = {CHDR_W{1'b0}};
+ assign s_${block_name}_${port_name}_tlast = 1'b0;
+ assign s_${block_name}_${port_name}_tvalid = 1'b0;
%endif
- %endfor
- %for output in range(seps[sep]["num_data_o"]):
- %if not (sep, "out%d" % (output)) in sources:
- assign m_${sep}_out${output}_tready = 1'b1;
+ %elif direction == "output":
+ %if not (block_name, port_name) in sources:
+ assign m_${block_name}_${port_name}_tready = 1'b1;
%endif
- %endfor
-%endfor
-%for block in blocks:
- %for input in block_descs[blocks[block]["block_desc"]].data["inputs"]:
- %if not (block, input) in destinations:
- assign s_${block}_${input}_tdata = ${block_descs[blocks[block]["block_desc"]].chdr_width}'h0;
- assign s_${block}_${input}_tlast = 1'b0;
- assign s_${block}_${input}_tvalid = 1'b0;
- %endif
- %endfor
- %for output in block_descs[blocks[block]["block_desc"]].data["outputs"]:
- %if not (block, output) in sources:
- assign m_${block}_${output}_tready = 1'b1;
- %endif
- %endfor
+ %endif
%endfor
diff --git a/host/utils/rfnoc/templates/modules/rfnoc_block.v.mako b/host/utils/rfnoc/templates/modules/rfnoc_block.v.mako
index 061e4dc8e..ee4a811a8 100644
--- a/host/utils/rfnoc/templates/modules/rfnoc_block.v.mako
+++ b/host/utils/rfnoc/templates/modules/rfnoc_block.v.mako
@@ -1,15 +1,22 @@
-<%page args="block_id, block_number, block_name, block, block_params"/>\
+<%page args="block_id, block_number, block_name, block, block_params, block_ports"/>\
\
<%
import re
import six
+
+ # Create two strings, one for the input and one for the output, that each
+ # contains all the signal names to be connected to the input or output
+ # AXIS-CHDR ports of this block.
axis_inputs = ""
axis_outputs = ""
- for input in list(block.data["inputs"].keys()):
- axis_inputs = "{0}_%s_%s_{1}, " % (block_name, input) + axis_inputs
+ for port_desc in block_ports:
+ if port_desc[0] == block_name:
+ port_name = port_desc[1]
+ if port_desc[2] == "input":
+ axis_inputs = "{0}_%s_%s_{1}, " % (block_name, port_name) + axis_inputs
+ elif port_desc[2] == "output":
+ axis_outputs = "{0}_%s_%s_{1}, " % (block_name, port_name) + axis_outputs
axis_inputs = axis_inputs[:-2]
- for output in list(block.data["outputs"].keys()):
- axis_outputs = "{0}_%s_%s_{1}, " % (block_name, output) + axis_outputs
axis_outputs = axis_outputs[:-2]
%>\
diff --git a/host/utils/rfnoc/templates/rfnoc_image_core.v.mako b/host/utils/rfnoc/templates/rfnoc_image_core.v.mako
index fb3cb3d2e..a18ff53a1 100644
--- a/host/utils/rfnoc/templates/rfnoc_image_core.v.mako
+++ b/host/utils/rfnoc/templates/rfnoc_image_core.v.mako
@@ -131,7 +131,7 @@ module rfnoc_image_core #(
// Blocks
// ----------------------------------------------------
%for i, name in enumerate(config.noc_blocks):
-<%include file="/modules/rfnoc_block.v.mako" args="block_id=i + len(ctrl_seps) + 1, block_number=i, block_name=name, block=config.blocks[config.noc_blocks[name]['block_desc']], block_params=config.noc_blocks[name]['parameters']"/>
+<%include file="/modules/rfnoc_block.v.mako" args="block_id=i + len(ctrl_seps) + 1, block_number=i, block_name=name, block=config.blocks[config.noc_blocks[name]['block_desc']], block_params=config.noc_blocks[name]['parameters'], block_ports=config.block_ports"/>
%endfor
// ----------------------------------------------------
@@ -142,7 +142,7 @@ module rfnoc_image_core #(
// ----------------------------------------------------
// Unused Ports
// ----------------------------------------------------
-<%include file="/modules/drive_unused_ports.v.mako" args="connections=config.block_con, blocks=config.noc_blocks, block_descs=config.blocks, seps=config.stream_endpoints"/>\
+<%include file="/modules/drive_unused_ports.v.mako" args="connections=config.block_con, block_ports=config.block_ports"/>\
// ----------------------------------------------------
// Clock Domains