Skip to content

Commit

Permalink
Merge pull request #6 from byuccl/tmr-config
Browse files Browse the repository at this point in the history
SpyDrNet 1.1.0
  • Loading branch information
jacobdbrown4 authored Oct 23, 2021
2 parents dafbc15 + aeff65c commit ca9f026
Show file tree
Hide file tree
Showing 44 changed files with 1,190 additions and 621 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ python:
- "3.9"
install:
- pip install ply
- pip install pyyaml
- pip install spydrnet
script:
- pytest
6 changes: 6 additions & 0 deletions RELEASE.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
SpyDrNet-TMR 1.1.0
------------------
October 23rd, 2021

- Added option for YAML configuration file to apply TMR to netlists

SpyDrNet-TMR 1.0.0
------------------
August 18th, 2021
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.. _find_after_ff_voter_points:

=========================================
find_after_ff_voter_points
=========================================

.. currentmodule:: spydrnet_tmr.analysis.voter_insertion.find_after_ff_voter_points
.. autofunction:: find_after_ff_voter_points


.. autosummary::
:toctree: generated/
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.. _find_before_ff_voter_points:

=========================================
find_before_ff_voter_points
=========================================

.. currentmodule:: spydrnet_tmr.analysis.voter_insertion.find_before_ff_voter_points
.. autofunction:: find_before_ff_voter_points


.. autosummary::
:toctree: generated/

This file was deleted.

This file was deleted.

8 changes: 4 additions & 4 deletions docs/reference/functions/analysis/voter_algorithms/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ Voter Algorithms

Currently, SpyDrNet TMR employs the following voter insertion algorithms:

* Place a feedback voter after every flip-flop. See :ref:`find_voter_insertion_after_ff`
* Place a feedback voter before every flip-flop. See :ref:`find_voter_insertion_before_ff`
* Place a feedback voter after every flip-flop. See :ref:`find_after_ff_voter_points`
* Place a feedback voter before every flip-flop. See :ref:`find_before_ff_voter_points`
* Place reduction voters where TMR boundaries are crossed (i.e. goes from triplicated to non triplicated). See :ref:`find_reduction_voter_points` and :ref:`identify_reduction_points`

.. toctree::
:maxdepth: 2

find_voter_insertion_points_before_ff
find_voter_insertion_points_after_ff
find_before_ff_voter_points
find_after_ff_voter_points
find_reduction_voter_points
identify_reduction_points
6 changes: 3 additions & 3 deletions docs/tutorial.rst
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,15 @@ Determine What To Replicate
Determine Organ Insertion Points
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
We call find_voter_insertion_points_after_ff() to determine where organs will be inserted. We pass the ports and instances to replicate and the flip flop types as parameters. A list of outer pins is returned. Each pin in the list corresponds to an instance's output at which an organ will be placed.
We call find_after_ff_voter_points() to determine where organs will be inserted. We pass the ports and instances to replicate and the flip flop types as parameters. A list of outer pins is returned. Each pin in the list corresponds to an instance's output at which an organ will be placed.

Note: one does not have to use find_voter_insertion_points_after_ff() but can instead specify the outer pins themselves (one would probably not want to use this function when finding detector insertion points, as it will most likely find more places to put detectors than is desired).
Note: one does not have to use find_after_ff_voter_points() but can instead specify the outer pins themselves (one would probably not want to use this function when finding detector insertion points, as it will most likely find more places to put detectors than is desired).

Other voter insertion point algorithms are available. See :ref:`voter_algorithms`

.. code-block::
insertion_points = find_voter_insertion_points_after_ff([*hinstances_to_replicate, *hports_to_replicate], {'FDRE', 'FDSE', 'FDPE', 'FDCE'})
insertion_points = find_after_ff_voter_points([*hinstances_to_replicate, *hports_to_replicate], {'FDRE', 'FDSE', 'FDPE', 'FDCE'})
Replicate the Design
^^^^^^^^^^^^^^^^^^^^^
Expand Down
163 changes: 163 additions & 0 deletions examples/basic/plot_config_tmr.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
"""
YAML Configuration Mode for Triplication
========================================
In order to ease the use of SpyDrNet-TMR and allow for complex replication/voter
insertion, support for YAML configurations has been implemented. A configuration
file for SpyDrNet-TMR is organized as the following:
.. code-block:: yaml
# Replication options for both instances and top-level ports
replication:
instances_to_replicate:
<instance_option>
ports_to_replicate:
<port_option>
voter_insertion:
<voter_algorithm_name>:
instances_at_valid_points:
<instance_option>
ports_at_valid_points:
<port_option>
Instance options include the following:
- `all`: include all instances
- `none`: exclude all instances
- `exclude_prim: ["<primitve_name>"]`: include all instances except for ones of primtive types listed
- `exclude_hinst: ["<hinst_name>"]`: include all instances except for the hierachircal instance names given
Port options include the following:
- `all`: include all top-level ports
- `none`: exclude all top-level ports
- `top_level_input_ports`: only include all top-level input ports
- `top_level_output_ports`: only include all top-level output ports
- `top_level_inoutput_ports`: only include all top-level in/output ports
- `exclude_ports: ["<port_name>"]`: include all top-level ports except for the port names given
Voter insertion algorithm names come from the module/function names found in
the `spydrnet_tmr/analysis/voter_insertion/` directory. The algorithm name is
matched with the modules/functions in that directory in the following manner:
`find_<voter_algorithm_name>_points.py`. The given algorithm name in a
configuration file must excatly match an algorithm from the algorithms in the
mentioned drectory.
- Example:
- `<voter_algorithm_name>` for `find_after_ff_voter_points.py` would be `after_ff`
- `<voter_algorithm_name>` for `find_after_ff_voter_points.py` would be `after_ff`
"""
import yaml
from yaml.loader import FullLoader


from spydrnet_tmr import load_example_netlist_by_name
from spydrnet_tmr.process_config import process_config
from spydrnet_tmr.apply_tmr_to_netlist import apply_tmr_to_netlist
from spydrnet_tmr.support_files.vendor_names import XILINX
from spydrnet import compose

YAML_CONFIG1 = """
################ TMR Config Example 1 ################
replication:
# All leaf instances will be replicated within the design.
instances_to_replicate:
all
# Only the top-level input ports will be replicated, which leaves any output
# ports or inoutput ports not replicated.
ports_to_replicate:
top_level_input_ports
# Here in the voter_insertion section, we have two algorithms that will be
# applied to the netlist.
#
# First, place a voter before every flip-flop in the design denoted by the
# name "before_ff" which comes from the function/module name in the
# 'spydrnet_tmr/analysis/voter_insertion/' directory. This needs to match exact!
# Second, place reduction voters for replicated to non-replicated TMR boundaries
# again denoted by the name "reduction" which comes from the corresponding
# function/module name.
#
# For both of these algorithms, all points will be considered for voter
# insertion, but that does not mean a voter will be placed at every point.
# For example, the "before_ff" algorithm will consider LUTs for voter insertion,
# but will ultimately decide not to place a voter before it because it isn't a
# flip-flop. If you don't want a voter at a certain instance/port, use
# 'exclude_prim', 'exclude_ports', or 'exclude_hinst'.
voter_insertion:
before_ff:
instances_at_valid_points:
all
ports_at_valid_points:
all
reduction:
instances_at_valid_points:
all
ports_at_valid_points:
all
"""

YAML_CONFIG2 = """
################ TMR Config Example 2 ################
replication:
# Here is an example of excluding an instance within the design. The
# hierarchical name is required.
instances_to_replicate:
exclude_hinst: ["PURPOSEFUL_GENERATE[8].SEQUENTIAL_LOGIC/DQ_reg[1]"]
ports_to_replicate:
all
voter_insertion:
reduction:
# Here is an example of excluding all instances of a primitive type for
# voter insertion. In this case, we want to do this because the flip-flop
# that is excluded from replication will receive a clock signal from the
# global clock buffer, and we don't want to place a voter in its path, so
# we'll exclude all BUFGs from the reduction voter insertion algorithm.
instances_at_valid_points:
exclude_prim: ["BUFG"]
ports_at_valid_points:
all
"""


def run():
netlist_config_pairs = {
"two_bit_counter_top": YAML_CONFIG1,
"registered_inverter": YAML_CONFIG2,
}

for netlist_name, config_filename in netlist_config_pairs.items():
process_config_and_apply_tmr(netlist_name, config_filename)


def process_config_and_apply_tmr(netlist_name, config_str):
"""
Process YAML configuration file and apply TMR to netlist.
Use the 'process_config' and 'apply_tmr_to_netlist' functions for an existing
example netlist and an existing config file.
"""

example_netlist_name = netlist_name
netlist = load_example_netlist_by_name(example_netlist_name)

tmr_config = yaml.load(config_str, Loader=FullLoader)
(
hinstances_and_hports_to_replicate,
valid_voter_point_dict,
) = process_config(netlist, tmr_config)

netlist = apply_tmr_to_netlist(
netlist,
XILINX,
hinstances_and_hports_to_replicate,
valid_voter_point_dict,
)

compose(netlist, netlist_name + "_tmr.edf")


run()
55 changes: 24 additions & 31 deletions examples/basic/plot_counter_bitstream_tmr.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@
set_property CONFIG_VOLTAGE 3.3 [current_design]
set_property CFGBVS VCCO [current_design]
Note that this example does not use the `apply_tmr_to_netlist`, but rather shows how TMR can be applied without using that function in the case that customization is required.
Note that this example does not use the `apply_tmr_to_netlist`, but rather shows how TMR can be applied without using that function in the case that customization is required.
SpyDrNet TMR allows for some flexibility when it comes to replicating instances and ports, and this is shown here in this example. Only the two LED ports ('led[1:0]') will be replicated from all of the top ports, which means the total LEDs used in the final netlist will be 6 (2 LEDs x 3 = 6 LEDs). All instances inside the netlist will be replicated.
Expand Down Expand Up @@ -130,18 +130,13 @@
This script will also build a bitstream if desired. To build it, simple set the `build_bitstream_flag` boolean to 'True' at the top of the script. A TCL script for Vivado's batch mode will be created that will load in the TMR netlist and build a bitstream for the correct part for the FPGA on the BASYS3 board. If Vivado is installed correctly, the script will then execute the commands in the auto-generated TCL script, and if successful, will output a bitstream (.bit) file ready to be downloaded to a board.
"""
from spydrnet.uniquify import uniquify
from spydrnet_tmr import apply_nmr, insert_organs
import spydrnet_tmr
from spydrnet_tmr.analysis.voter_insertion.find_voter_insertion_points_after_ff import (
find_voter_insertion_points_after_ff,
)
from spydrnet_tmr.transformation.replication.organ import XilinxTMRVoter
import pathlib
import subprocess

from spydrnet_tmr.support_files.xilinx_primitive_tokens import FF_CELLS
from spydrnet.uniquify import uniquify
import spydrnet_tmr
from spydrnet_tmr.apply_tmr_to_netlist import apply_tmr_to_netlist
from spydrnet_tmr.support_files.vendor_names import XILINX
from spydrnet_tmr.utils.load_primitive_info import load_primitive_info

# Set this flag to 'True' to build the bitstream, and 'False' to skip it
build_bitstream_flag = False
Expand All @@ -160,33 +155,32 @@ def run():
recursive=True, filter=lambda x: x.item.reference.is_leaf() is True
)
)
instances_to_replicate = list(x.item for x in hinstances_to_replicate)

# set ports_to_replicate [get_ports]
hports_to_replicate = list(netlist.get_hports())
ports_to_replicate = list(
x.item for x in hports_to_replicate if x.name == str("led[1:0]")
hports_to_replicate = list(
netlist.get_hports(filter=lambda x: x.item.name == str("led[1:0]"))
)

primitive_info = load_primitive_info(netlist, XILINX)

# find out where to insert reduction and feedback voters
insertion_points = find_voter_insertion_points_after_ff(
[*hinstances_to_replicate, *hports_to_replicate],
[cell.name for cell in primitive_info[FF_CELLS]],
)
valid_voter_point_dict = dict()
valid_voter_point_dict["reduction"] = [
*hinstances_to_replicate,
*hports_to_replicate,
]
valid_voter_point_dict["after_ff"] = [
*hinstances_to_replicate,
*hports_to_replicate,
]

# replicate instances and ports
replicas = apply_nmr(
[*instances_to_replicate, *ports_to_replicate],
3,
name_suffix="TMR",
rename_original=True,
apply_tmr_to_netlist(
netlist,
XILINX,
hinstances_and_hports_to_replicate=[
*hinstances_to_replicate,
*hports_to_replicate,
],
valid_voter_point_dict=valid_voter_point_dict,
)

# insert voters on the selected drivers
insert_organs(replicas, insertion_points, XilinxTMRVoter(), "VOTER")

netlist_tmr_name = netlist_name + "_tmr"

netlist.compose(netlist_tmr_name + ".edf")
Expand All @@ -201,7 +195,6 @@ def run():


def build_bitstream_from_netlist(extract_path, netlist_name, part):
import subprocess

# build_set = ["datapath", ["xdc"], [ "constants", "alu", "regfile", "datapath" ] ]

Expand Down
3 changes: 1 addition & 2 deletions examples/basic/plot_generic_tmr.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,13 @@
Basic TMR
----------
A bare minimum use case for SpyDrNet-TMR.
A bare minimum use case for SpyDrNet-TMR.
This script loads in a netlist of an inverter from SpyDrNet. Only required parameters are given to `apply_tmr_to_netlist` so default settings will be applied. Everything in the netlist will be replicated, including all top-level ports. Since there are no reduction voters required and no special voter insertion was enabled, there are no voters inserted in this design.
"""

import spydrnet as sdn
import spydrnet_tmr as sdn_tmr
from spydrnet_tmr.apply_tmr_to_netlist import apply_tmr_to_netlist
from spydrnet_tmr.support_files.vendor_names import XILINX

Expand Down
Loading

0 comments on commit ca9f026

Please sign in to comment.