Merge remote-tracking branch 'lnis_origin/master' into ganesh_dev

This commit is contained in:
Ganesh Gore 2021-01-23 19:06:35 -07:00
commit fec1d8eeb2
118 changed files with 6232 additions and 859 deletions

View File

@ -14,6 +14,7 @@ python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/full_testbench/config
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/full_testbench/configuration_chain_use_set --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/full_testbench/configuration_chain_use_setb --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/full_testbench/configuration_chain_use_set_reset --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/full_testbench/configuration_chain_config_enable_scff --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/full_testbench/multi_region_configuration_chain --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/full_testbench/fast_configuration_chain --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/full_testbench/fast_configuration_chain_use_set --debug --show_thread_logs
@ -108,6 +109,7 @@ python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/tile_organization/til
echo -e "Testing global port definition from tiles";
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/global_tile_ports/global_tile_clock --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/global_tile_ports/global_tile_reset --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/global_tile_ports/global_tile_4clock --debug --show_thread_logs
echo -e "Testing yosys flow using custom ys script for running quicklogic device";
python3 openfpga_flow/scripts/run_fpga_task.py quicklogic_tests/flow_test --debug --show_thread_logs

View File

@ -49,6 +49,9 @@ python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/io/embedded_io --deb
echo -e "Testing Verilog generation with SoC I/Os for an FPGA ";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/io/soc_io --debug --show_thread_logs
echo -e "Testing Verilog generation with registerable I/Os for an FPGA ";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/io/registerable_io --debug --show_thread_logs
echo -e "Testing Verilog generation with adder chain across an FPGA";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/fabric_chain/adder_chain --debug --show_thread_logs

View File

@ -6,7 +6,7 @@
The award-winning OpenFPGA framework is the **first open-source FPGA IP generator** supporting highly-customizable homogeneous FPGA architectures. OpenFPGA provides a full set of EDA support for customized FPGAs, including Verilog-to-bitstream generation and self-testing verification. OpenFPGA opens the door to democratizing FPGA technology and EDA techniques, with agile prototyping approaches and constantly evolving EDA tools for chip designers and researchers.
A quick overview of OpenFPGA tools can be found [**here**](https://openfpga.readthedocs.io/en/master/tutorials/tools.html).
A quick overview of OpenFPGA tools can be found [**here**](https://openfpga.readthedocs.io/en/master/tutorials/tools/).
We also recommend potential users to checkout the summary of [**technical capabilities**](https://openfpga.readthedocs.io/en/master/overview/tech_highlights.html) before compiling.
## Compilation

View File

@ -49,6 +49,8 @@ Similar to the Switch Boxes and Connection Blocks, the channel wire segments in
- ``circuit_model_name="<string>"`` should match a circuit model whose type is ``chan_wire`` defined in :ref:`circuit_library`.
.. _annotate_vpr_arch_physical_tile_annotation:
Physical Tile Annotation
~~~~~~~~~~~~~~~~~~~~~~~~
@ -60,21 +62,14 @@ Here is an example:
.. code-block:: xml
<tile_annotations>
<global_port name="<string>" tile_port="<string>" is_clock="<bool>" is_reset="<bool>" is_set="<bool>" default_val="<int>"/>
<global_port name="<string>" is_clock="<bool>" is_reset="<bool>" is_set="<bool>" default_val="<int>">
<tile name="<string>" port="<string>" x="<int>" y="<int>"/>
...
</global_port>
</tile_annotations>
- ``name="<string>"`` is the port name to appear in the top-level FPGA fabric.
- ``tile_port="<string>"`` is the port name of a physical tile, e.g., ``tile_port="clb.clk"``.
.. note:: The port of physical tile must be a valid port of the physical definition in VPR architecture!
.. note:: The linked port of physical tile must meet the following requirements:
- If the ``global_port`` is set as clock through ``is_clock="true"``, the port of the physical tile must also be a clock port.
- If not a clock, the port of the physical tile must be defined as non-clock global
- The port of the physical tile should have zero connectivity (``Fc=0``) in VPR architecture
- ``is_clock="<bool>"`` define if the global port is a clock port at the top-level FPGA fabric. An operating clock port will be driven by proper signals in auto-generated testbenches.
- ``is_reset="<bool>"`` define if the global port is a reset port at the top-level FPGA fabric. An operating reset port will be driven by proper signals in testbenches.
@ -87,6 +82,26 @@ Here is an example:
- ``default_val="<int>"`` define if the default value for the global port when initialized in testbenches. Valid values are either ``0`` or ``1``. For example, the default value of an active-high reset pin is ``0``, while an active-low reset pin is ``1``.
.. note:: A global port could be connected from different tiles by defining multiple <tile> lines under a global port!!!
.. option:: <tile name="<string>" port="<string>" x="<int>" y="<int>"/>
- ``name="<string>"`` is the name of a physical tile, e.g., ``name="clb"``.
- ``port="<string>"`` is the port name of a physical tile, e.g., ``port="clk[0:3]"``.
- ``x="<int>"`` is the x coordinate of a physical tile, e.g., ``x="1"``. If the x coordinate is set to ``-1``, it means all the valid x coordinates of the selected physical tile in the FPGA device will be considered.
- ``y="<int>"`` is the y coordinate of a physical tile, e.g., ``y="1"``. If the y coordinate is set to ``-1``, it means all the valid y coordinates of the selected physical tile in the FPGA device will be considered.
.. note:: The port of physical tile must be a valid port of the physical definition in VPR architecture! If you define a multi-bit port, it must be explicitly defined in the port, e.g., clk[0:3], which must be in the range of the port definition in physical tiles of VPR architecture files!!!
.. note:: The linked port of physical tile must meet the following requirements:
- If the ``global_port`` is set as clock through ``is_clock="true"``, the port of the physical tile must also be a clock port.
- If not a clock, the port of the physical tile must be defined as non-clock global
- The port of the physical tile should have zero connectivity (``Fc=0``) in VPR architecture
A more illustrative example:
:numref:`fig_global_tile_ports` illustrates the difference between the global ports defined through ``circuit_model`` and ``tile_annotation``.
@ -114,7 +129,9 @@ When a global port, e.g., ``clk``, is defined in ``tile_annotation`` using the f
.. code-block:: xml
<tile_annotations>
<global_port name="clk" tile_port="clb.clk" is_clock="true"/>
<global_port name="clk" is_clock="true">
<tile name="clb" port="clk"/>
</global_port>
</tile_annotations>
Clock port ``clk`` of each ``clb`` tile will be connected to a common clock port of the top module, while local clock network is customizable through VPR's architecture description language. For instance, the local clock network can be a programmable clock network.

View File

@ -136,6 +136,8 @@ Pass Gate Logic
.. note:: pass-gate logic are used in building multiplexers and LUTs.
.. _circuit_library_circuit_port:
Circuit Port
^^^^^^^^^^^^

View File

@ -979,18 +979,18 @@ This example shows:
.. _circuit_model_ccff_example:
Configuration-chain Flip-flop
`````````````````````````````
Regular Configuration-chain Flip-flop
`````````````````````````````````````
:numref:`fig_ccff` illustrates an example of scan-chain flop-flop used to build a configuration chain.
:numref:`fig_ccff_config_chain` illustrates an example of standard flip-flops used to build a configuration chain.
.. _fig_ccff:
.. _fig_ccff_config_chain:
.. figure:: ./figures/scff.png
.. figure:: ./figures/config_chain.svg
:scale: 50%
:alt: SCFF symbol
An example of a Scan-Chain Flip-Flop.
An example of a Flip-Flop organized in a chain.
The code describing this FF is:
@ -999,14 +999,94 @@ The code describing this FF is:
<circuit_model type="ccff" name="ccff" prefix="ccff" verilog_netlist="ccff.v" spice_netlist="ccff.sp">
<port type="input" prefix="D" size="1"/>
<port type="output" prefix="Q" size="1"/>
<port type="output" prefix="Qb" size="1"/>
<port type="clock" prefix="CK" size="1" is_global="true"/>
<port type="output" prefix="QN" size="1"/>
<port type="clock" prefix="CK" size="1" is_global="true" is_prog="true" is_clock="true"/>
</circuit_model>
This example shows:
- A configuration-chain flip-flop which is defined in a Verilog netlist ``ccff.v`` and a SPICE netlist ``ccff.sp``
- The flip-flop has a global clock port, ``CK``, which will be wired a global programming clock
.. note::
The output ports of the configuration flip-flop must follow a fixed sequence in definition:
- The first output port **MUST** be the data output port, e.g., ``Q``.
- The second output port **MUST** be the **inverted** data output port, e.g., ``QN``.
Configuration-chain Flip-flop with Configure Enable Signals
```````````````````````````````````````````````````````````
Configuration chain could be built with flip-flops with outputs that are enabled by specific signals.
Consider the example in :numref:`fig_ccff_config_chain_config_enable`, the flip-flop has
- a configure enable signal ``CFG_EN`` to release the data output ``Q`` and ``QN``
- a pair of data outputs ``Q`` and ``QN`` which are controlled by the configure enable signal ``CFG_EN``
- a regular data output ``SCAN_Q`` which outputs registered data
.. _fig_ccff_config_chain_config_enable:
.. figure:: ./figures/config_chain_config_enable.svg
:scale: 50%
:alt: SCFF symbol
An example of a Flip-Flop with config enable feature organized in a chain.
The code describing this FF is:
.. code-block:: xml
<circuit_model type="ccff" name="ccff" prefix="ccff" verilog_netlist="ccff.v" spice_netlist="ccff.sp">
<port type="input" prefix="CFG_EN" size="1" is_global="true" is_config_enable="true"/>
<port type="input" prefix="D" size="1"/>
<port type="output" prefix="SCAN_Q" size="1"/>
<port type="output" prefix="QN" size="1"/>
<port type="output" prefix="Q" size="1"/>
<port type="clock" prefix="CK" size="1" is_global="true" is_prog="true" is_clock="true"/>
</circuit_model>
.. note::
The output ports of the configuration flip-flop must follow a fixed sequence in definition:
- The first output port **MUST** be the regular data output port, e.g., ``SCAN_Q``.
- The second output port **MUST** be the **inverted** data output port which is activated by the configure enable signal, e.g., ``QN``.
- The second output port **MUST** be the data output port which is activated by the configure enable signal, e.g., ``Q``.
Configuration-chain Flip-flop with Scan Input
`````````````````````````````````````````````
Configuration chain could be built with flip-flops with a scan chain input .
Consider the example in :numref:`fig_ccff_config_chain_scan_capable`, the flip-flop has
- an additional input ``SI`` to enable scan-chain capabaility
- a configure enable signal ``CFG_EN`` to release the data output ``Q`` and ``QN``
- a pair of data outputs ``Q`` and ``QN`` which are controlled by the configure enable signal ``CFG_EN``
- a regular data output ``SCAN_Q`` which outputs registered data
.. _fig_ccff_config_chain_scan_capable:
.. figure:: ./figures/config_chain_scan_capable.svg
:scale: 50%
:alt: SCFF symbol
An example of a Flip-Flop with scan input organized in a chain.
The code describing this FF is:
.. code-block:: xml
<circuit_model type="ccff" name="ccff" prefix="ccff" verilog_netlist="ccff.v" spice_netlist="ccff.sp">
<port type="input" prefix="CFG_EN" size="1" is_global="true" is_config_enable="true"/>
<port type="input" prefix="D" size="1"/>
<port type="input" prefix="SI" size="1"/>
<port type="output" prefix="SCAN_Q" size="1"/>
<port type="output" prefix="QN" size="1"/>
<port type="output" prefix="Q" size="1"/>
<port type="clock" prefix="CK" size="1" is_global="true" is_prog="true" is_clock="true"/>
</circuit_model>
.. note::
The input ports of the configuration flip-flop must follow a fixed sequence in definition:
- The first input port **MUST** be the regular data input port, e.g., ``D``.
- The second input port **MUST** be the scan input port, e.g., ``SI``.
Hard Logics
~~~~~~~~~~~

View File

@ -0,0 +1,375 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:xl="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" viewBox="85.49984 326.11534 685.6513 148.03441" width="685.6513" height="148.03441">
<defs>
<font-face font-family="Times New Roman" font-size="14" panose-1="2 2 6 3 5 4 5 2 3 4" units-per-em="1000" underline-position="-108.88672" underline-thickness="48.828125" slope="0" x-height="447.2656" cap-height="662.1094" ascent="891.1133" descent="-216.3086" font-weight="400">
<font-face-src>
<font-face-name name="TimesNewRomanPSMT"/>
</font-face-src>
</font-face>
<font-face font-family="Times New Roman" font-size="9" panose-1="2 2 6 3 5 4 5 2 3 4" units-per-em="1000" underline-position="-108.88672" underline-thickness="48.828125" slope="0" x-height="447.2656" cap-height="662.1094" ascent="891.1133" descent="-216.3086" font-weight="400">
<font-face-src>
<font-face-name name="TimesNewRomanPSMT"/>
</font-face-src>
</font-face>
<font-face font-family="Times New Roman" font-size="14" panose-1="2 2 5 3 5 4 5 9 3 4" units-per-em="1000" underline-position="-108.88672" underline-thickness="48.828125" slope="-1166.6423" x-height="430.1758" cap-height="662.1094" ascent="891.1133" descent="-216.3086" font-style="italic" font-weight="400">
<font-face-src>
<font-face-name name="TimesNewRomanPS-ItalicMT"/>
</font-face-src>
</font-face>
<font-face font-family="Times New Roman" font-size="9" panose-1="2 2 5 3 5 4 5 9 3 4" units-per-em="1000" underline-position="-108.88672" underline-thickness="48.828125" slope="-1814.777" x-height="430.1758" cap-height="662.1094" ascent="891.1133" descent="-216.3086" font-style="italic" font-weight="400">
<font-face-src>
<font-face-name name="TimesNewRomanPS-ItalicMT"/>
</font-face-src>
</font-face>
<font-face font-family="Times New Roman" font-size="12" panose-1="2 2 5 3 5 4 5 9 3 4" units-per-em="1000" underline-position="-108.88672" underline-thickness="48.828125" slope="-1361.0827" x-height="430.1758" cap-height="662.1094" ascent="891.1133" descent="-216.3086" font-style="italic" font-weight="400">
<font-face-src>
<font-face-name name="TimesNewRomanPS-ItalicMT"/>
</font-face-src>
</font-face>
<font-face font-family="Times New Roman" font-size="12" panose-1="2 2 8 3 7 5 5 2 3 4" units-per-em="1000" underline-position="-108.88672" underline-thickness="95.21484" slope="0" x-height="456.54297" cap-height="662.1094" ascent="891.1133" descent="-216.3086" font-weight="700">
<font-face-src>
<font-face-name name="TimesNewRomanPS-BoldMT"/>
</font-face-src>
</font-face>
</defs>
<metadata> Produced by OmniGraffle 7.18.1\n2021-01-05 01:03:21 +0000</metadata>
<g id="regular" stroke-opacity="1" stroke="none" fill-opacity="1" fill="none" stroke-dasharray="none">
<title>regular</title>
<g id="regular_Layer_1">
<title>Layer 1</title>
<g id="Group_35788">
<g id="Graphic_35772">
<rect x="176.97979" y="347.32" width="67.44001" height="58.68" fill="#ffffc0"/>
<rect x="176.97979" y="347.32" width="67.44001" height="58.68" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
<text transform="translate(181.97979 368.86263)" fill="black">
<tspan font-family="Times New Roman" font-size="14" font-weight="400" fill="black" x="11.595982" y="12">CCFF</tspan>
</text>
</g>
<g id="Graphic_35775">
<text transform="translate(178.04028 358.26883)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">D</tspan>
</text>
</g>
<g id="Graphic_35776">
<text transform="translate(185.1764 387.8059)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">CLK</tspan>
</text>
</g>
<g id="Line_35778">
<line x1="175.8488" y1="362.96" x2="164.16" y2="362.9738" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35779">
<line x1="175.8488" y1="392.49704" x2="164.16" y2="392.51084" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35781">
<line x1="257.2396" y1="362.96" x2="245.5508" y2="362.97366" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35780">
<line x1="257.2396" y1="385.51786" x2="245.5508" y2="385.53153" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_35785">
<path d="M 176.97979 388.91704 L 184.53979 392.99704 L 176.97979 397.07704 Z" fill="#ccc"/>
<path d="M 176.97979 388.91704 L 184.53979 392.99704 L 176.97979 397.07704 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Graphic_35786">
<text transform="translate(235.8 358.26883)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">Q</tspan>
</text>
</g>
<g id="Graphic_35787">
<text transform="translate(229.54877 380.8267)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">QN</tspan>
</text>
</g>
</g>
<g id="Group_35789">
<g id="Graphic_35799">
<rect x="295.0598" y="347.32" width="67.44001" height="58.68" fill="#ffffc0"/>
<rect x="295.0598" y="347.32" width="67.44001" height="58.68" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
<text transform="translate(300.0598 368.86263)" fill="black">
<tspan font-family="Times New Roman" font-size="14" font-weight="400" fill="black" x="11.595982" y="12">CCFF</tspan>
</text>
</g>
<g id="Graphic_35798">
<text transform="translate(296.12027 358.26883)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">D</tspan>
</text>
</g>
<g id="Graphic_35797">
<text transform="translate(303.2564 387.8059)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">CLK</tspan>
</text>
</g>
<g id="Line_35796">
<line x1="293.9288" y1="362.96" x2="282.24" y2="362.9738" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35795">
<line x1="293.9288" y1="392.49704" x2="282.24" y2="392.51084" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35794">
<line x1="375.3196" y1="362.96" x2="363.6308" y2="362.97366" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35793">
<line x1="375.3196" y1="385.51786" x2="363.6308" y2="385.53153" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_35792">
<path d="M 295.0598 388.91704 L 302.6198 392.99704 L 295.0598 397.07704 Z" fill="#ccc"/>
<path d="M 295.0598 388.91704 L 302.6198 392.99704 L 295.0598 397.07704 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Graphic_35791">
<text transform="translate(353.88 358.26883)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">Q</tspan>
</text>
</g>
<g id="Graphic_35790">
<text transform="translate(347.62877 380.8267)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">QN</tspan>
</text>
</g>
</g>
<g id="Group_35800">
<g id="Graphic_35810">
<rect x="591.108" y="347.07" width="67.44001" height="58.68" fill="#ffffc0"/>
<rect x="591.108" y="347.07" width="67.44001" height="58.68" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
<text transform="translate(596.108 368.61263)" fill="black">
<tspan font-family="Times New Roman" font-size="14" font-style="italic" font-weight="400" fill="black" x="10.830357" y="12">CCFF</tspan>
</text>
</g>
<g id="Graphic_35809">
<text transform="translate(592.1685 358.01883)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-style="italic" font-weight="400" fill="black" x="0" y="8">D</tspan>
</text>
</g>
<g id="Graphic_35808">
<text transform="translate(599.799 387.5559)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-style="italic" font-weight="400" fill="black" x="0" y="8">CLK</tspan>
</text>
</g>
<g id="Line_35807">
<line x1="589.977" y1="362.71" x2="578.2882" y2="362.7238" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35806">
<line x1="589.977" y1="392.24704" x2="578.2882" y2="392.26084" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35805">
<line x1="671.3678" y1="362.71" x2="659.679" y2="362.72366" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35804">
<line x1="671.3678" y1="385.26786" x2="659.679" y2="385.28153" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_35803">
<path d="M 591.108 388.66704 L 598.668 392.74704 L 591.108 396.82704 Z" fill="#ccc"/>
<path d="M 591.108 388.66704 L 598.668 392.74704 L 591.108 396.82704 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Graphic_35802">
<text transform="translate(649.9282 358.01883)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-style="italic" font-weight="400" fill="black" x="0" y="8">Q</tspan>
</text>
</g>
<g id="Graphic_35801">
<text transform="translate(643.9253 380.5767)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-style="italic" font-weight="400" fill="black" x="0" y="8">QN</tspan>
</text>
</g>
</g>
<g id="Line_35812">
<line x1="257.2396" y1="362.96" x2="282.24" y2="362.9738" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35813">
<line x1="123.76164" y1="420.28384" x2="578.2882" y2="419.25" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35814">
<line x1="578.2882" y1="392.26084" x2="578.2882" y2="419.25" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35815">
<line x1="282.24" y1="392.51084" x2="282.4856" y2="417.73015" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35816">
<line x1="164.16" y1="392.51084" x2="164.11552" y2="417.301" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_35817">
<text transform="translate(96.08 413.06613)" fill="black">
<tspan font-family="Times New Roman" font-size="12" font-style="italic" font-weight="400" fill="black" x="0" y="11">CLK</tspan>
</text>
</g>
<g id="Graphic_35818">
<text transform="translate(90.49984 355.6251)" fill="black">
<tspan font-family="Times New Roman" font-size="12" font-style="italic" font-weight="400" fill="black" x="0" y="11">CCFF_HEAD</tspan>
</text>
</g>
<g id="Line_35819">
<line x1="257.2396" y1="385.51786" x2="256.6573" y2="449.64" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35820">
<line x1="268.8802" y1="365.89998" x2="269.125" y2="439" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_35821">
<ellipse cx="268.8701" cy="362.88" rx="2.47010548958709" ry="2.52000397038629" fill="black"/>
<ellipse cx="268.8701" cy="362.88" rx="2.47010548958709" ry="2.52000397038629" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Graphic_35822">
<ellipse cx="282.515" cy="420.75" rx="2.47010548958708" ry="2.5200039703863" fill="black"/>
<ellipse cx="282.515" cy="420.75" rx="2.47010548958708" ry="2.5200039703863" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Graphic_35823">
<ellipse cx="164.1101" cy="420.321" rx="2.47010548958709" ry="2.52000397038635" fill="black"/>
<ellipse cx="164.1101" cy="420.321" rx="2.47010548958709" ry="2.52000397038635" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Line_35825">
<line x1="375.3196" y1="385.51786" x2="375.0411" y2="447.48" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35824">
<line x1="389.23688" y1="362.88283" x2="389.11" y2="439" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_35826">
<ellipse cx="389.3301" cy="362.88" rx="2.47010548958705" ry="2.52000397038629" fill="black"/>
<ellipse cx="389.3301" cy="362.88" rx="2.47010548958705" ry="2.52000397038629" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Group_35827">
<g id="Graphic_35837">
<rect x="430.7424" y="347.07" width="67.44001" height="58.68" fill="#ffffc0"/>
<rect x="430.7424" y="347.07" width="67.44001" height="58.68" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
<text transform="translate(435.7424 368.61263)" fill="black">
<tspan font-family="Times New Roman" font-size="14" font-style="italic" font-weight="400" fill="black" x="10.830357" y="12">CCFF</tspan>
</text>
</g>
<g id="Graphic_35836">
<text transform="translate(431.8029 358.01883)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-style="italic" font-weight="400" fill="black" x="0" y="8">D</tspan>
</text>
</g>
<g id="Graphic_35835">
<text transform="translate(439.4334 387.5559)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-style="italic" font-weight="400" fill="black" x="0" y="8">CLK</tspan>
</text>
</g>
<g id="Line_35834">
<line x1="429.6114" y1="362.71" x2="417.9226" y2="362.7238" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35833">
<line x1="429.6114" y1="392.24704" x2="417.9226" y2="392.26084" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35832">
<line x1="511.0022" y1="362.71" x2="499.3134" y2="362.72366" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35831">
<line x1="511.0022" y1="385.26786" x2="499.3134" y2="385.28153" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_35830">
<path d="M 430.7424 388.66704 L 438.3024 392.74704 L 430.7424 396.82704 Z" fill="#ccc"/>
<path d="M 430.7424 388.66704 L 438.3024 392.74704 L 430.7424 396.82704 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Graphic_35829">
<text transform="translate(489.5626 358.01883)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-style="italic" font-weight="400" fill="black" x="0" y="8">Q</tspan>
</text>
</g>
<g id="Graphic_35828">
<text transform="translate(483.5597 380.5767)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-style="italic" font-weight="400" fill="black" x="0" y="8">QN</tspan>
</text>
</g>
</g>
<g id="Line_35838">
<line x1="375.3196" y1="362.96" x2="417.9226" y2="362.7238" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_35839">
<text transform="translate(560.84 352.07)" fill="black">
<tspan font-family="Times New Roman" font-size="14" font-style="italic" font-weight="400" fill="black" x="0" y="12"></tspan>
</text>
</g>
<g id="Line_35841">
<line x1="417.9226" y1="392.26084" x2="417.7868" y2="416.7892" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_35840">
<ellipse cx="417.7701" cy="419.80915" rx="2.47010548958708" ry="2.52000397038635" fill="black"/>
<ellipse cx="417.7701" cy="419.80915" rx="2.47010548958708" ry="2.52000397038635" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Graphic_35842">
<text transform="translate(705.2 355.28)" fill="black">
<tspan font-family="Times New Roman" font-size="12" font-style="italic" font-weight="400" fill="black" x="0" y="11">CCFF_TAIL</tspan>
</text>
</g>
<g id="Line_35843">
<line x1="511.0022" y1="362.7562" x2="553.6052" y2="362.52" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35844">
<line x1="671.3678" y1="362.71" x2="700.2" y2="362.63117" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35846">
<line x1="523.2969" y1="362.16283" x2="523.17" y2="438.28" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_35845">
<ellipse cx="523.3901" cy="362.16" rx="2.47010548958711" ry="2.52000397038627" fill="black"/>
<ellipse cx="523.3901" cy="362.16" rx="2.47010548958711" ry="2.52000397038627" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Line_35848">
<line x1="686.1907" y1="362.16283" x2="686.0638" y2="438.28" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_35847">
<ellipse cx="686.2839" cy="362.16" rx="2.47010548958711" ry="2.52000397038627" fill="black"/>
<ellipse cx="686.2839" cy="362.16" rx="2.47010548958711" ry="2.52000397038627" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Line_35849">
<line x1="511.2522" y1="385.29786" x2="511.6981" y2="447.48" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35850">
<line x1="671.6178" y1="385.29786" x2="671.3248" y2="446.4" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_35851">
<text transform="translate(266 436.64)" fill="black">
<tspan font-family="Times New Roman" font-size="12" font-style="italic" font-weight="400" fill="black" x="0" y="11">mem_out[0]</tspan>
</text>
</g>
<g id="Graphic_35852">
<text transform="translate(223.88 454.64)" fill="black">
<tspan font-family="Times New Roman" font-size="12" font-style="italic" font-weight="400" fill="black" x="0" y="11">mem_outb[0]</tspan>
</text>
</g>
<g id="Graphic_35853">
<text transform="translate(388.10408 435.2)" fill="black">
<tspan font-family="Times New Roman" font-size="12" font-style="italic" font-weight="400" fill="black" x="0" y="11">mem_out[1]</tspan>
</text>
</g>
<g id="Graphic_35854">
<text transform="translate(342.32 452.48)" fill="black">
<tspan font-family="Times New Roman" font-size="12" font-style="italic" font-weight="400" fill="black" x="0" y="11">mem_outb[1]</tspan>
</text>
</g>
<g id="Graphic_35856">
<text transform="translate(522.32 435.2)" fill="black">
<tspan font-family="Times New Roman" font-size="12" font-style="italic" font-weight="400" fill="black" x="0" y="11">mem_out[2]</tspan>
</text>
</g>
<g id="Graphic_35855">
<text transform="translate(479.12 452.48)" fill="black">
<tspan font-family="Times New Roman" font-size="12" font-style="italic" font-weight="400" fill="black" x="0" y="11">mem_outb[2]</tspan>
</text>
</g>
<g id="Graphic_35858">
<text transform="translate(678.92 435.2)" fill="black">
<tspan font-family="Times New Roman" font-size="12" font-style="italic" font-weight="400" fill="black" x="0" y="11">mem_out[n]</tspan>
</text>
</g>
<g id="Graphic_35857">
<text transform="translate(638.6 451.4)" fill="black">
<tspan font-family="Times New Roman" font-size="12" font-style="italic" font-weight="400" fill="black" x="0" y="11">mem_outb[n]</tspan>
</text>
</g>
<g id="Line_35859">
<line x1="97" y1="432.37333" x2="770.6512" y2="428.66667" stroke="#ff2600" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="4.0,4.0" stroke-width="1"/>
</g>
<g id="Graphic_35860">
<text transform="translate(94.55704 439.64204)" fill="#ff2600">
<tspan font-family="Times New Roman" font-size="12" font-weight="700" fill="#ff2600" x="0" y="11">Configurable Circuits</tspan>
</text>
</g>
<g id="Graphic_35861">
<text transform="translate(90.49984 331.11534)" fill="#ff2600">
<tspan font-family="Times New Roman" font-size="12" font-weight="700" fill="#ff2600" x="0" y="11">Configuration Chain</tspan>
</text>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 23 KiB

View File

@ -0,0 +1,411 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:xl="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" viewBox="85.49984 288 687.9915 211.40894" width="687.9915" height="211.40894">
<defs>
<font-face font-family="Times New Roman" font-size="12" panose-1="2 2 5 3 5 4 5 9 3 4" units-per-em="1000" underline-position="-108.88672" underline-thickness="48.828125" slope="-1361.0827" x-height="430.1758" cap-height="662.1094" ascent="891.1133" descent="-216.3086" font-style="italic" font-weight="400">
<font-face-src>
<font-face-name name="TimesNewRomanPS-ItalicMT"/>
</font-face-src>
</font-face>
<font-face font-family="Times New Roman" font-size="14" panose-1="2 2 5 3 5 4 5 9 3 4" units-per-em="1000" underline-position="-108.88672" underline-thickness="48.828125" slope="-1166.6423" x-height="430.1758" cap-height="662.1094" ascent="891.1133" descent="-216.3086" font-style="italic" font-weight="400">
<font-face-src>
<font-face-name name="TimesNewRomanPS-ItalicMT"/>
</font-face-src>
</font-face>
<font-face font-family="Times New Roman" font-size="14" panose-1="2 2 6 3 5 4 5 2 3 4" units-per-em="1000" underline-position="-108.88672" underline-thickness="48.828125" slope="0" x-height="447.2656" cap-height="662.1094" ascent="891.1133" descent="-216.3086" font-weight="400">
<font-face-src>
<font-face-name name="TimesNewRomanPSMT"/>
</font-face-src>
</font-face>
<font-face font-family="Times New Roman" font-size="9" panose-1="2 2 6 3 5 4 5 2 3 4" units-per-em="1000" underline-position="-108.88672" underline-thickness="48.828125" slope="0" x-height="447.2656" cap-height="662.1094" ascent="891.1133" descent="-216.3086" font-weight="400">
<font-face-src>
<font-face-name name="TimesNewRomanPSMT"/>
</font-face-src>
</font-face>
<font-face font-family="Times New Roman" font-size="12" panose-1="2 2 8 3 7 5 5 2 3 4" units-per-em="1000" underline-position="-108.88672" underline-thickness="95.21484" slope="0" x-height="456.54297" cap-height="662.1094" ascent="891.1133" descent="-216.3086" font-weight="700">
<font-face-src>
<font-face-name name="TimesNewRomanPS-BoldMT"/>
</font-face-src>
</font-face>
</defs>
<metadata> Produced by OmniGraffle 7.18.1\n2021-01-05 01:03:21 +0000</metadata>
<g id="config_enable" stroke-opacity="1" stroke="none" fill-opacity="1" fill="none" stroke-dasharray="none">
<title>config_enable</title>
<g id="config_enable_Layer_1">
<title>Layer 1</title>
<g id="Line_35813">
<line x1="123.76164" y1="420.2495" x2="580.523" y2="418.25" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35816">
<line x1="164.16" y1="392.51084" x2="164.11552" y2="417.301" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_35817">
<text transform="translate(96.08 413.06613)" fill="black">
<tspan font-family="Times New Roman" font-size="12" font-style="italic" font-weight="400" fill="black" x="0" y="11">CLK</tspan>
</text>
</g>
<g id="Graphic_35818">
<text transform="translate(90.49984 355.6251)" fill="black">
<tspan font-family="Times New Roman" font-size="12" font-style="italic" font-weight="400" fill="black" x="0" y="11">CCFF_HEAD</tspan>
</text>
</g>
<g id="Graphic_35822">
<ellipse cx="294.0701" cy="419.42256" rx="2.47010548958708" ry="2.52000397038635" fill="black"/>
<ellipse cx="294.0701" cy="419.42256" rx="2.47010548958708" ry="2.52000397038635" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Graphic_35823">
<ellipse cx="164.1101" cy="420.321" rx="2.47010548958709" ry="2.52000397038635" fill="black"/>
<ellipse cx="164.1101" cy="420.321" rx="2.47010548958709" ry="2.52000397038635" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Graphic_35839">
<text transform="translate(560.84 352.07)" fill="black">
<tspan font-family="Times New Roman" font-size="14" font-style="italic" font-weight="400" fill="black" x="0" y="12"></tspan>
</text>
</g>
<g id="Graphic_35840">
<ellipse cx="417.7701" cy="419.80915" rx="2.47010548958708" ry="2.52000397038635" fill="black"/>
<ellipse cx="417.7701" cy="419.80915" rx="2.47010548958708" ry="2.52000397038635" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Graphic_35842">
<text transform="translate(680.8373 354.9051)" fill="black">
<tspan font-family="Times New Roman" font-size="12" font-style="italic" font-weight="400" fill="black" x="0" y="11">CCFF_TAIL</tspan>
</text>
</g>
<g id="Line_35843">
<line x1="511.0022" y1="362.7562" x2="553.6052" y2="362.52" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35849">
<line x1="580.523" y1="392.26084" x2="580.523" y2="418.25" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_35851">
<text transform="translate(189.32 452.48)" fill="black">
<tspan font-family="Times New Roman" font-size="12" font-style="italic" font-weight="400" fill="black" x="0" y="11">mem_out[0]</tspan>
</text>
</g>
<g id="Graphic_35852">
<text transform="translate(232.16 433.04)" fill="black">
<tspan font-family="Times New Roman" font-size="12" font-style="italic" font-weight="400" fill="black" x="0" y="11">mem_outb[0]</tspan>
</text>
</g>
<g id="Graphic_35853">
<text transform="translate(318.56 449.6)" fill="black">
<tspan font-family="Times New Roman" font-size="12" font-style="italic" font-weight="400" fill="black" x="0" y="11">mem_out[1]</tspan>
</text>
</g>
<g id="Graphic_35854">
<text transform="translate(362.9025 430.88)" fill="black">
<tspan font-family="Times New Roman" font-size="12" font-style="italic" font-weight="400" fill="black" x="0" y="11">mem_outb[1]</tspan>
</text>
</g>
<g id="Graphic_35856">
<text transform="translate(442.04 452.48)" fill="black">
<tspan font-family="Times New Roman" font-size="12" font-style="italic" font-weight="400" fill="black" x="0" y="11">mem_out[2]</tspan>
</text>
</g>
<g id="Graphic_35855">
<text transform="translate(486.68 430.88)" fill="black">
<tspan font-family="Times New Roman" font-size="12" font-style="italic" font-weight="400" fill="black" x="0" y="11">mem_outb[2]</tspan>
</text>
</g>
<g id="Graphic_35858">
<text transform="translate(606.2 446.72)" fill="black">
<tspan font-family="Times New Roman" font-size="12" font-style="italic" font-weight="400" fill="black" x="0" y="11">mem_out[n]</tspan>
</text>
</g>
<g id="Graphic_35857">
<text transform="translate(650.12 429.8)" fill="black">
<tspan font-family="Times New Roman" font-size="12" font-style="italic" font-weight="400" fill="black" x="0" y="11">mem_outb[n]</tspan>
</text>
</g>
<g id="Group_35863">
<g id="Graphic_35772">
<rect x="176.97979" y="347.32" width="67.44001" height="58.68" fill="#ffffc0"/>
<rect x="176.97979" y="347.32" width="67.44001" height="58.68" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
<text transform="translate(181.97979 368.86263)" fill="black">
<tspan font-family="Times New Roman" font-size="14" font-weight="400" fill="black" x="11.595982" y="12">CCFF</tspan>
</text>
</g>
<g id="Graphic_35775">
<text transform="translate(178.04028 358.26883)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">D</tspan>
</text>
</g>
<g id="Graphic_35776">
<text transform="translate(185.1764 387.8059)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">CLK</tspan>
</text>
</g>
<g id="Line_35778">
<line x1="175.8488" y1="362.96" x2="164.16" y2="362.9738" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35779">
<line x1="175.8488" y1="392.49704" x2="164.16" y2="392.51084" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35781">
<line x1="257.2396" y1="362.96" x2="245.5508" y2="362.97366" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_35785">
<path d="M 176.97979 388.91704 L 184.53979 392.99704 L 176.97979 397.07704 Z" fill="#ccc"/>
<path d="M 176.97979 388.91704 L 184.53979 392.99704 L 176.97979 397.07704 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Graphic_35786">
<text transform="translate(207.96647 358.26883)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">SCAN_Q</tspan>
</text>
</g>
<g id="Graphic_35859">
<text transform="translate(226.63794 395.36767)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">QN</tspan>
</text>
</g>
<g id="Graphic_35860">
<text transform="translate(214.92 395.61767)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">Q</tspan>
</text>
</g>
</g>
<g id="Line_35861">
<line x1="218.88" y1="405.90486" x2="218.96188" y2="447.48" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35862">
<line x1="235.8" y1="406" x2="235.8" y2="432.84513" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Group_35864">
<g id="Graphic_35874">
<rect x="306.9398" y="347.32" width="67.44001" height="58.68" fill="#ffffc0"/>
<rect x="306.9398" y="347.32" width="67.44001" height="58.68" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
<text transform="translate(311.9398 368.86263)" fill="black">
<tspan font-family="Times New Roman" font-size="14" font-weight="400" fill="black" x="11.595982" y="12">CCFF</tspan>
</text>
</g>
<g id="Graphic_35873">
<text transform="translate(308.00027 358.26883)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">D</tspan>
</text>
</g>
<g id="Graphic_35872">
<text transform="translate(315.1364 387.8059)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">CLK</tspan>
</text>
</g>
<g id="Line_35871">
<line x1="305.8088" y1="362.96" x2="294.12" y2="362.9738" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35870">
<line x1="305.8088" y1="392.49704" x2="294.12" y2="392.51084" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35869">
<line x1="387.1996" y1="362.96" x2="375.5108" y2="362.97366" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_35868">
<path d="M 306.9398 388.91704 L 314.4998 392.99704 L 306.9398 397.07704 Z" fill="#ccc"/>
<path d="M 306.9398 388.91704 L 314.4998 392.99704 L 306.9398 397.07704 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Graphic_35867">
<text transform="translate(337.92647 358.26883)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">SCAN_Q</tspan>
</text>
</g>
<g id="Graphic_35866">
<text transform="translate(356.59794 395.36767)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">QN</tspan>
</text>
</g>
<g id="Graphic_35865">
<text transform="translate(344.88 395.61767)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">Q</tspan>
</text>
</g>
</g>
<g id="Line_35875">
<line x1="257.2396" y1="362.96" x2="294.12" y2="362.9738" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Group_35877">
<g id="Graphic_35887">
<rect x="430.7424" y="347.07" width="67.44001" height="58.68" fill="#ffffc0"/>
<rect x="430.7424" y="347.07" width="67.44001" height="58.68" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
<text transform="translate(435.7424 368.61263)" fill="black">
<tspan font-family="Times New Roman" font-size="14" font-weight="400" fill="black" x="11.595982" y="12">CCFF</tspan>
</text>
</g>
<g id="Graphic_35886">
<text transform="translate(431.8029 358.01883)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">D</tspan>
</text>
</g>
<g id="Graphic_35885">
<text transform="translate(438.939 387.5559)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">CLK</tspan>
</text>
</g>
<g id="Line_35884">
<line x1="429.6114" y1="362.71" x2="417.9226" y2="362.7238" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35883">
<line x1="429.6114" y1="392.24704" x2="417.9226" y2="392.26084" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35882">
<line x1="511.0022" y1="362.71" x2="499.3134" y2="362.72366" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_35881">
<path d="M 430.7424 388.66704 L 438.3024 392.74704 L 430.7424 396.82704 Z" fill="#ccc"/>
<path d="M 430.7424 388.66704 L 438.3024 392.74704 L 430.7424 396.82704 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Graphic_35880">
<text transform="translate(461.7291 358.01883)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">SCAN_Q</tspan>
</text>
</g>
<g id="Graphic_35879">
<text transform="translate(480.40056 395.11767)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">QN</tspan>
</text>
</g>
<g id="Graphic_35878">
<text transform="translate(468.6826 395.36767)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">Q</tspan>
</text>
</g>
</g>
<g id="Line_35888">
<line x1="387.1996" y1="362.96" x2="417.9226" y2="362.7238" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Group_35889">
<g id="Graphic_35899">
<rect x="593.3428" y="347.07" width="67.44001" height="58.68" fill="#ffffc0"/>
<rect x="593.3428" y="347.07" width="67.44001" height="58.68" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
<text transform="translate(598.3428 368.61263)" fill="black">
<tspan font-family="Times New Roman" font-size="14" font-weight="400" fill="black" x="11.595982" y="12">CCFF</tspan>
</text>
</g>
<g id="Graphic_35898">
<text transform="translate(594.4033 358.01883)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">D</tspan>
</text>
</g>
<g id="Graphic_35897">
<text transform="translate(601.5394 387.5559)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">CLK</tspan>
</text>
</g>
<g id="Line_35896">
<line x1="592.2118" y1="362.71" x2="580.523" y2="362.7238" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35895">
<line x1="592.2118" y1="392.24704" x2="580.523" y2="392.26084" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35894">
<line x1="673.6026" y1="362.71" x2="661.9138" y2="362.72366" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_35893">
<path d="M 593.3428 388.66704 L 600.9028 392.74704 L 593.3428 396.82704 Z" fill="#ccc"/>
<path d="M 593.3428 388.66704 L 600.9028 392.74704 L 593.3428 396.82704 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Graphic_35892">
<text transform="translate(624.32946 358.01883)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">SCAN_Q</tspan>
</text>
</g>
<g id="Graphic_35891">
<text transform="translate(643.0009 395.11767)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">QN</tspan>
</text>
</g>
<g id="Graphic_35890">
<text transform="translate(631.283 395.36767)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">Q</tspan>
</text>
</g>
</g>
<g id="Line_35901">
<line x1="348.32055" y1="406.1741" x2="348.24887" y2="444.6" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35900">
<line x1="365.24055" y1="406" x2="365.24055" y2="432.84513" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35903">
<line x1="471.725" y1="405.73076" x2="471.7103" y2="447.48" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35902">
<line x1="488.645" y1="405.55665" x2="488.645" y2="432.4018" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35905">
<line x1="635.885" y1="406.47363" x2="635.8709" y2="441.72" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35904">
<line x1="652.805" y1="406.29953" x2="652.805" y2="433.14467" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35906">
<line x1="417.9226" y1="393.48" x2="417.9226" y2="419.46915" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35907">
<line x1="294.12" y1="392.51084" x2="294.0757" y2="416.40256" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_35909">
<text transform="translate(189 347.32)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">CONFIG_EN</tspan>
</text>
</g>
<g id="Graphic_35910">
<text transform="translate(188.0328 309.2)" fill="black">
<tspan font-family="Times New Roman" font-size="12" font-style="italic" font-weight="400" fill="black" x="0" y="11">CFG_EN</tspan>
</text>
</g>
<g id="Graphic_35911">
<text transform="translate(318.24 347.07)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">CONFIG_EN</tspan>
</text>
</g>
<g id="Line_35914">
<line x1="210.6998" y1="328.70976" x2="210.6998" y2="346.32" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35915">
<line x1="341.7405" y1="338.41742" x2="341.7405" y2="346.75" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_35917">
<text transform="translate(439.644 347.07)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">CONFIG_EN</tspan>
</text>
</g>
<g id="Line_35916">
<line x1="463.1445" y1="338.12" x2="463.1445" y2="346.75" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_35919">
<text transform="translate(603.804 347.07)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">CONFIG_EN</tspan>
</text>
</g>
<g id="Line_35918">
<line x1="627.3045" y1="334.08" x2="627.3045" y2="346.75" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35920">
<line x1="213.16987" y1="336.11768" x2="627.3045" y2="334.08" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_35921">
<ellipse cx="463.1445" cy="335.1" rx="2.47010548958708" ry="2.52000397038632" fill="black"/>
<ellipse cx="463.1445" cy="335.1" rx="2.47010548958708" ry="2.52000397038632" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Graphic_35922">
<ellipse cx="341.7405" cy="335.39742" rx="2.47010548958708" ry="2.52000397038629" fill="black"/>
<ellipse cx="341.7405" cy="335.39742" rx="2.47010548958708" ry="2.52000397038629" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Graphic_35923">
<ellipse cx="210.6998" cy="336.12983" rx="2.47010548958711" ry="2.5200039703863" fill="black"/>
<ellipse cx="210.6998" cy="336.12983" rx="2.47010548958711" ry="2.5200039703863" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Line_35926">
<line x1="99.34016" y1="472.63047" x2="772.9913" y2="468.9238" stroke="#ff2600" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="4.0,4.0" stroke-width="1"/>
</g>
<g id="Graphic_35925">
<text transform="translate(96.8972 479.89917)" fill="#ff2600">
<tspan font-family="Times New Roman" font-size="12" font-weight="700" fill="#ff2600" x="0" y="11">Configurable Circuits</tspan>
</text>
</g>
<g id="Graphic_35924">
<text transform="translate(93.2 293)" fill="#ff2600">
<tspan font-family="Times New Roman" font-size="12" font-weight="700" fill="#ff2600" x="0" y="11">Configuration Chain</tspan>
</text>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 24 KiB

View File

@ -0,0 +1,462 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:xl="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" viewBox="60.48 304.2 713.0113 195.20894" width="713.0113" height="195.20894">
<defs>
<font-face font-family="Times New Roman" font-size="12" panose-1="2 2 5 3 5 4 5 9 3 4" units-per-em="1000" underline-position="-108.88672" underline-thickness="48.828125" slope="-1361.0827" x-height="430.1758" cap-height="662.1094" ascent="891.1133" descent="-216.3086" font-style="italic" font-weight="400">
<font-face-src>
<font-face-name name="TimesNewRomanPS-ItalicMT"/>
</font-face-src>
</font-face>
<font-face font-family="Times New Roman" font-size="14" panose-1="2 2 5 3 5 4 5 9 3 4" units-per-em="1000" underline-position="-108.88672" underline-thickness="48.828125" slope="-1166.6423" x-height="430.1758" cap-height="662.1094" ascent="891.1133" descent="-216.3086" font-style="italic" font-weight="400">
<font-face-src>
<font-face-name name="TimesNewRomanPS-ItalicMT"/>
</font-face-src>
</font-face>
<font-face font-family="Times New Roman" font-size="14" panose-1="2 2 6 3 5 4 5 2 3 4" units-per-em="1000" underline-position="-108.88672" underline-thickness="48.828125" slope="0" x-height="447.2656" cap-height="662.1094" ascent="891.1133" descent="-216.3086" font-weight="400">
<font-face-src>
<font-face-name name="TimesNewRomanPSMT"/>
</font-face-src>
</font-face>
<font-face font-family="Times New Roman" font-size="9" panose-1="2 2 6 3 5 4 5 2 3 4" units-per-em="1000" underline-position="-108.88672" underline-thickness="48.828125" slope="0" x-height="447.2656" cap-height="662.1094" ascent="891.1133" descent="-216.3086" font-weight="400">
<font-face-src>
<font-face-name name="TimesNewRomanPSMT"/>
</font-face-src>
</font-face>
<font-face font-family="Times New Roman" font-size="12" panose-1="2 2 8 3 7 5 5 2 3 4" units-per-em="1000" underline-position="-108.88672" underline-thickness="95.21484" slope="0" x-height="456.54297" cap-height="662.1094" ascent="891.1133" descent="-216.3086" font-weight="700">
<font-face-src>
<font-face-name name="TimesNewRomanPS-BoldMT"/>
</font-face-src>
</font-face>
</defs>
<metadata> Produced by OmniGraffle 7.18.1\n2021-01-05 01:03:21 +0000</metadata>
<g id="scan_capable" stroke-opacity="1" stroke="none" fill-opacity="1" fill="none" stroke-dasharray="none">
<title>scan_capable</title>
<g id="scan_capable_Layer_1">
<title>Layer 1</title>
<g id="Line_35813">
<line x1="123.76164" y1="420.2495" x2="580.523" y2="418.25" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35816">
<line x1="164.16" y1="392.51084" x2="164.11552" y2="417.301" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_35817">
<text transform="translate(96.08 413.06613)" fill="black">
<tspan font-family="Times New Roman" font-size="12" font-style="italic" font-weight="400" fill="black" x="0" y="11">CLK</tspan>
</text>
</g>
<g id="Graphic_35818">
<text transform="translate(65.48 355.64)" fill="black">
<tspan font-family="Times New Roman" font-size="12" font-style="italic" font-weight="400" fill="black" x="0" y="11">CCFF_HEAD</tspan>
</text>
</g>
<g id="Graphic_35822">
<ellipse cx="294.0701" cy="419.42256" rx="2.47010548958708" ry="2.52000397038635" fill="black"/>
<ellipse cx="294.0701" cy="419.42256" rx="2.47010548958708" ry="2.52000397038635" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Graphic_35823">
<ellipse cx="164.1101" cy="420.321" rx="2.47010548958709" ry="2.52000397038635" fill="black"/>
<ellipse cx="164.1101" cy="420.321" rx="2.47010548958709" ry="2.52000397038635" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Graphic_35839">
<text transform="translate(560.84 352.07)" fill="black">
<tspan font-family="Times New Roman" font-size="14" font-style="italic" font-weight="400" fill="black" x="0" y="12"></tspan>
</text>
</g>
<g id="Graphic_35840">
<ellipse cx="417.7701" cy="419.80915" rx="2.47010548958708" ry="2.52000397038635" fill="black"/>
<ellipse cx="417.7701" cy="419.80915" rx="2.47010548958708" ry="2.52000397038635" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Graphic_35842">
<text transform="translate(680.8373 354.9051)" fill="black">
<tspan font-family="Times New Roman" font-size="12" font-style="italic" font-weight="400" fill="black" x="0" y="11">CCFF_TAIL</tspan>
</text>
</g>
<g id="Line_35843">
<line x1="511.0022" y1="362.7562" x2="553.6052" y2="362.52" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35849">
<line x1="580.523" y1="392.26084" x2="580.523" y2="418.25" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_35851">
<text transform="translate(189.32 452.48)" fill="black">
<tspan font-family="Times New Roman" font-size="12" font-style="italic" font-weight="400" fill="black" x="0" y="11">mem_out[0]</tspan>
</text>
</g>
<g id="Graphic_35852">
<text transform="translate(232.16 433.04)" fill="black">
<tspan font-family="Times New Roman" font-size="12" font-style="italic" font-weight="400" fill="black" x="0" y="11">mem_outb[0]</tspan>
</text>
</g>
<g id="Graphic_35853">
<text transform="translate(318.56 449.6)" fill="black">
<tspan font-family="Times New Roman" font-size="12" font-style="italic" font-weight="400" fill="black" x="0" y="11">mem_out[1]</tspan>
</text>
</g>
<g id="Graphic_35854">
<text transform="translate(362.9025 430.88)" fill="black">
<tspan font-family="Times New Roman" font-size="12" font-style="italic" font-weight="400" fill="black" x="0" y="11">mem_outb[1]</tspan>
</text>
</g>
<g id="Graphic_35856">
<text transform="translate(442.04 452.48)" fill="black">
<tspan font-family="Times New Roman" font-size="12" font-style="italic" font-weight="400" fill="black" x="0" y="11">mem_out[2]</tspan>
</text>
</g>
<g id="Graphic_35855">
<text transform="translate(486.68 430.88)" fill="black">
<tspan font-family="Times New Roman" font-size="12" font-style="italic" font-weight="400" fill="black" x="0" y="11">mem_outb[2]</tspan>
</text>
</g>
<g id="Graphic_35858">
<text transform="translate(606.2 446.72)" fill="black">
<tspan font-family="Times New Roman" font-size="12" font-style="italic" font-weight="400" fill="black" x="0" y="11">mem_out[n]</tspan>
</text>
</g>
<g id="Graphic_35857">
<text transform="translate(650.12 429.8)" fill="black">
<tspan font-family="Times New Roman" font-size="12" font-style="italic" font-weight="400" fill="black" x="0" y="11">mem_outb[n]</tspan>
</text>
</g>
<g id="Group_35863">
<g id="Graphic_35772">
<rect x="176.97979" y="347.32" width="67.44001" height="58.68" fill="#ffffc0"/>
<rect x="176.97979" y="347.32" width="67.44001" height="58.68" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
<text transform="translate(181.97979 368.86263)" fill="black">
<tspan font-family="Times New Roman" font-size="14" font-weight="400" fill="black" x="11.595982" y="12">CCFF</tspan>
</text>
</g>
<g id="Graphic_35775">
<text transform="translate(178.04028 358.26883)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">D</tspan>
</text>
</g>
<g id="Graphic_35776">
<text transform="translate(185.1764 387.8059)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">CLK</tspan>
</text>
</g>
<g id="Line_35778">
<line x1="175.8488" y1="362.96" x2="164.16" y2="362.9738" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35779">
<line x1="175.8488" y1="392.49704" x2="164.16" y2="392.51084" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35781">
<line x1="257.2396" y1="362.96" x2="245.5508" y2="362.97366" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_35785">
<path d="M 176.97979 388.91704 L 184.53979 392.99704 L 176.97979 397.07704 Z" fill="#ccc"/>
<path d="M 176.97979 388.91704 L 184.53979 392.99704 L 176.97979 397.07704 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Graphic_35786">
<text transform="translate(207.96647 358.26883)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">SCAN_Q</tspan>
</text>
</g>
<g id="Graphic_35859">
<text transform="translate(226.63794 395.36767)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">QN</tspan>
</text>
</g>
<g id="Graphic_35860">
<text transform="translate(214.92 395.61767)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">Q</tspan>
</text>
</g>
</g>
<g id="Line_35861">
<line x1="218.88" y1="405.90486" x2="218.96188" y2="447.48" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35862">
<line x1="235.8" y1="406" x2="235.8" y2="432.84513" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Group_35864">
<g id="Graphic_35874">
<rect x="306.9398" y="347.32" width="67.44001" height="58.68" fill="#ffffc0"/>
<rect x="306.9398" y="347.32" width="67.44001" height="58.68" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
<text transform="translate(311.9398 368.86263)" fill="black">
<tspan font-family="Times New Roman" font-size="14" font-weight="400" fill="black" x="11.595982" y="12">CCFF</tspan>
</text>
</g>
<g id="Graphic_35873">
<text transform="translate(308.00027 358.26883)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">D</tspan>
</text>
</g>
<g id="Graphic_35872">
<text transform="translate(315.1364 387.8059)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">CLK</tspan>
</text>
</g>
<g id="Line_35871">
<line x1="305.8088" y1="362.96" x2="294.12" y2="362.9738" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35870">
<line x1="305.8088" y1="392.49704" x2="294.12" y2="392.51084" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35869">
<line x1="387.1996" y1="362.96" x2="375.5108" y2="362.97366" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_35868">
<path d="M 306.9398 388.91704 L 314.4998 392.99704 L 306.9398 397.07704 Z" fill="#ccc"/>
<path d="M 306.9398 388.91704 L 314.4998 392.99704 L 306.9398 397.07704 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Graphic_35867">
<text transform="translate(337.92647 358.26883)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">SCAN_Q</tspan>
</text>
</g>
<g id="Graphic_35866">
<text transform="translate(356.59794 395.36767)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">QN</tspan>
</text>
</g>
<g id="Graphic_35865">
<text transform="translate(344.88 395.61767)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">Q</tspan>
</text>
</g>
</g>
<g id="Line_35875">
<line x1="257.2396" y1="362.96" x2="294.12" y2="362.9738" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Group_35877">
<g id="Graphic_35887">
<rect x="430.7424" y="347.07" width="67.44001" height="58.68" fill="#ffffc0"/>
<rect x="430.7424" y="347.07" width="67.44001" height="58.68" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
<text transform="translate(435.7424 368.61263)" fill="black">
<tspan font-family="Times New Roman" font-size="14" font-weight="400" fill="black" x="11.595982" y="12">CCFF</tspan>
</text>
</g>
<g id="Graphic_35886">
<text transform="translate(431.8029 358.01883)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">D</tspan>
</text>
</g>
<g id="Graphic_35885">
<text transform="translate(438.939 387.5559)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">CLK</tspan>
</text>
</g>
<g id="Line_35884">
<line x1="429.6114" y1="362.71" x2="417.9226" y2="362.7238" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35883">
<line x1="429.6114" y1="392.24704" x2="417.9226" y2="392.26084" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35882">
<line x1="511.0022" y1="362.71" x2="499.3134" y2="362.72366" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_35881">
<path d="M 430.7424 388.66704 L 438.3024 392.74704 L 430.7424 396.82704 Z" fill="#ccc"/>
<path d="M 430.7424 388.66704 L 438.3024 392.74704 L 430.7424 396.82704 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Graphic_35880">
<text transform="translate(461.7291 358.01883)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">SCAN_Q</tspan>
</text>
</g>
<g id="Graphic_35879">
<text transform="translate(480.40056 395.11767)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">QN</tspan>
</text>
</g>
<g id="Graphic_35878">
<text transform="translate(468.6826 395.36767)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">Q</tspan>
</text>
</g>
</g>
<g id="Line_35888">
<line x1="387.1996" y1="362.96" x2="417.9226" y2="362.7238" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Group_35889">
<g id="Graphic_35899">
<rect x="593.3428" y="347.07" width="67.44001" height="58.68" fill="#ffffc0"/>
<rect x="593.3428" y="347.07" width="67.44001" height="58.68" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
<text transform="translate(598.3428 368.61263)" fill="black">
<tspan font-family="Times New Roman" font-size="14" font-weight="400" fill="black" x="11.595982" y="12">CCFF</tspan>
</text>
</g>
<g id="Graphic_35898">
<text transform="translate(594.4033 358.01883)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">D</tspan>
</text>
</g>
<g id="Graphic_35897">
<text transform="translate(601.5394 387.5559)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">CLK</tspan>
</text>
</g>
<g id="Line_35896">
<line x1="592.2118" y1="362.71" x2="580.523" y2="362.7238" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35895">
<line x1="592.2118" y1="392.24704" x2="580.523" y2="392.26084" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35894">
<line x1="673.6026" y1="362.71" x2="661.9138" y2="362.72366" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_35893">
<path d="M 593.3428 388.66704 L 600.9028 392.74704 L 593.3428 396.82704 Z" fill="#ccc"/>
<path d="M 593.3428 388.66704 L 600.9028 392.74704 L 593.3428 396.82704 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Graphic_35892">
<text transform="translate(624.32946 358.01883)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">SCAN_Q</tspan>
</text>
</g>
<g id="Graphic_35891">
<text transform="translate(643.0009 395.11767)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">QN</tspan>
</text>
</g>
<g id="Graphic_35890">
<text transform="translate(631.283 395.36767)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">Q</tspan>
</text>
</g>
</g>
<g id="Line_35901">
<line x1="348.32055" y1="406.1741" x2="348.24887" y2="444.6" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35900">
<line x1="365.24055" y1="406" x2="365.24055" y2="432.84513" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35903">
<line x1="471.725" y1="405.73076" x2="471.7103" y2="447.48" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35902">
<line x1="488.645" y1="405.55665" x2="488.645" y2="432.4018" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35905">
<line x1="635.885" y1="406.47363" x2="635.8709" y2="441.72" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35904">
<line x1="652.805" y1="406.29953" x2="652.805" y2="433.14467" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35906">
<line x1="417.9226" y1="393.48" x2="417.9226" y2="419.46915" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35907">
<line x1="294.12" y1="392.51084" x2="294.0757" y2="416.40256" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_35909">
<text transform="translate(189 347.32)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">CONFIG_EN</tspan>
</text>
</g>
<g id="Graphic_35910">
<text transform="translate(188.0328 309.2)" fill="black">
<tspan font-family="Times New Roman" font-size="12" font-style="italic" font-weight="400" fill="black" x="0" y="11">CFG_EN</tspan>
</text>
</g>
<g id="Graphic_35911">
<text transform="translate(318.24 347.07)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">CONFIG_EN</tspan>
</text>
</g>
<g id="Line_35914">
<line x1="210.6998" y1="328.70976" x2="210.6998" y2="346.32" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35915">
<line x1="341.7405" y1="338.41742" x2="341.7405" y2="346.75" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_35917">
<text transform="translate(439.644 347.07)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">CONFIG_EN</tspan>
</text>
</g>
<g id="Line_35916">
<line x1="463.1445" y1="338.12" x2="463.1445" y2="346.75" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_35919">
<text transform="translate(603.804 347.07)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">CONFIG_EN</tspan>
</text>
</g>
<g id="Line_35918">
<line x1="627.3045" y1="334.08" x2="627.3045" y2="346.75" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35920">
<line x1="213.16987" y1="336.11768" x2="627.3045" y2="334.08" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_35921">
<ellipse cx="463.1445" cy="335.1" rx="2.47010548958708" ry="2.52000397038632" fill="black"/>
<ellipse cx="463.1445" cy="335.1" rx="2.47010548958708" ry="2.52000397038632" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Graphic_35922">
<ellipse cx="341.7405" cy="335.39742" rx="2.47010548958708" ry="2.52000397038629" fill="black"/>
<ellipse cx="341.7405" cy="335.39742" rx="2.47010548958708" ry="2.52000397038629" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Graphic_35923">
<ellipse cx="210.6998" cy="336.12983" rx="2.47010548958711" ry="2.5200039703863" fill="black"/>
<ellipse cx="210.6998" cy="336.12983" rx="2.47010548958711" ry="2.5200039703863" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Line_35926">
<line x1="99.34016" y1="472.63047" x2="772.9913" y2="468.9238" stroke="#ff2600" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="4.0,4.0" stroke-width="1"/>
</g>
<g id="Graphic_35925">
<text transform="translate(96.8972 479.89917)" fill="#ff2600">
<tspan font-family="Times New Roman" font-size="12" font-weight="700" fill="#ff2600" x="0" y="11">Configurable Circuits</tspan>
</text>
</g>
<g id="Graphic_35924">
<text transform="translate(71.011316 309.2)" fill="#ff2600">
<tspan font-family="Times New Roman" font-size="12" font-weight="700" fill="#ff2600" x="0" y="11">Configuration Chain</tspan>
</text>
</g>
<g id="Graphic_35927">
<text transform="translate(177.84 372.6)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">SI</tspan>
</text>
</g>
<g id="Line_35928">
<path d="M 175.8488 377.29115 L 164.16 377.375 L 164.16 362.9738" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_35929">
<ellipse cx="164.16" cy="363.2949" rx="2.4701054895871" ry="2.52000397038626" fill="black"/>
<ellipse cx="164.16" cy="363.2949" rx="2.4701054895871" ry="2.52000397038626" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Line_35931">
<line x1="139.14015" y1="362.6472" x2="164.07007" y2="362.49023" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_35934">
<text transform="translate(307.8 372.6)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">SI</tspan>
</text>
</g>
<g id="Line_35933">
<path d="M 305.8088 377.29115 L 294.12 377.375 L 294.12 362.9738" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_35932">
<ellipse cx="294.12" cy="363.2949" rx="2.47010548958708" ry="2.52000397038629" fill="black"/>
<ellipse cx="294.12" cy="363.2949" rx="2.47010548958708" ry="2.52000397038629" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Graphic_35937">
<text transform="translate(431.6026 372.1462)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">SI</tspan>
</text>
</g>
<g id="Line_35936">
<path d="M 429.6114 376.83735 L 417.9226 376.9212 L 417.9226 362.52" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_35935">
<ellipse cx="417.9226" cy="362.8411" rx="2.47010548958708" ry="2.52000397038635" fill="black"/>
<ellipse cx="417.9226" cy="362.8411" rx="2.47010548958708" ry="2.52000397038635" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Graphic_35940">
<text transform="translate(594.203 372.1462)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">SI</tspan>
</text>
</g>
<g id="Line_35939">
<path d="M 592.2118 376.83735 L 580.523 376.9212 L 580.523 362.52" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_35938">
<ellipse cx="580.523" cy="362.8411" rx="2.47010548958711" ry="2.52000397038635" fill="black"/>
<ellipse cx="580.523" cy="362.8411" rx="2.47010548958711" ry="2.52000397038635" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

View File

@ -10,7 +10,10 @@ General organization is as follows
<openfpga_simulation_setting>
<clock_setting>
<operating frequency="<int>|<string>" num_cycles="<int>|<string>" slack="<float>"/>
<operating frequency="<int>|<string>" num_cycles="<int>|<string>" slack="<float>">
<clock name="<string>" port="<string>" frequency="<float>"/>
...
</operating>
<programming frequency="<int>"/>
</clock_setting>
<simulator_option>
@ -54,13 +57,17 @@ We should the full syntax in the code block below and then provide details on ea
.. code-block:: xml
<clock_setting>
<operating frequency="<float>|<string>" num_cycles="<int>|<string>" slack="<float>"/>
<operating frequency="<float>|<string>" num_cycles="<int>|<string>" slack="<float>">
<clock name="<string>" port="<string>" frequency="<float>"/>
...
</operating>
<programming frequency="<float>"/>
</clock_setting>
Operating clock setting
^^^^^^^^^^^^^^^^^^^^^^^
Operating clocks are defined under the XML node ``<operating>``
To support FPGA fabrics with multiple clocks, OpenFPGA allows users to define a default operating clock frequency as well as a set of clock ports using different frequencies.
.. option:: <operating frequency="<float>|<string>" num_cycles="<int>|<string>" slack="<float>"/>
@ -70,6 +77,8 @@ Operating clocks are defined under the XML node ``<operating>``
This is very useful to validate the maximum operating frequency for users' implementations
In such case, the value of this attribute should be a reserved word ``auto``.
.. note:: The frequency is considered as a default operating clock frequency, which will be used when a clock pin of a multi-clock FPGA fabric lacks explicit clock definition.
- ``num_cycles="<int>|<string>"``
can be either ``auto`` or an integer. When set to ``auto``, OpenFPGA will infer the number of clock cycles from the average/median of all the signal activities.
When set to an integer, OpenFPGA will use the given number of clock cycles in HDL and SPICE simulations.
@ -86,6 +95,22 @@ Operating clocks are defined under the XML node ``<operating>``
.. warning:: Avoid to use a negative slack! This may cause your simulation to fail!
.. option:: <clock name="<string>" port="<string>" frequency="<float>"/>
- ``name="<string>``
Specify a unique name for a clock signal. The name will be used in generating clock stimulus in testbenches.
- ``port="<string>``
Specify the clock port which the clock signal should be applied to. The clock port must be a valid clock port defined in OpenFPGA architecture description. Explicit index is required, e.g., ``clk[1:1]``. Otherwise, default index ``0`` will be considered, e.g., ``clk`` will be translated as ``clk[0:0]``.
.. note:: You can define clock ports either through the tile annotation in :ref:`annotate_vpr_arch_physical_tile_annotation` or :ref:`circuit_library_circuit_port`.
- ``frequency="<float>``
Specify frequency of a clock signal in the unit of ``[Hz]``
.. warning:: Currently, we only allow operating clocks to be overwritten!!!
Programming clock setting
^^^^^^^^^^^^^^^^^^^^^^^^^
Programming clocks are defined under the XML node ``<programming>``

View File

@ -0,0 +1,14 @@
File Formats
------------
OpenFPGA widely uses XML format for interchangable files
.. _file_formats:
File formats
.. toctree::
:maxdepth: 2
pin_constraints_file

View File

@ -0,0 +1,25 @@
.. _file_format_pin_constraints_file:
Pin Constraints File
--------------------
The *Pin Constraints File* (PCF) aims to create pin binding between an implementation and an FPGA fabric
An example of design constraints is shown as follows.
.. code-block:: xml
<pin_constraints>
<set_io pin="clk[0]" net="clk0"/>
<set_io pin="clk[1]" net="clk1"/>
<set_io pin="clk[2]" net="OPEN"/>
<set_io pin="clk[3]" net="OPEN"/>
</pin_constraints>
.. option:: pin="<string>"
The pin name of the FPGA fabric to be constrained, which should be a valid pin defined in OpenFPGA architecture description. Explicit index is required, e.g., ``clk[1:1]``. Otherwise, default index ``0`` will be considered, e.g., ``clk`` will be translated as ``clk[0:0]``.
.. option:: net="<string>"
The net name of the pin to be mapped, which should be consistent with net definition in your ``.blif`` file. The reserved word ``OPEN`` means that no net should be mapped to a given pin. Please ensure that it is not conflicted with any net names in your ``.blif`` file.

View File

@ -12,3 +12,5 @@ FPGA-Bitstream can generate two types of bitstreams:
generic_bitstream
fabric_dependent_bitstream
repack_design_constraints

View File

@ -0,0 +1,29 @@
.. _fpga_bitstream_repack_design_constraints:
Repack Design Constraints
-------------------------
An example of design constraints is shown as follows.
.. code-block:: xml
<repack_design_constraints>
<pin_constraint pb_type="clb" pin="clk[0]" net="clk0"/>
<pin_constraint pb_type="clb" pin="clk[1]" net="clk1"/>
<pin_constraint pb_type="clb" pin="clk[2]" net="OPEN"/>
<pin_constraint pb_type="clb" pin="clk[3]" net="OPEN"/>
</repack_design_constraints>
.. option:: pb_type="<string>"
The pb_type name to be constrained, which should be consistent with VPR's architecture description.
.. option:: pin="<string>"
The pin name of the ``pb_type`` to be constrained, which should be consistent with VPR's architecture description.
.. option:: net="<string>"
The net name of the pin to be mapped, which should be consistent with net definition in your ``.blif`` file. The reserved word ``OPEN`` means that no net should be mapped to a given pin. Please ensure that it is not conflicted with any net names in your ``.blif`` file.
.. warning:: Design constraints is a feature for power-users. It may cause repack to fail. It is users's responsibility to ensure proper design constraints

View File

@ -16,3 +16,5 @@
fpga_bitstream/index
file_formats/index

View File

@ -6,11 +6,28 @@ FPGA-Bitstream
repack
~~~~~~
Repack the netlist to physical pbs
Repack the netlist to physical pbs
Repack is an essential procedure before building a bitstream, which aims to packing each programmable blocks by considering **only** the physical modes.
Repack's functionality are in the following aspects:
.. note:: This must be done before bitstream generator and testbench generation. Strongly recommend it is done after all the fix-up have been applied
- It annotates the net mapping results from operating modes (considered by VPR) to the physical modes (considered by OpenFPGA)
- It re-routes all the nets by considering the programmable interconnects in physical modes **only**.
.. note:: This must be done before bitstream generator and testbench generation. Strongly recommend it is done after all the fix-up have been applied
.. option:: --design_constraints
Apply design constraints from an external file.
Normally, repack takes the net mapping from VPR packing and routing results.
Alternatively, repack can accept the design constraints, in particular, net remapping, from an XML-based design constraint description.
See details in :ref:`fpga_bitstream_repack_design_constraints`.
.. warning:: Design constraints are designed to help repacker to identify which clock net to be mapped to which pin, so that multi-clock benchmarks can be correctly implemented, in the case that VPR may not have sufficient vision on clock net mapping. **Try not to use design constraints to remap any other types of nets!!!**
- ``--verbose`` Show verbose log
.. option:: --verbose
Show verbose log
build_architecture_bitstream
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -33,6 +33,8 @@ write_verilog_testbench
- ``--reference_benchmark_file_path`` Must specify the reference benchmark Verilog file if you want to output any testbenches
- ``--pin_constraints_file`` specify the *Pin Constraints File* (PCF) if you want to custom stimulus in testbenches. Strongly recommend for multi-clock simulations. See detailed file format about :ref:`file_format_pin_constraints_file`.
- ``--fast_configuration`` Enable fast configuration phase for the top-level testbench in order to reduce runtime of simulations. It is applicable to configuration chain, memory bank and frame-based configuration protocols. For configuration chain, when enabled, the zeros at the head of the bitstream will be skipped. For memory bank and frame-based, when enabled, all the zero configuration bits will be skipped. So ensure that your memory cells can be correctly reset to zero with a reset signal.
.. note:: If both reset and set ports are defined in the circuit modeling for programming, OpenFPGA will pick the one that will bring largest benefit in speeding up configuration.

View File

@ -4,4 +4,6 @@ add_subdirectory(libopenfpgashell)
add_subdirectory(libarchopenfpga)
add_subdirectory(libopenfpgautil)
add_subdirectory(libfabrickey)
add_subdirectory(librepackdc)
add_subdirectory(libfpgabitstream)
add_subdirectory(libpcf)

View File

@ -290,17 +290,35 @@ size_t check_ccff_circuit_model_ports(const CircuitLibrary& circuit_lib,
VTR_ASSERT(CIRCUIT_MODEL_CCFF == circuit_lib.model_type(circuit_model));
/* Check if we have D, Set and Reset */
/* We can have either 1 input which is D or 2 inputs which are D and scan input */
size_t num_input_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true).size();
if ((1 != num_input_ports) && (2 != num_input_ports)) {
VTR_LOG_ERROR("Configuration flip-flop '%s' must have either 1 or 2 %s ports!\n\tAmong which:\n\t\tthe first input is a regular input (e.g., D)\n\t\tand the other could be scan-chain input (e.g., SI)\n",
circuit_lib.model_name(circuit_model).c_str(),
CIRCUIT_MODEL_PORT_TYPE_STRING[size_t(CIRCUIT_MODEL_PORT_INPUT)]);
num_err++;
}
num_err += check_one_circuit_model_port_type_and_size_required(circuit_lib, circuit_model,
CIRCUIT_MODEL_PORT_INPUT,
1, 1, false);
num_input_ports, 1, false);
/* Check if we have a clock */
num_err += check_one_circuit_model_port_type_and_size_required(circuit_lib, circuit_model,
CIRCUIT_MODEL_PORT_CLOCK,
1, 1, true);
/* Check if we have 1 or 2 outputs */
/* Check if we have 1 or 2 or 3 outputs */
size_t num_output_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, true).size();
if ((1 != num_output_ports)
&& (2 != num_output_ports)
&& (3 != num_output_ports)) {
VTR_LOG_ERROR("Configuration flip-flop '%s' must have either 1 or 2 or 3 %s ports!\n\tAmong which:\n\t\tthe first port is the manadatory regular data output (e.g., Q) and \n\t\tthe second port could be the inverted data output which can optionally be enabled by configure-enable signal (e.g., QN or cgf_en_QN) and \n\t\tthe third port could be the data output which can optionally be enabled by configure-enable signal (e.g., cgf_en_Q)\n",
circuit_lib.model_name(circuit_model).c_str(),
CIRCUIT_MODEL_PORT_TYPE_STRING[size_t(CIRCUIT_MODEL_PORT_OUTPUT)]);
num_err++;
}
num_err += check_one_circuit_model_port_type_and_size_required(circuit_lib, circuit_model,
CIRCUIT_MODEL_PORT_OUTPUT,
num_output_ports, 1, false);

View File

@ -12,6 +12,9 @@
/* Headers from vtr util library */
#include "vtr_assert.h"
/* Headers from openfpga util library */
#include "openfpga_port_parser.h"
/* Headers from libarchfpga */
#include "arch_error.h"
#include "read_xml_util.h"
@ -32,6 +35,33 @@ e_sim_accuracy_type string_to_sim_accuracy_type(const std::string& type_string)
return NUM_SIM_ACCURACY_TYPES;
}
/********************************************************************
* Parse XML codes of a <clock> line to an object of simulation setting
*******************************************************************/
static
void read_xml_operating_clock_override_setting(pugi::xml_node& xml_clock_override_setting,
const pugiutil::loc_data& loc_data,
openfpga::SimulationSetting& sim_setting) {
std::string clock_name = get_attribute(xml_clock_override_setting, "name", loc_data).as_string();
/* Create a new clock override object in the sim_setting object with the given name */
SimulationClockId clock_id = sim_setting.create_clock(clock_name);
/* Report if the clock creation failed, this is due to a conflicts in naming*/
if (false == sim_setting.valid_clock_id(clock_id)) {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_clock_override_setting),
"Fail to create simulation clock '%s', it may share the same name as other simulation clock definition!\n",
clock_name.c_str());
}
/* Parse port information */
openfpga::PortParser clock_port_parser(get_attribute(xml_clock_override_setting, "port", loc_data).as_string());
sim_setting.set_clock_port(clock_id, clock_port_parser.port());
/* Parse frequency information */
sim_setting.set_clock_frequency(clock_id, get_attribute(xml_clock_override_setting, "frequency", loc_data).as_float(0.));
}
/********************************************************************
* Parse XML codes of a <clock_setting> to an object of simulation setting
*******************************************************************/
@ -42,7 +72,7 @@ void read_xml_clock_setting(pugi::xml_node& xml_clock_setting,
/* Parse operating clock setting */
pugi::xml_node xml_operating_clock_setting = get_single_child(xml_clock_setting, "operating", loc_data);
sim_setting.set_operating_clock_frequency(get_attribute(xml_operating_clock_setting, "frequency", loc_data).as_float(0.));
sim_setting.set_default_operating_clock_frequency(get_attribute(xml_operating_clock_setting, "frequency", loc_data).as_float(0.));
/* Parse number of clock cycles to be used in simulation
* Valid keywords is "auto" or other integer larger than 0
@ -59,6 +89,15 @@ void read_xml_clock_setting(pugi::xml_node& xml_clock_setting,
sim_setting.set_operating_clock_frequency_slack(get_attribute(xml_operating_clock_setting, "slack", loc_data).as_float(0.));
/* Iterate over multiple operating clock settings and parse one by one */
for (pugi::xml_node xml_clock : xml_operating_clock_setting.children()) {
/* Error out if the XML child has an invalid name! */
if (xml_clock.name() != std::string("clock")) {
bad_tag(xml_clock, loc_data, xml_operating_clock_setting, {"clock"});
}
read_xml_operating_clock_override_setting(xml_clock, loc_data, sim_setting);
}
/* Parse programming clock setting */
pugi::xml_node xml_programming_clock_setting = get_single_child(xml_clock_setting, "programming", loc_data);

View File

@ -30,25 +30,12 @@ static
void read_xml_tile_global_port_annotation(pugi::xml_node& xml_tile,
const pugiutil::loc_data& loc_data,
openfpga::TileAnnotation& tile_annotation) {
/* We have two mandatory XML attributes
* 1. name of the port
* 2. name of the tile and ports in the format of <tile_name>.<tile_port_name>
/* We have mandatory XML attributes:
* - name of the port
*/
const std::string& name_attr = get_attribute(xml_tile, "name", loc_data).as_string();
const std::string& tile_port_name_attr = get_attribute(xml_tile, "tile_port", loc_data).as_string();
/* Extract the tile name */
openfpga::StringToken tokenizer(tile_port_name_attr);
std::vector<std::string> tile_port_tokens = tokenizer.split('.');
if (2 != tile_port_tokens.size()) {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_tile),
"Invalid tile_port attribute '%s'! Valid format is <tile_name>.<port_name>\n",
tile_port_name_attr.c_str());
}
/* Extract the tile port information */
openfpga::PortParser tile_port_parser(tile_port_tokens[1]);
TileGlobalPortId tile_global_port_id = tile_annotation.create_global_port(name_attr, tile_port_tokens[0], tile_port_parser.port());
TileGlobalPortId tile_global_port_id = tile_annotation.create_global_port(name_attr);
/* Report any duplicated port names */
if (TileGlobalPortId::INVALID() == tile_global_port_id) {
@ -57,6 +44,39 @@ void read_xml_tile_global_port_annotation(pugi::xml_node& xml_tile,
name_attr.c_str());
}
/* Iterate over the children under this node,
* each child should be named after <pb_type>
*/
for (pugi::xml_node xml_tile_port : xml_tile.children()) {
/* Error out if the XML child has an invalid name! */
if (xml_tile_port.name() != std::string("tile")) {
bad_tag(xml_tile_port, loc_data, xml_tile, {"tile"});
}
/* Parse the name of the tiles and ports */
const std::string& tile_name_attr = get_attribute(xml_tile_port, "name", loc_data).as_string();
const std::string& port_name_attr = get_attribute(xml_tile_port, "port", loc_data).as_string();
/* Extract the tile port information */
openfpga::PortParser tile_port_parser(port_name_attr);
/* Parse tile coordinates */
vtr::Point<size_t> tile_coord(get_attribute(xml_tile_port, "x", loc_data, pugiutil::ReqOpt::OPTIONAL).as_int(-1),
get_attribute(xml_tile_port, "y", loc_data, pugiutil::ReqOpt::OPTIONAL).as_int(-1));
/* Add tile port information */
tile_annotation.add_global_port_tile_information(tile_global_port_id,
tile_name_attr,
tile_port_parser.port(),
tile_coord);
}
/* Check: Must have at least one global port tile information */
if (true == tile_annotation.global_port_tile_names(tile_global_port_id).empty()) {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_tile),
"Invalid tile annotation for global port '%s'! At least 1 tile port definition is expected!\n",
name_attr.c_str());
}
/* Get is_clock attributes */
tile_annotation.set_global_port_is_clock(tile_global_port_id, get_attribute(xml_tile, "is_clock", loc_data, pugiutil::ReqOpt::OPTIONAL).as_bool(false));
@ -81,7 +101,7 @@ void read_xml_tile_global_port_annotation(pugi::xml_node& xml_tile,
* Top function to parse XML description about tile annotation
*******************************************************************/
openfpga::TileAnnotation read_xml_tile_annotations(pugi::xml_node& Node,
const pugiutil::loc_data& loc_data) {
const pugiutil::loc_data& loc_data) {
openfpga::TileAnnotation tile_annotations;
/* Parse configuration protocol root node */

View File

@ -9,6 +9,13 @@ namespace openfpga {
* Member functions for class SimulationSetting
***********************************************************************/
/************************************************************************
* Public Accessors : aggregates
***********************************************************************/
SimulationSetting::simulation_clock_range SimulationSetting::clocks() const {
return vtr::make_range(clock_ids_.begin(), clock_ids_.end());
}
/************************************************************************
* Constructors
***********************************************************************/
@ -19,12 +26,31 @@ SimulationSetting::SimulationSetting() {
/************************************************************************
* Public Accessors
***********************************************************************/
float SimulationSetting::operating_clock_frequency() const {
return clock_frequencies_.x();
float SimulationSetting::default_operating_clock_frequency() const {
return default_clock_frequencies_.x();
}
float SimulationSetting::programming_clock_frequency() const {
return clock_frequencies_.y();
return default_clock_frequencies_.y();
}
size_t SimulationSetting::num_simulation_clock_cycles() const {
return clock_ids_.size();
}
std::string SimulationSetting::clock_name(const SimulationClockId& clock_id) const {
VTR_ASSERT(valid_clock_id(clock_id));
return clock_names_[clock_id];
}
BasicPort SimulationSetting::clock_port(const SimulationClockId& clock_id) const {
VTR_ASSERT(valid_clock_id(clock_id));
return clock_ports_[clock_id];
}
float SimulationSetting::clock_frequency(const SimulationClockId& clock_id) const {
VTR_ASSERT(valid_clock_id(clock_id));
return clock_frequencies_[clock_id];
}
bool SimulationSetting::auto_select_num_clock_cycles() const {
@ -110,12 +136,44 @@ float SimulationSetting::stimuli_input_slew(const e_sim_signal_type& signal_type
/************************************************************************
* Public Mutators
***********************************************************************/
void SimulationSetting::set_operating_clock_frequency(const float& clock_freq) {
clock_frequencies_.set_x(clock_freq);
void SimulationSetting::set_default_operating_clock_frequency(const float& clock_freq) {
default_clock_frequencies_.set_x(clock_freq);
}
void SimulationSetting::set_programming_clock_frequency(const float& clock_freq) {
clock_frequencies_.set_y(clock_freq);
default_clock_frequencies_.set_y(clock_freq);
}
SimulationClockId SimulationSetting::create_clock(const std::string& name) {
/* Ensure a unique name for the clock definition */
std::map<std::string, SimulationClockId>::iterator it = clock_name2ids_.find(name);
if (it != clock_name2ids_.end()) {
return SimulationClockId::INVALID();
}
/* This is a legal name. we can create a new id */
SimulationClockId clock_id = SimulationClockId(clock_ids_.size());
clock_ids_.push_back(clock_id);
clock_names_.push_back(name);
clock_ports_.emplace_back();
clock_frequencies_.push_back(0.);
/* Register in the name-to-id map */
clock_name2ids_[name] = clock_id;
return clock_id;
}
void SimulationSetting::set_clock_port(const SimulationClockId& clock_id,
const BasicPort& port) {
VTR_ASSERT(valid_clock_id(clock_id));
clock_ports_[clock_id] = port;
}
void SimulationSetting::set_clock_frequency(const SimulationClockId& clock_id,
const float& frequency) {
VTR_ASSERT(valid_clock_id(clock_id));
clock_frequencies_[clock_id] = frequency;
}
void SimulationSetting::set_num_clock_cycles(const size_t& num_clk_cycles) {
@ -212,4 +270,9 @@ bool SimulationSetting::valid_signal_threshold(const float& threshold) const {
return (0. < threshold) && (threshold < 1);
}
bool SimulationSetting::valid_clock_id(const SimulationClockId& clock_id) const {
return ( size_t(clock_id) < clock_ids_.size() ) && ( clock_id == clock_ids_[clock_id] );
}
} /* namespace openfpga ends */

View File

@ -7,9 +7,15 @@
*******************************************************************/
#include <string>
#include <array>
#include <map>
#include "vtr_vector.h"
#include "vtr_geometry.h"
#include "openfpga_port.h"
#include "simulation_setting_fwd.h"
/********************************************************************
* Types of signal type in measurement and stimuli
*******************************************************************/
@ -48,11 +54,21 @@ namespace openfpga {
*
*******************************************************************/
class SimulationSetting {
public: /* Types */
typedef vtr::vector<SimulationClockId, SimulationClockId>::const_iterator simulation_clock_iterator;
/* Create range */
typedef vtr::Range<simulation_clock_iterator> simulation_clock_range;
public: /* Constructors */
SimulationSetting();
public: /* Accessors: aggregates */
simulation_clock_range clocks() const;
public: /* Public Accessors */
float operating_clock_frequency() const;
float default_operating_clock_frequency() const;
float programming_clock_frequency() const;
size_t num_simulation_clock_cycles() const;
std::string clock_name(const SimulationClockId& clock_id) const;
BasicPort clock_port(const SimulationClockId& clock_id) const;
float clock_frequency(const SimulationClockId& clock_id) const;
bool auto_select_num_clock_cycles() const;
size_t num_clock_cycles() const;
float operating_clock_frequency_slack() const;
@ -73,8 +89,19 @@ class SimulationSetting {
e_sim_accuracy_type stimuli_input_slew_type(const e_sim_signal_type& signal_type) const;
float stimuli_input_slew(const e_sim_signal_type& signal_type) const;
public: /* Public Mutators */
void set_operating_clock_frequency(const float& clock_freq);
void set_default_operating_clock_frequency(const float& clock_freq);
void set_programming_clock_frequency(const float& clock_freq);
/* Add a new simulation clock with
* - a given name
* - a given port description
* - a default zero frequency which can be overwritten by
* the operating_clock_frequency()
*/
SimulationClockId create_clock(const std::string& name);
void set_clock_port(const SimulationClockId& clock_id,
const BasicPort& port);
void set_clock_frequency(const SimulationClockId& clock_id,
const float& frequency);
void set_num_clock_cycles(const size_t& num_clk_cycles);
void set_operating_clock_frequency_slack(const float& op_clk_freq_slack);
void set_simulation_temperature(const float& sim_temp);
@ -102,13 +129,30 @@ class SimulationSetting {
const float& input_slew);
public: /* Public Validators */
bool valid_signal_threshold(const float& threshold) const;
bool valid_clock_id(const SimulationClockId& clock_id) const;
private: /* Internal data */
/* Operating clock frequency: the clock frequency to be applied to users' implemetation on FPGA
/* Operating clock frequency: the default clock frequency to be applied to users' implemetation on FPGA
* This will be stored in the x() part of vtr::Point
* Programming clock frequency: the clock frequency to be applied to configuration protocol of FPGA
* This will be stored in the y() part of vtr::Point
*/
vtr::Point<float> clock_frequencies_;
vtr::Point<float> default_clock_frequencies_;
/* Multiple simulation clocks with detailed information
* Each clock has
* - a unique id
* - a unique name
* - a unique port definition which is supposed
* to match the clock port definition in OpenFPGA documentation
* - a frequency which is only applicable to this clock name
*/
vtr::vector<SimulationClockId, SimulationClockId> clock_ids_;
vtr::vector<SimulationClockId, std::string> clock_names_;
vtr::vector<SimulationClockId, BasicPort> clock_ports_;
vtr::vector<SimulationClockId, float> clock_frequencies_;
/* Fast name-to-id lookup */
std::map<std::string, SimulationClockId> clock_name2ids_;
/* Number of clock cycles to be used in simulation
* If the value is 0, the clock cycles can be automatically

View File

@ -0,0 +1,22 @@
/************************************************************************
* A header file for SimulationSetting class, including critical data declaration
* Please include this file only for using any SimulationSetting data structure
* Refer to simulation_setting.h for more details
***********************************************************************/
/************************************************************************
* Create strong id for Simulation Clock to avoid illegal type casting
***********************************************************************/
#ifndef SIMULATION_SETTING_FWD_H
#define SIMULATION_SETTING_FWD_H
#include "vtr_strong_id.h"
struct simulation_clock_id_tag;
typedef vtr::StrongId<simulation_clock_id_tag> SimulationClockId;
/* Short declaration of class */
class SimulationSetting;
#endif

View File

@ -30,16 +30,21 @@ std::string TileAnnotation::global_port_name(const TileGlobalPortId& global_port
return global_port_names_[global_port_id];
}
std::string TileAnnotation::global_port_tile_name(const TileGlobalPortId& global_port_id) const {
std::vector<std::string> TileAnnotation::global_port_tile_names(const TileGlobalPortId& global_port_id) const {
VTR_ASSERT(valid_global_port_id(global_port_id));
return global_port_tile_names_[global_port_id];
}
BasicPort TileAnnotation::global_port_tile_port(const TileGlobalPortId& global_port_id) const {
std::vector<BasicPort> TileAnnotation::global_port_tile_ports(const TileGlobalPortId& global_port_id) const {
VTR_ASSERT(valid_global_port_id(global_port_id));
return global_port_tile_ports_[global_port_id];
}
std::vector<vtr::Point<size_t>> TileAnnotation::global_port_tile_coordinates(const TileGlobalPortId& global_port_id) const {
VTR_ASSERT(valid_global_port_id(global_port_id));
return global_port_tile_coordinates_[global_port_id];
}
bool TileAnnotation::global_port_is_clock(const TileGlobalPortId& global_port_id) const {
VTR_ASSERT(valid_global_port_id(global_port_id));
return global_port_is_clock_[global_port_id];
@ -63,9 +68,7 @@ size_t TileAnnotation::global_port_default_value(const TileGlobalPortId& global_
/************************************************************************
* Public Mutators
***********************************************************************/
TileGlobalPortId TileAnnotation::create_global_port(const std::string& port_name,
const std::string& tile_name,
const BasicPort& tile_port) {
TileGlobalPortId TileAnnotation::create_global_port(const std::string& port_name) {
/* Ensure that the name is unique */
std::map<std::string, TileGlobalPortId>::iterator it = global_port_name2ids_.find(port_name);
if (it != global_port_name2ids_.end()) {
@ -76,8 +79,9 @@ TileGlobalPortId TileAnnotation::create_global_port(const std::string& port_name
TileGlobalPortId port_id = TileGlobalPortId(global_port_ids_.size());
global_port_ids_.push_back(port_id);
global_port_names_.push_back(port_name);
global_port_tile_names_.push_back(tile_name);
global_port_tile_ports_.push_back(tile_port);
global_port_tile_names_.emplace_back();
global_port_tile_ports_.emplace_back();
global_port_tile_coordinates_.emplace_back();
global_port_is_clock_.push_back(false);
global_port_is_set_.push_back(false);
global_port_is_reset_.push_back(false);
@ -89,6 +93,16 @@ TileGlobalPortId TileAnnotation::create_global_port(const std::string& port_name
return port_id;
}
void TileAnnotation::add_global_port_tile_information(const TileGlobalPortId& global_port_id,
const std::string& tile_name,
const BasicPort& tile_port,
const vtr::Point<size_t>& tile_coord) {
VTR_ASSERT(valid_global_port_id(global_port_id));
global_port_tile_names_[global_port_id].push_back(tile_name);
global_port_tile_ports_[global_port_id].push_back(tile_port);
global_port_tile_coordinates_[global_port_id].push_back(tile_coord);
}
void TileAnnotation::set_global_port_is_clock(const TileGlobalPortId& global_port_id,
const bool& is_clock) {
VTR_ASSERT(valid_global_port_id(global_port_id));

View File

@ -9,6 +9,7 @@
#include <array>
#include "vtr_vector.h"
#include "vtr_geometry.h"
#include "openfpga_port.h"
@ -39,8 +40,9 @@ class TileAnnotation {
global_port_range global_ports() const;
public: /* Public accessors */
std::string global_port_name(const TileGlobalPortId& global_port_id) const;
std::string global_port_tile_name(const TileGlobalPortId& global_port_id) const;
BasicPort global_port_tile_port(const TileGlobalPortId& global_port_id) const;
std::vector<std::string> global_port_tile_names(const TileGlobalPortId& global_port_id) const;
std::vector<BasicPort> global_port_tile_ports(const TileGlobalPortId& global_port_id) const;
std::vector<vtr::Point<size_t>> global_port_tile_coordinates(const TileGlobalPortId& global_port_id) const;
bool global_port_is_clock(const TileGlobalPortId& global_port_id) const;
bool global_port_is_set(const TileGlobalPortId& global_port_id) const;
bool global_port_is_reset(const TileGlobalPortId& global_port_id) const;
@ -49,9 +51,12 @@ class TileAnnotation {
/* By default, we do not set it as a clock.
* Users should set it through the set_global_port_is_clock() function
*/
TileGlobalPortId create_global_port(const std::string& port_name,
const std::string& tile_name,
const BasicPort& tile_port);
TileGlobalPortId create_global_port(const std::string& port_name);
/* Add tile port information */
void add_global_port_tile_information(const TileGlobalPortId& global_port_id,
const std::string& tile_name,
const BasicPort& tile_port,
const vtr::Point<size_t>& tile_coord);
void set_global_port_is_clock(const TileGlobalPortId& global_port_id,
const bool& is_clock);
void set_global_port_is_set(const TileGlobalPortId& global_port_id,
@ -70,8 +75,9 @@ class TileAnnotation {
/* Global port information for tiles */
vtr::vector<TileGlobalPortId, TileGlobalPortId> global_port_ids_;
vtr::vector<TileGlobalPortId, std::string> global_port_names_;
vtr::vector<TileGlobalPortId, std::string> global_port_tile_names_;
vtr::vector<TileGlobalPortId, BasicPort> global_port_tile_ports_;
vtr::vector<TileGlobalPortId, std::vector<std::string>> global_port_tile_names_;
vtr::vector<TileGlobalPortId, std::vector<vtr::Point<size_t>>> global_port_tile_coordinates_;
vtr::vector<TileGlobalPortId, std::vector<BasicPort>> global_port_tile_ports_;
vtr::vector<TileGlobalPortId, bool> global_port_is_clock_;
vtr::vector<TileGlobalPortId, bool> global_port_is_reset_;
vtr::vector<TileGlobalPortId, bool> global_port_is_set_;

View File

@ -27,7 +27,7 @@ void write_xml_clock_setting(std::fstream& fp,
fp << "\t" << "<clock_setting>" << "\n";
fp << "\t\t" << "<operating";
write_xml_attribute(fp, "frequency", sim_setting.operating_clock_frequency());
write_xml_attribute(fp, "frequency", sim_setting.default_operating_clock_frequency());
if (true == sim_setting.auto_select_num_clock_cycles()) {
write_xml_attribute(fp, "num_cycles", "auto");
@ -37,8 +37,20 @@ void write_xml_clock_setting(std::fstream& fp,
}
write_xml_attribute(fp, "slack", std::to_string(sim_setting.operating_clock_frequency_slack()).c_str());
fp << ">" << "\n";
fp << "/>" << "\n";
/* Output clock information one by one */
for (const SimulationClockId& clock_id : sim_setting.clocks()) {
fp << "\t\t\t" << "<clock";
write_xml_attribute(fp, "name", sim_setting.clock_name(clock_id).c_str());
write_xml_attribute(fp, "port", generate_xml_port_name(sim_setting.clock_port(clock_id)).c_str());
write_xml_attribute(fp, "frequency", std::to_string(sim_setting.clock_frequency(clock_id)).c_str());
fp << ">" << "\n";
}
fp << "\t\t" << "</operating";
fp << ">" << "\n";
fp << "\t\t" << "<operating";
write_xml_attribute(fp, "frequency", sim_setting.programming_clock_frequency());
@ -219,7 +231,7 @@ void write_xml_simulation_setting(std::fstream& fp,
const openfpga::SimulationSetting& sim_setting) {
/* Validate the file stream */
openfpga::check_file_stream(fname, fp);
/* Write the root node <openfpga_simulation_setting>
*/
fp << "<openfpga_simulation_setting>" << "\n";

View File

@ -17,25 +17,6 @@
/* namespace openfpga begins */
namespace openfpga {
/********************************************************************
* FIXME: Use a common function to output ports
* Generate the full hierarchy name for a operating pb_type
*******************************************************************/
static
std::string generate_tile_port_name(const BasicPort& pb_port) {
std::string port_name;
/* Output format: <port_name>[<LSB>:<MSB>] */
port_name += pb_port.get_name();
port_name += std::string("[");
port_name += std::to_string(pb_port.get_lsb());
port_name += std::string(":");
port_name += std::to_string(pb_port.get_msb());
port_name += std::string("]");
return port_name;
}
/********************************************************************
* A writer to output a device variation in a technology library to XML format
*******************************************************************/
@ -51,11 +32,6 @@ void write_xml_tile_annotation_global_port(std::fstream& fp,
write_xml_attribute(fp, "name", tile_annotation.global_port_name(global_port_id).c_str());
std::string tile_port_attr = tile_annotation.global_port_tile_name(global_port_id)
+ "."
+ generate_tile_port_name(tile_annotation.global_port_tile_port(global_port_id));
write_xml_attribute(fp, "tile_port", tile_port_attr.c_str());
write_xml_attribute(fp, "is_clock", tile_annotation.global_port_is_clock(global_port_id));
write_xml_attribute(fp, "is_set", tile_annotation.global_port_is_set(global_port_id));
@ -64,7 +40,18 @@ void write_xml_tile_annotation_global_port(std::fstream& fp,
write_xml_attribute(fp, "default_value", tile_annotation.global_port_default_value(global_port_id));
fp << "/>" << "\n";
fp << ">" << "\n";
for (size_t tile_info_id = 0; tile_info_id < tile_annotation.global_port_tile_names(global_port_id).size(); ++tile_info_id) {
fp << "\t\t\t" << "<tile ";
write_xml_attribute(fp, "name", tile_annotation.global_port_tile_names(global_port_id)[tile_info_id].c_str());
write_xml_attribute(fp, "port", generate_xml_port_name(tile_annotation.global_port_tile_ports(global_port_id)[tile_info_id]).c_str());
write_xml_attribute(fp, "x", tile_annotation.global_port_tile_coordinates(global_port_id)[tile_info_id].x());
write_xml_attribute(fp, "y", tile_annotation.global_port_tile_coordinates(global_port_id)[tile_info_id].y());
fp << "/>";
}
fp << "\t\t" << "</global_port>";
}
/********************************************************************

View File

@ -90,3 +90,21 @@ void write_xml_attribute(std::fstream& fp,
fp << std::scientific << value;
fp << "\"";
}
/********************************************************************
* FIXME: Use a common function to output ports
* Generate the full hierarchy name for a operating pb_type
*******************************************************************/
std::string generate_xml_port_name(const openfpga::BasicPort& pb_port) {
std::string port_name;
/* Output format: <port_name>[<LSB>:<MSB>] */
port_name += pb_port.get_name();
port_name += std::string("[");
port_name += std::to_string(pb_port.get_lsb());
port_name += std::string(":");
port_name += std::to_string(pb_port.get_msb());
port_name += std::string("]");
return port_name;
}

View File

@ -6,6 +6,7 @@
*******************************************************************/
#include <fstream>
#include "circuit_library.h"
#include "openfpga_port.h"
/********************************************************************
* Function declaration
@ -30,4 +31,6 @@ void write_xml_attribute(std::fstream& fp,
const char* attr,
const size_t& value);
std::string generate_xml_port_name(const openfpga::BasicPort& pb_port);
#endif

View File

@ -2,11 +2,67 @@ cmake_minimum_required(VERSION 3.9)
project("libopenfpgautil")
#Version info
set(OPENFPGA_VERSION_FILE_IN ${CMAKE_CURRENT_SOURCE_DIR}/src/openfpga_version.cpp.in)
set(OPENFPGA_VERSION_FILE_OUT ${CMAKE_CURRENT_BINARY_DIR}/openfpga_version.cpp)
#Compiler info
set(OPENFPGA_COMPILER_INFO "${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION} on ${CMAKE_SYSTEM} ${CMAKE_SYSTEM_PROCESSOR}")
set(OPENFPGA_BUILD_INFO "${CMAKE_BUILD_TYPE}")
#Set default version numbers in case not specified
if(NOT DEFINED OPENFPGA_VERSION_MAJOR)
set(OPENFPGA_VERSION_MAJOR 0)
endif()
if(NOT DEFINED OPENFPGA_VERSION_MINOR)
set(OPENFPGA_VERSION_MINOR 0)
endif()
if(NOT DEFINED OPENFPGA_VERSION_PATCH)
set(OPENFPGA_VERSION_PATCH 0)
endif()
set(OPENFPGA_BUILD_INFO "${OPENFPGA_BUILD_INFO} ASSERT_LEVEL=${VTR_ASSERT_LEVEL}")
# We always update the openfpga_version.cpp file every time the project is built,
# to ensure the git revision and dirty status are up to date.
#
# We need to do this in two stages:
#
# 1) We build a custom target 'version' (which is always out of date) so it will always be run.
# It touches the unprocessed version input file so it too will always be out of date.
#
# 2) The custom command depends on the touched version input file and generates the processed
# version file, with updated values. The custom command uses the configure_version.cmake
# script to generate the up-to-date openfpga_version.cpp
add_custom_target(openfpga_version ALL
COMMAND ${CMAKE_COMMAND} -E touch ${OPENFPGA_VERSION_FILE_IN})
add_custom_command(OUTPUT ${OPENFPGA_VERSION_FILE_OUT}
COMMAND ${CMAKE_COMMAND}
-D IN_FILE=${OPENFPGA_VERSION_FILE_IN}
-D OUT_FILE=${OPENFPGA_VERSION_FILE_OUT}
-D OPENFPGA_VERSION_MAJOR=${OPENFPGA_VERSION_MAJOR}
-D OPENFPGA_VERSION_MINOR=${OPENFPGA_VERSION_MINOR}
-D OPENFPGA_VERSION_PATCH=${OPENFPGA_VERSION_PATCH}
-D OPENFPGA_VERSION_PRERELEASE=${OPENFPGA_VERSION_PRERELEASE}
-D OPENFPGA_COMPILER_INFO=${OPENFPGA_COMPILER_INFO}
-D OPENFPGA_BUILD_INFO=${OPENFPGA_BUILD_INFO}
-P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/configure_version.cmake
MAIN_DEPENDENCY ${OPENFPGA_VERSION_FILE_IN}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
VERBATIM)
#file(GLOB_RECURSE EXEC_SOURCES test/main.cpp)
file(GLOB_RECURSE LIB_SOURCES src/*.cpp)
file(GLOB_RECURSE LIB_HEADERS src/*.h)
files_to_dirs(LIB_HEADERS LIB_INCLUDE_DIRS)
#Add the version file to the sources
list(APPEND LIB_SOURCES ${OPENFPGA_VERSION_FILE_OUT})
#Remove test executable from library
#list(REMOVE_ITEM LIB_SOURCES ${EXEC_SOURCES})
@ -17,6 +73,9 @@ add_library(libopenfpgautil STATIC
target_include_directories(libopenfpgautil PUBLIC ${LIB_INCLUDE_DIRS})
set_target_properties(libopenfpgautil PROPERTIES PREFIX "") #Avoid extra 'lib' prefix
#Ensure version is always up to date by requiring version to be run first
add_dependencies(libopenfpgautil openfpga_version)
#Specify link-time dependancies
target_link_libraries(libopenfpgautil
libarchfpga

View File

@ -0,0 +1,55 @@
#
# Versioning information
#
#Figure out the git revision
find_package(Git QUIET)
if(GIT_FOUND)
exec_program(${GIT_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}
ARGS describe --always --long --dirty
OUTPUT_VARIABLE OPENFPGA_VCS_REVISION
RETURN_VALUE GIT_DESCRIBE_RETURN_VALUE)
if(NOT GIT_DESCRIBE_RETURN_VALUE EQUAL 0)
#Git describe failed, usually this means we
#aren't in a git repo -- so don't set a VCS
#revision
set(OPENFPGA_VCS_REVISION "unkown")
endif()
#Call again with exclude to get the revision excluding any tags
#(i.e. just the commit ID and dirty flag)
exec_program(${GIT_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}
ARGS describe --always --long --dirty --exclude '*'
OUTPUT_VARIABLE OPENFPGA_VCS_REVISION_SHORT
RETURN_VALUE GIT_DESCRIBE_RETURN_VALUE)
if(NOT GIT_DESCRIBE_RETURN_VALUE EQUAL 0)
#Git describe failed, usually this means we
#aren't in a git repo -- so don't set a VCS
#revision
set(OPENFPGA_VCS_REVISION_SHORT "unkown")
endif()
else()
#Couldn't find git, so can't look-up VCS revision
set(OPENFPGA_VCS_REVISION "unkown")
set(OPENFPGA_VCS_REVISION_SHORT "unkown")
endif()
#Set the version according to semver.org
set(OPENFPGA_VERSION "${OPENFPGA_VERSION_MAJOR}.${OPENFPGA_VERSION_MINOR}.${OPENFPGA_VERSION_PATCH}")
if(OPENFPGA_VERSION_PRERELEASE)
set(OPENFPGA_VERSION "${OPENFPGA_VERSION}-${OPENFPGA_VERSION_PRERELEASE}")
endif()
set(OPENFPGA_VERSION_SHORT ${OPENFPGA_VERSION})
if(OPENFPGA_VCS_REVISION)
set(OPENFPGA_VERSION "${OPENFPGA_VERSION}+${OPENFPGA_VCS_REVISION_SHORT}")
endif()
#Other build meta-data
string(TIMESTAMP OPENFPGA_BUILD_TIMESTAMP)
set(OPENFPGA_BUILD_TIMESTAMP "${OPENFPGA_BUILD_TIMESTAMP}")
set(OPENFPGA_BUILD_INFO "${OPENFPGA_BUILD_INFO}")
message(STATUS "OpenFPGA Version: ${OPENFPGA_VERSION}")
configure_file(${IN_FILE} ${OUT_FILE})

View File

@ -13,7 +13,10 @@ namespace openfpga {
/* Top-level module name */
constexpr char* FPGA_TOP_MODULE_NAME = "fpga_top";
constexpr char* CONFIGURABLE_MEMORY_CHAIN_IN_NAME = "ccff_head";
constexpr char* CONFIGURABLE_MEMORY_CHAIN_OUT_NAME = "ccff_tail";
constexpr char* CONFIGURABLE_MEMORY_DATA_OUT_NAME = "mem_out";
constexpr char* CONFIGURABLE_MEMORY_INVERTED_DATA_OUT_NAME = "mem_outb";
/* IO PORT */
/* Prefix of global input, output and inout ports of FPGA fabric */

View File

@ -0,0 +1,21 @@
#include "openfpga_version.h"
//This file is automatically processed by CMAKE and replaces
//the values between ampersand's with the releveant CMAKE variable
//before being compiled.
namespace openfpga {
const char* VERSION = "@OPENFPGA_VERSION@";
const char* VERSION_SHORT = "@OPENFPGA_VERSION_SHORT@";
const size_t VERSION_MAJOR = @OPENFPGA_VERSION_MAJOR@;
const size_t VERSION_MINOR = @OPENFPGA_VERSION_MINOR@;
const size_t VERSION_PATCH = @OPENFPGA_VERSION_PATCH@;
const char* VERSION_PRERELEASE = "@OPENFPGA_VERSION_PRERELEASE@";
const char* VCS_REVISION = "@OPENFPGA_VCS_REVISION@";
const char* VCS_REVISION_SHORT = "@OPENFPGA_VCS_REVISION_SHORT@";
const char* COMPILER = "@OPENFPGA_COMPILER_INFO@";
const char* BUILD_TIMESTAMP = "@OPENFPGA_BUILD_TIMESTAMP@";
const char* BUILD_INFO = "@OPENFPGA_BUILD_INFO@";
}

View File

@ -0,0 +1,20 @@
#ifndef OPENFPGA_VERSION_H
#define OPENFPGA_VERSION_H
#include <cstddef>
namespace openfpga {
extern const char* VERSION;
extern const char* VERSION_SHORT;
extern const size_t VERSION_MAJOR;
extern const size_t VERSION_MINOR;
extern const size_t VERSION_PATCH;
extern const char* VERSION_PRERELEASE;
extern const char* VCS_REVISION;
extern const char* COMPILER;
extern const char* BUILD_TIMESTAMP;
extern const char* BUILD_INFO;
} // namespace openfpga
#endif

View File

@ -0,0 +1,35 @@
cmake_minimum_required(VERSION 3.9)
project("libpcf")
file(GLOB_RECURSE EXEC_SOURCES test/*.cpp)
file(GLOB_RECURSE LIB_SOURCES src/*.cpp)
file(GLOB_RECURSE LIB_HEADERS src/*.h)
files_to_dirs(LIB_HEADERS LIB_INCLUDE_DIRS)
#Remove test executable from library
list(REMOVE_ITEM LIB_SOURCES ${EXEC_SOURCES})
#Create the library
add_library(libpcf STATIC
${LIB_HEADERS}
${LIB_SOURCES})
target_include_directories(libpcf PUBLIC ${LIB_INCLUDE_DIRS})
set_target_properties(libpcf PROPERTIES PREFIX "") #Avoid extra 'lib' prefix
#Specify link-time dependancies
target_link_libraries(libpcf
libopenfpgautil
libarchopenfpga
libvtrutil
libpugixml
libpugiutil)
#Create the test executable
foreach(testsourcefile ${EXEC_SOURCES})
# Use a simple string replace, to cut off .cpp.
get_filename_component(testname ${testsourcefile} NAME_WE)
add_executable(${testname} ${testsourcefile})
# Make sure the library is linked to each test executable
target_link_libraries(${testname} libpcf)
endforeach(testsourcefile ${EXEC_SOURCES})

View File

@ -0,0 +1,9 @@
<pin_constraints>
<!-- For a given .blif file, we want to assign
- the clk0 signal to the clk[0] port of the FPGA fabric
- the clk1 signal to the clk[1] port of the FPGA fabric
-->
<set_io pin="clk[0]" net="clk0"/>
<set_io pin="clk[1]" net="clk1"/>
</pin_constraints>

View File

@ -0,0 +1,72 @@
#include <algorithm>
#include "vtr_assert.h"
#include "vtr_log.h"
#include "pin_constraints.h"
/************************************************************************
* Member functions for class PinConstraints
***********************************************************************/
/************************************************************************
* Constructors
***********************************************************************/
PinConstraints::PinConstraints() {
return;
}
/************************************************************************
* Public Accessors : aggregates
***********************************************************************/
PinConstraints::pin_constraint_range PinConstraints::pin_constraints() const {
return vtr::make_range(pin_constraint_ids_.begin(), pin_constraint_ids_.end());
}
/************************************************************************
* Public Accessors : Basic data query
***********************************************************************/
openfpga::BasicPort PinConstraints::pin(const PinConstraintId& pin_constraint_id) const {
/* validate the pin_constraint_id */
VTR_ASSERT(valid_pin_constraint_id(pin_constraint_id));
return pin_constraint_pins_[pin_constraint_id];
}
std::string PinConstraints::net(const PinConstraintId& pin_constraint_id) const {
/* validate the pin_constraint_id */
VTR_ASSERT(valid_pin_constraint_id(pin_constraint_id));
return pin_constraint_nets_[pin_constraint_id];
}
bool PinConstraints::empty() const {
return 0 == pin_constraint_ids_.size();
}
/************************************************************************
* Public Mutators
***********************************************************************/
void PinConstraints::reserve_pin_constraints(const size_t& num_pin_constraints) {
pin_constraint_ids_.reserve(num_pin_constraints);
pin_constraint_pins_.reserve(num_pin_constraints);
pin_constraint_nets_.reserve(num_pin_constraints);
}
PinConstraintId PinConstraints::create_pin_constraint(const openfpga::BasicPort& pin,
const std::string& net) {
/* Create a new id */
PinConstraintId pin_constraint_id = PinConstraintId(pin_constraint_ids_.size());
pin_constraint_ids_.push_back(pin_constraint_id);
pin_constraint_pins_.push_back(pin);
pin_constraint_nets_.push_back(net);
return pin_constraint_id;
}
/************************************************************************
* Internal invalidators/validators
***********************************************************************/
/* Validators */
bool PinConstraints::valid_pin_constraint_id(const PinConstraintId& pin_constraint_id) const {
return ( size_t(pin_constraint_id) < pin_constraint_ids_.size() ) && ( pin_constraint_id == pin_constraint_ids_[pin_constraint_id] );
}

View File

@ -0,0 +1,80 @@
#ifndef PIN_CONSTRAINTS_H
#define PIN_CONSTRAINTS_H
/********************************************************************
* This file include the declaration of pin constraints
*******************************************************************/
#include <string>
#include <map>
#include <array>
/* Headers from vtrutil library */
#include "vtr_vector.h"
#include "vtr_geometry.h"
/* Headers from openfpgautil library */
#include "openfpga_port.h"
#include "pin_constraints_fwd.h"
/* Constants */
constexpr char* PIN_CONSTRAINT_OPEN_NET = "OPEN";
/********************************************************************
* A data structure to describe the pin constraints for FPGA fabrics
* This data structure may include a number of pin constraints
* each of which may constrain:
* - pin assignment, for instance, force a net to be mapped to specific pin
*
* Typical usage:
* --------------
* // Create an object of pin constraints
* PinConstraints pin_constraints;
* // Add a pin assignment
* openfpga::BasicPort pin_info(clk, 1);
* std::string net_info("top_clock");
* PinConstraintId pin_constraint_id = pin_constraints.create_pin_constraint(pin_info, net_info);
*
*******************************************************************/
class PinConstraints {
public: /* Types */
typedef vtr::vector<PinConstraintId, PinConstraintId>::const_iterator pin_constraint_iterator;
/* Create range */
typedef vtr::Range<pin_constraint_iterator> pin_constraint_range;
public: /* Constructors */
PinConstraints();
public: /* Accessors: aggregates */
pin_constraint_range pin_constraints() const;
public: /* Public Accessors: Basic data query */
/* Get the pin to be constrained */
openfpga::BasicPort pin(const PinConstraintId& pin_constraint_id) const;
/* Get the net to be constrained */
std::string net(const PinConstraintId& pin_constraint_id) const;
/* Check if there are any pin constraints */
bool empty() const;
public: /* Public Mutators */
/* Reserve a number of design constraints to be memory efficent */
void reserve_pin_constraints(const size_t& num_pin_constraints);
/* Add a pin constraint to storage */
PinConstraintId create_pin_constraint(const openfpga::BasicPort& pin,
const std::string& net);
public: /* Public invalidators/validators */
bool valid_pin_constraint_id(const PinConstraintId& pin_constraint_id) const;
private: /* Internal data */
/* Unique ids for each design constraint */
vtr::vector<PinConstraintId, PinConstraintId> pin_constraint_ids_;
/* Pins to constraint */
vtr::vector<PinConstraintId, openfpga::BasicPort> pin_constraint_pins_;
/* Nets to constraint */
vtr::vector<PinConstraintId, std::string> pin_constraint_nets_;
};
#endif

View File

@ -0,0 +1,22 @@
/************************************************************************
* A header file for PinConstraints class, including critical data declaration
* Please include this file only for using any PinConstraints data structure
* Refer to pin_constraints.h for more details
***********************************************************************/
/************************************************************************
* Create strong id for PinConstraints to avoid illegal type casting
***********************************************************************/
#ifndef PIN_CONSTRAINTS_FWD_H
#define PIN_CONSTRAINTS_FWD_H
#include "vtr_strong_id.h"
struct pin_constraint_id_tag;
typedef vtr::StrongId<pin_constraint_id_tag> PinConstraintId;
/* Short declaration of class */
class PinConstraints;
#endif

View File

@ -0,0 +1,82 @@
/********************************************************************
* This file includes the top-level function of this library
* which reads an XML of pin constraints to the associated
* data structures
*******************************************************************/
#include <string>
/* Headers from pugi XML library */
#include "pugixml.hpp"
#include "pugixml_util.hpp"
/* Headers from vtr util library */
#include "vtr_assert.h"
#include "vtr_time.h"
/* Headers from libopenfpga util library */
#include "openfpga_port_parser.h"
/* Headers from libarchfpga */
#include "arch_error.h"
#include "read_xml_util.h"
#include "read_xml_pin_constraints.h"
/********************************************************************
* Parse XML codes of a <set_io> to an object of PinConstraint
*******************************************************************/
static
void read_xml_pin_constraint(pugi::xml_node& xml_pin_constraint,
const pugiutil::loc_data& loc_data,
PinConstraints& pin_constraints) {
openfpga::PortParser port_parser(get_attribute(xml_pin_constraint, "pin", loc_data).as_string());
std::string net_name = get_attribute(xml_pin_constraint, "net", loc_data).as_string();
/* Create a new pin constraint in the storage */
PinConstraintId pin_constraint_id = pin_constraints.create_pin_constraint(port_parser.port(), net_name);
if (false == pin_constraints.valid_pin_constraint_id(pin_constraint_id)) {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_pin_constraint),
"Fail to create pin constraint!\n");
}
}
/********************************************************************
* Parse XML codes about <pin_constraints> to an object of PinConstraints
*******************************************************************/
PinConstraints read_xml_pin_constraints(const char* pin_constraint_fname) {
vtr::ScopedStartFinishTimer timer("Read Pin Constraints");
PinConstraints pin_constraints;
/* Parse the file */
pugi::xml_document doc;
pugiutil::loc_data loc_data;
try {
loc_data = pugiutil::load_xml(doc, pin_constraint_fname);
pugi::xml_node xml_root = get_single_child(doc, "pin_constraints", loc_data);
size_t num_pin_constraints = std::distance(xml_root.children().begin(), xml_root.children().end());
/* Reserve memory space for the region */
pin_constraints.reserve_pin_constraints(num_pin_constraints);
for (pugi::xml_node xml_pin_constraint : xml_root.children()) {
/* Error out if the XML child has an invalid name! */
if (xml_pin_constraint.name() != std::string("set_io")) {
bad_tag(xml_pin_constraint, loc_data, xml_root, {"set_io"});
}
read_xml_pin_constraint(xml_pin_constraint, loc_data, pin_constraints);
}
} catch (pugiutil::XmlError& e) {
archfpga_throw(pin_constraint_fname, e.line(),
"%s", e.what());
}
return pin_constraints;
}

View File

@ -0,0 +1,16 @@
#ifndef READ_XML_PIN_CONSTRAINTS_H
#define READ_XML_PIN_CONSTRAINTS_H
/********************************************************************
* Include header files that are required by function declaration
*******************************************************************/
#include "pugixml_util.hpp"
#include "pugixml.hpp"
#include "pin_constraints.h"
/********************************************************************
* Function declaration
*******************************************************************/
PinConstraints read_xml_pin_constraints(const char* pin_constraint_fname);
#endif

View File

@ -0,0 +1,94 @@
/********************************************************************
* This file includes functions that outputs a pin constraint object to XML format
*******************************************************************/
/* Headers from system goes first */
#include <string>
#include <algorithm>
/* Headers from vtr util library */
#include "vtr_assert.h"
#include "vtr_log.h"
#include "vtr_time.h"
/* Headers from openfpga util library */
#include "openfpga_digest.h"
/* Headers from arch openfpga library */
#include "write_xml_utils.h"
/* Headers from pin constraint library */
#include "write_xml_pin_constraints.h"
/********************************************************************
* A writer to output a pin constraint to XML format
*
* Return 0 if successful
* Return 1 if there are more serious bugs in the architecture
* Return 2 if fail when creating files
*******************************************************************/
static
int write_xml_pin_constraint(std::fstream& fp,
const PinConstraints& pin_constraints,
const PinConstraintId& pin_constraint) {
/* Validate the file stream */
if (false == openfpga::valid_file_stream(fp)) {
return 2;
}
openfpga::write_tab_to_file(fp, 1);
fp << "<set_io";
if (false == pin_constraints.valid_pin_constraint_id(pin_constraint)) {
return 1;
}
write_xml_attribute(fp, "pin", generate_xml_port_name(pin_constraints.pin(pin_constraint)).c_str());
write_xml_attribute(fp, "net", pin_constraints.net(pin_constraint).c_str());
fp << "/>" << "\n";
return 0;
}
/********************************************************************
* A writer to output a repack pin constraint object to XML format
*
* Return 0 if successful
* Return 1 if there are more serious bugs in the architecture
* Return 2 if fail when creating files
*******************************************************************/
int write_xml_pin_constraints(const char* fname,
const PinConstraints& pin_constraints) {
vtr::ScopedStartFinishTimer timer("Write Pin Constraints");
/* Create a file handler */
std::fstream fp;
/* Open the file stream */
fp.open(std::string(fname), std::fstream::out | std::fstream::trunc);
/* Validate the file stream */
openfpga::check_file_stream(fname, fp);
/* Write the root node */
fp << "<pin_constraints>" << "\n";
int err_code = 0;
/* Write region by region */
for (const PinConstraintId& pin_constraint : pin_constraints.pin_constraints()) {
/* Write constraint by constraint */
err_code = write_xml_pin_constraint(fp, pin_constraints, pin_constraint);
if (0 != err_code) {
return err_code;
}
}
/* Finish writing the root node */
fp << "</pin_constraints>" << "\n";
/* Close the file stream */
fp.close();
return err_code;
}

View File

@ -0,0 +1,16 @@
#ifndef WRITE_XML_PIN_CONSTRAINTS_H
#define WRITE_XML_PIN_CONSTRAINTS_H
/********************************************************************
* Include header files that are required by function declaration
*******************************************************************/
#include <fstream>
#include "pin_constraints.h"
/********************************************************************
* Function declaration
*******************************************************************/
int write_xml_pin_constraints(const char* fname,
const PinConstraints& pin_constraints);
#endif

View File

@ -0,0 +1,33 @@
/********************************************************************
* Unit test functions to validate the correctness of
* 1. parser of data structures
* 2. writer of data structures
*******************************************************************/
/* Headers from vtrutils */
#include "vtr_assert.h"
#include "vtr_log.h"
/* Headers from fabric key */
#include "read_xml_pin_constraints.h"
#include "write_xml_pin_constraints.h"
int main(int argc, const char** argv) {
/* Ensure we have only one or two argument */
VTR_ASSERT((2 == argc) || (3 == argc));
/* Parse the fabric key from an XML file */
PinConstraints pin_constraints = read_xml_pin_constraints(argv[1]);
VTR_LOG("Read the pin constraints from an XML file: %s.\n",
argv[1]);
/* Output pin constraints to an XML file
* This is optional only used when there is a second argument
*/
if (3 <= argc) {
write_xml_pin_constraints(argv[2], pin_constraints);
VTR_LOG("Echo the pin constraints to an XML file: %s.\n",
argv[2]);
}
}

View File

@ -0,0 +1,35 @@
cmake_minimum_required(VERSION 3.9)
project("librepackdc")
file(GLOB_RECURSE EXEC_SOURCES test/*.cpp)
file(GLOB_RECURSE LIB_SOURCES src/*.cpp)
file(GLOB_RECURSE LIB_HEADERS src/*.h)
files_to_dirs(LIB_HEADERS LIB_INCLUDE_DIRS)
#Remove test executable from library
list(REMOVE_ITEM LIB_SOURCES ${EXEC_SOURCES})
#Create the library
add_library(librepackdc STATIC
${LIB_HEADERS}
${LIB_SOURCES})
target_include_directories(librepackdc PUBLIC ${LIB_INCLUDE_DIRS})
set_target_properties(librepackdc PROPERTIES PREFIX "") #Avoid extra 'lib' prefix
#Specify link-time dependancies
target_link_libraries(librepackdc
libopenfpgautil
libarchopenfpga
libvtrutil
libpugixml
libpugiutil)
#Create the test executable
foreach(testsourcefile ${EXEC_SOURCES})
# Use a simple string replace, to cut off .cpp.
get_filename_component(testname ${testsourcefile} NAME_WE)
add_executable(${testname} ${testsourcefile})
# Make sure the library is linked to each test executable
target_link_libraries(${testname} librepackdc)
endforeach(testsourcefile ${EXEC_SOURCES})

View File

@ -0,0 +1,7 @@
<repack_design_constraints>
<pin_constraint pb_type="clb" pin="clk[0]" net="clk0"/>
<pin_constraint pb_type="clb" pin="clk[1]" net="clk1"/>
<pin_constraint pb_type="clb" pin="clk[2]" net="OPEN"/>
<pin_constraint pb_type="clb" pin="clk[3]" net="OPEN"/>
</repack_design_constraints>

View File

@ -0,0 +1,89 @@
/********************************************************************
* This file includes the top-level function of this library
* which reads an XML of a fabric key to the associated
* data structures
*******************************************************************/
#include <string>
/* Headers from pugi XML library */
#include "pugixml.hpp"
#include "pugixml_util.hpp"
/* Headers from vtr util library */
#include "vtr_assert.h"
#include "vtr_time.h"
/* Headers from libopenfpga util library */
#include "openfpga_port_parser.h"
/* Headers from libarchfpga */
#include "arch_error.h"
#include "read_xml_util.h"
#include "read_xml_repack_design_constraints.h"
/********************************************************************
* Parse XML codes of a <key> to an object of FabricKey
*******************************************************************/
static
void read_xml_pin_constraint(pugi::xml_node& xml_pin_constraint,
const pugiutil::loc_data& loc_data,
RepackDesignConstraints& repack_design_constraints) {
/* Create a new design constraint in the storage */
RepackDesignConstraintId design_constraint_id = repack_design_constraints.create_design_constraint(RepackDesignConstraints::PIN_ASSIGNMENT);
if (false == repack_design_constraints.valid_design_constraint_id(design_constraint_id)) {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_pin_constraint),
"Fail to create design constraint!\n");
}
repack_design_constraints.set_pb_type(design_constraint_id,
get_attribute(xml_pin_constraint, "pb_type", loc_data).as_string());
openfpga::PortParser port_parser(get_attribute(xml_pin_constraint, "pin", loc_data).as_string());
repack_design_constraints.set_pin(design_constraint_id,
port_parser.port());
repack_design_constraints.set_net(design_constraint_id,
get_attribute(xml_pin_constraint, "net", loc_data).as_string());
}
/********************************************************************
* Parse XML codes about <repack_design_constraints> to an object of RepackDesignConstraints
*******************************************************************/
RepackDesignConstraints read_xml_repack_design_constraints(const char* design_constraint_fname) {
vtr::ScopedStartFinishTimer timer("Read Repack Design Constraints");
RepackDesignConstraints repack_design_constraints;
/* Parse the file */
pugi::xml_document doc;
pugiutil::loc_data loc_data;
try {
loc_data = pugiutil::load_xml(doc, design_constraint_fname);
pugi::xml_node xml_root = get_single_child(doc, "repack_design_constraints", loc_data);
size_t num_design_constraints = std::distance(xml_root.children().begin(), xml_root.children().end());
/* Reserve memory space for the region */
repack_design_constraints.reserve_design_constraints(num_design_constraints);
for (pugi::xml_node xml_design_constraint : xml_root.children()) {
/* Error out if the XML child has an invalid name! */
if (xml_design_constraint.name() != std::string("pin_constraint")) {
bad_tag(xml_design_constraint, loc_data, xml_root, {"pin_constraint"});
}
read_xml_pin_constraint(xml_design_constraint, loc_data, repack_design_constraints);
}
} catch (pugiutil::XmlError& e) {
archfpga_throw(design_constraint_fname, e.line(),
"%s", e.what());
}
return repack_design_constraints;
}

View File

@ -0,0 +1,16 @@
#ifndef READ_XML_REPACK_DESIGN_CONSTRAINTS_H
#define READ_XML_REPACK_DESIGN_CONSTRAINTS_H
/********************************************************************
* Include header files that are required by function declaration
*******************************************************************/
#include "pugixml_util.hpp"
#include "pugixml.hpp"
#include "repack_design_constraints.h"
/********************************************************************
* Function declaration
*******************************************************************/
RepackDesignConstraints read_xml_repack_design_constraints(const char* design_constraint_fname);
#endif

View File

@ -0,0 +1,108 @@
#include <algorithm>
#include "vtr_assert.h"
#include "vtr_log.h"
#include "repack_design_constraints.h"
/************************************************************************
* Member functions for class RepackDesignConstraints
***********************************************************************/
/************************************************************************
* Constructors
***********************************************************************/
RepackDesignConstraints::RepackDesignConstraints() {
return;
}
/************************************************************************
* Public Accessors : aggregates
***********************************************************************/
RepackDesignConstraints::repack_design_constraint_range RepackDesignConstraints::design_constraints() const {
return vtr::make_range(repack_design_constraint_ids_.begin(), repack_design_constraint_ids_.end());
}
/************************************************************************
* Public Accessors : Basic data query
***********************************************************************/
RepackDesignConstraints::e_design_constraint_type RepackDesignConstraints::type(const RepackDesignConstraintId& repack_design_constraint_id) const {
/* validate the design_constraint_id */
VTR_ASSERT(valid_design_constraint_id(repack_design_constraint_id));
return repack_design_constraint_types_[repack_design_constraint_id];
}
std::string RepackDesignConstraints::pb_type(const RepackDesignConstraintId& repack_design_constraint_id) const {
/* validate the design_constraint_id */
VTR_ASSERT(valid_design_constraint_id(repack_design_constraint_id));
return repack_design_constraint_pb_types_[repack_design_constraint_id];
}
openfpga::BasicPort RepackDesignConstraints::pin(const RepackDesignConstraintId& repack_design_constraint_id) const {
/* validate the design_constraint_id */
VTR_ASSERT(valid_design_constraint_id(repack_design_constraint_id));
return repack_design_constraint_pins_[repack_design_constraint_id];
}
std::string RepackDesignConstraints::net(const RepackDesignConstraintId& repack_design_constraint_id) const {
/* validate the design_constraint_id */
VTR_ASSERT(valid_design_constraint_id(repack_design_constraint_id));
return repack_design_constraint_nets_[repack_design_constraint_id];
}
bool RepackDesignConstraints::empty() const {
return 0 == repack_design_constraint_ids_.size();
}
/************************************************************************
* Public Mutators
***********************************************************************/
void RepackDesignConstraints::reserve_design_constraints(const size_t& num_design_constraints) {
repack_design_constraint_ids_.reserve(num_design_constraints);
repack_design_constraint_types_.reserve(num_design_constraints);
repack_design_constraint_pb_types_.reserve(num_design_constraints);
repack_design_constraint_pins_.reserve(num_design_constraints);
repack_design_constraint_nets_.reserve(num_design_constraints);
}
RepackDesignConstraintId RepackDesignConstraints::create_design_constraint(const RepackDesignConstraints::e_design_constraint_type& repack_design_constraint_type) {
/* Create a new id */
RepackDesignConstraintId repack_design_constraint_id = RepackDesignConstraintId(repack_design_constraint_ids_.size());
repack_design_constraint_ids_.push_back(repack_design_constraint_id);
repack_design_constraint_types_.push_back(repack_design_constraint_type);
repack_design_constraint_pb_types_.emplace_back();
repack_design_constraint_pins_.emplace_back();
repack_design_constraint_nets_.emplace_back();
return repack_design_constraint_id;
}
void RepackDesignConstraints::set_pb_type(const RepackDesignConstraintId& repack_design_constraint_id,
const std::string& pb_type) {
/* validate the design_constraint_id */
VTR_ASSERT(valid_design_constraint_id(repack_design_constraint_id));
repack_design_constraint_pb_types_[repack_design_constraint_id] = pb_type;
}
void RepackDesignConstraints::set_pin(const RepackDesignConstraintId& repack_design_constraint_id,
const openfpga::BasicPort& pin) {
/* validate the design_constraint_id */
VTR_ASSERT(valid_design_constraint_id(repack_design_constraint_id));
repack_design_constraint_pins_[repack_design_constraint_id] = pin;
}
void RepackDesignConstraints::set_net(const RepackDesignConstraintId& repack_design_constraint_id,
const std::string& net) {
/* validate the design_constraint_id */
VTR_ASSERT(valid_design_constraint_id(repack_design_constraint_id));
repack_design_constraint_nets_[repack_design_constraint_id] = net;
}
/************************************************************************
* Internal invalidators/validators
***********************************************************************/
/* Validators */
bool RepackDesignConstraints::valid_design_constraint_id(const RepackDesignConstraintId& design_constraint_id) const {
return ( size_t(design_constraint_id) < repack_design_constraint_ids_.size() ) && ( design_constraint_id == repack_design_constraint_ids_[design_constraint_id] );
}

View File

@ -0,0 +1,106 @@
#ifndef REPACK_DESIGN_CONSTRAINTS_H
#define REPACK_DESIGN_CONSTRAINTS_H
/********************************************************************
* This file include the declaration of repack design constraints
*******************************************************************/
#include <string>
#include <map>
#include <array>
/* Headers from vtrutil library */
#include "vtr_vector.h"
#include "vtr_geometry.h"
/* Headers from openfpgautil library */
#include "openfpga_port.h"
#include "repack_design_constraints_fwd.h"
/* Constants */
constexpr char* REPACK_DESIGN_CONSTRAINT_OPEN_NET = "OPEN";
/********************************************************************
* A data structure to describe the design constraints for repacking tools
* This data structure may include a number of design constraints
* each of which may constrain:
* - pin assignment, for instance, force a net to be mapped to specific pin
*
* Typical usage:
* --------------
* // Create an object of design constraints
* RepackDesignConstraints repack_design_constraints;
* // Add a pin assignment
* RepackDesignConstraintId repack_dc_id = fabric_key.create_design_constraint(RepackDesignConstraints::PIN_ASSIGNMENT);
*
*******************************************************************/
class RepackDesignConstraints {
public: /* Type of design constraints */
enum e_design_constraint_type {
PIN_ASSIGNMENT,
NUM_DESIGN_CONSTRAINT_TYPES
};
public: /* Types */
typedef vtr::vector<RepackDesignConstraintId, RepackDesignConstraintId>::const_iterator repack_design_constraint_iterator;
/* Create range */
typedef vtr::Range<repack_design_constraint_iterator> repack_design_constraint_range;
public: /* Constructors */
RepackDesignConstraints();
public: /* Accessors: aggregates */
repack_design_constraint_range design_constraints() const;
public: /* Public Accessors: Basic data query */
/* Get the type of constraint */
e_design_constraint_type type(const RepackDesignConstraintId& repack_design_constraint_id) const;
/* Get the pb_type name to be constrained */
std::string pb_type(const RepackDesignConstraintId& repack_design_constraint_id) const;
/* Get the pin to be constrained */
openfpga::BasicPort pin(const RepackDesignConstraintId& repack_design_constraint_id) const;
/* Get the net to be constrained */
std::string net(const RepackDesignConstraintId& repack_design_constraint_id) const;
/* Check if there are any design constraints */
bool empty() const;
public: /* Public Mutators */
/* Reserve a number of design constraints to be memory efficent */
void reserve_design_constraints(const size_t& num_design_constraints);
/* Add a design constraint to storage */
RepackDesignConstraintId create_design_constraint(const e_design_constraint_type& repack_design_constraint_type);
/* Set the pb_type name to be constrained */
void set_pb_type(const RepackDesignConstraintId& repack_design_constraint_id,
const std::string& pb_type);
/* Set the pin to be constrained */
void set_pin(const RepackDesignConstraintId& repack_design_constraint_id,
const openfpga::BasicPort& pin);
/* Set the net to be constrained */
void set_net(const RepackDesignConstraintId& repack_design_constraint_id,
const std::string& net);
public: /* Public invalidators/validators */
bool valid_design_constraint_id(const RepackDesignConstraintId& repack_design_constraint_id) const;
private: /* Internal data */
/* Unique ids for each design constraint */
vtr::vector<RepackDesignConstraintId, RepackDesignConstraintId> repack_design_constraint_ids_;
/* Type for each design constraint */
vtr::vector<RepackDesignConstraintId, e_design_constraint_type> repack_design_constraint_types_;
/* Tiles to constraint */
vtr::vector<RepackDesignConstraintId, std::string> repack_design_constraint_pb_types_;
/* Pins to constraint */
vtr::vector<RepackDesignConstraintId, openfpga::BasicPort> repack_design_constraint_pins_;
/* Nets to constraint */
vtr::vector<RepackDesignConstraintId, std::string> repack_design_constraint_nets_;
};
#endif

View File

@ -0,0 +1,22 @@
/************************************************************************
* A header file for RepackDesignConstraints class, including critical data declaration
* Please include this file only for using any TechnologyLibrary data structure
* Refer to repack_design_constraints.h for more details
***********************************************************************/
/************************************************************************
* Create strong id for RepackDesignConstraints to avoid illegal type casting
***********************************************************************/
#ifndef REPACK_DESIGN_CONSTRAINTS_FWD_H
#define REPACK_DESIGN_CONSTRAINTS_FWD_H
#include "vtr_strong_id.h"
struct repack_design_constraint_id_tag;
typedef vtr::StrongId<repack_design_constraint_id_tag> RepackDesignConstraintId;
/* Short declaration of class */
class RepackDesignConstraints;
#endif

View File

@ -0,0 +1,97 @@
/********************************************************************
* This file includes functions that outputs a repack design constraint object to XML format
*******************************************************************/
/* Headers from system goes first */
#include <string>
#include <algorithm>
/* Headers from vtr util library */
#include "vtr_assert.h"
#include "vtr_log.h"
#include "vtr_time.h"
/* Headers from openfpga util library */
#include "openfpga_digest.h"
/* Headers from arch openfpga library */
#include "write_xml_utils.h"
/* Headers from fabrickey library */
#include "write_xml_repack_design_constraints.h"
/********************************************************************
* A writer to output a pin constraint to XML format
*
* Return 0 if successful
* Return 1 if there are more serious bugs in the architecture
* Return 2 if fail when creating files
*******************************************************************/
static
int write_xml_pin_constraint(std::fstream& fp,
const RepackDesignConstraints& repack_design_constraints,
const RepackDesignConstraintId& design_constraint) {
/* Validate the file stream */
if (false == openfpga::valid_file_stream(fp)) {
return 2;
}
openfpga::write_tab_to_file(fp, 1);
fp << "<pin_constraint";
if (false == repack_design_constraints.valid_design_constraint_id(design_constraint)) {
return 1;
}
write_xml_attribute(fp, "pb_type", repack_design_constraints.pb_type(design_constraint).c_str());
write_xml_attribute(fp, "pin", generate_xml_port_name(repack_design_constraints.pin(design_constraint)).c_str());
write_xml_attribute(fp, "net", repack_design_constraints.net(design_constraint).c_str());
fp << "/>" << "\n";
return 0;
}
/********************************************************************
* A writer to output a repack design constraint object to XML format
*
* Return 0 if successful
* Return 1 if there are more serious bugs in the architecture
* Return 2 if fail when creating files
*******************************************************************/
int write_xml_repack_design_constraints(const char* fname,
const RepackDesignConstraints& repack_design_constraints) {
vtr::ScopedStartFinishTimer timer("Write Repack Design Constraints");
/* Create a file handler */
std::fstream fp;
/* Open the file stream */
fp.open(std::string(fname), std::fstream::out | std::fstream::trunc);
/* Validate the file stream */
openfpga::check_file_stream(fname, fp);
/* Write the root node */
fp << "<repack_design_constraints>" << "\n";
int err_code = 0;
/* Write region by region */
for (const RepackDesignConstraintId& design_constraint : repack_design_constraints.design_constraints()) {
/* Write constraint by constraint */
if (RepackDesignConstraints::PIN_ASSIGNMENT == repack_design_constraints.type(design_constraint)) {
err_code = write_xml_pin_constraint(fp, repack_design_constraints, design_constraint);
if (0 != err_code) {
return err_code;
}
}
}
/* Finish writing the root node */
fp << "</repack_design_constraints>" << "\n";
/* Close the file stream */
fp.close();
return err_code;
}

View File

@ -0,0 +1,16 @@
#ifndef WRITE_XML_REPACK_DESIGN_CONSTRAINTS_H
#define WRITE_XML_REPACK_DESIGN_CONSTRAINTS_H
/********************************************************************
* Include header files that are required by function declaration
*******************************************************************/
#include <fstream>
#include "repack_design_constraints.h"
/********************************************************************
* Function declaration
*******************************************************************/
int write_xml_repack_design_constraints(const char* fname,
const RepackDesignConstraints& repack_design_constraints);
#endif

View File

@ -0,0 +1,34 @@
/********************************************************************
* Unit test functions to validate the correctness of
* 1. parser of data structures
* 2. writer of data structures
*******************************************************************/
/* Headers from vtrutils */
#include "vtr_assert.h"
#include "vtr_log.h"
/* Headers from fabric key */
#include "read_xml_repack_design_constraints.h"
#include "write_xml_repack_design_constraints.h"
int main(int argc, const char** argv) {
/* Ensure we have only one or two argument */
VTR_ASSERT((2 == argc) || (3 == argc));
/* Parse the fabric key from an XML file */
RepackDesignConstraints design_constraints = read_xml_repack_design_constraints(argv[1]);
VTR_LOG("Read the repack design constraints from an XML file: %s.\n",
argv[1]);
/* Output the circuit library to an XML file
* This is optional only used when there is a second argument
*/
if (3 <= argc) {
write_xml_repack_design_constraints(argv[2], design_constraints);
VTR_LOG("Echo the repack design constraints to an XML file: %s.\n",
argv[2]);
}
}

View File

@ -23,8 +23,10 @@ target_link_libraries(libopenfpga
libopenfpgashell
libopenfpgautil
libfabrickey
librepackdc
libfpgabitstream
libini
libpcf
libvtrutil
libvpr)

View File

@ -191,7 +191,7 @@ int annotate_simulation_setting(const AtomContext& atom_ctx,
SimulationSetting& sim_setting) {
/* Find if the operating frequency is binded to vpr results */
if (0. == sim_setting.operating_clock_frequency()) {
if (0. == sim_setting.default_operating_clock_frequency()) {
VTR_LOG("User specified the operating clock frequency to use VPR results\n");
/* Run timing analysis and collect critical path delay
* This code is copied from function vpr_analysis() in vpr_api.h
@ -212,12 +212,24 @@ int annotate_simulation_setting(const AtomContext& atom_ctx,
/* Get critical path delay. Update simulation settings */
float T_crit = timing_info->least_slack_critical_path().delay() * (1. + sim_setting.operating_clock_frequency_slack());
sim_setting.set_operating_clock_frequency(1 / T_crit);
sim_setting.set_default_operating_clock_frequency(1 / T_crit);
VTR_LOG("Use VPR critical path delay %g [ns] with a %g [%] slack in OpenFPGA.\n",
T_crit / 1e9, sim_setting.operating_clock_frequency_slack() * 100);
}
VTR_LOG("Will apply operating clock frequency %g [MHz] to simulations\n",
sim_setting.operating_clock_frequency() / 1e6);
sim_setting.default_operating_clock_frequency() / 1e6);
/* Walk through all the clock information */
for (const SimulationClockId& clock_id : sim_setting.clocks()) {
if (0. == sim_setting.clock_frequency(clock_id)) {
sim_setting.set_clock_frequency(clock_id, sim_setting.default_operating_clock_frequency());
}
VTR_LOG("Will apply clock frequency %g [MHz] to clock '%s[%d:%d]' in simulations\n",
sim_setting.clock_frequency(clock_id) / 1e6,
sim_setting.clock_port(clock_id).get_name().c_str(),
sim_setting.clock_port(clock_id).get_lsb(),
sim_setting.clock_port(clock_id).get_msb());
}
if (0. == sim_setting.num_clock_cycles()) {
/* Find the number of clock cycles to be used in simulation

View File

@ -21,6 +21,9 @@ ShellCommandId add_openfpga_repack_command(openfpga::Shell<OpenfpgaContext>& she
const ShellCommandClassId& cmd_class_id,
const std::vector<ShellCommandId>& dependent_cmds) {
Command shell_cmd("repack");
/* Add an option '--design_constraints' */
CommandOptionId opt_design_constraints = shell_cmd.add_option("design_constraints", false, "file path to the design constraints");
shell_cmd.set_option_require_value(opt_design_constraints, openfpga::OPT_STRING);
/* Add an option '--verbose' */
shell_cmd.add_option("verbose", false, "Enable verbose output");

View File

@ -708,7 +708,7 @@ std::string generate_formal_verification_sram_port_name(const CircuitLibrary& ci
* TODO: This could be replaced as a constexpr string
*********************************************************************/
std::string generate_configuration_chain_head_name() {
return std::string("ccff_head");
return std::string(CONFIGURABLE_MEMORY_CHAIN_IN_NAME);
}
/*********************************************************************
@ -716,7 +716,7 @@ std::string generate_configuration_chain_head_name() {
* TODO: This could be replaced as a constexpr string
*********************************************************************/
std::string generate_configuration_chain_tail_name() {
return std::string("ccff_tail");
return std::string(CONFIGURABLE_MEMORY_CHAIN_OUT_NAME);
}
/*********************************************************************
@ -732,7 +732,7 @@ std::string generate_configurable_memory_data_out_name() {
* TODO: This could be replaced as a constexpr string
*********************************************************************/
std::string generate_configurable_memory_inverted_data_out_name() {
return std::string("mem_outb");
return std::string(CONFIGURABLE_MEMORY_INVERTED_DATA_OUT_NAME);
}
/*********************************************************************

View File

@ -8,10 +8,15 @@
/* Headers from openfpgashell library */
#include "command_exit_codes.h"
/* Headers from librepackdc library */
#include "repack_design_constraints.h"
#include "read_xml_repack_design_constraints.h"
#include "build_physical_truth_table.h"
#include "repack.h"
#include "openfpga_repack.h"
/* Include global variables of VPR */
#include "globals.h"
@ -24,13 +29,23 @@ namespace openfpga {
int repack(OpenfpgaContext& openfpga_ctx,
const Command& cmd, const CommandContext& cmd_context) {
CommandOptionId opt_design_constraints = cmd.option("design_constraints");
CommandOptionId opt_verbose = cmd.option("verbose");
/* Load design constraints from file */
RepackDesignConstraints repack_design_constraints;
if (true == cmd_context.option_enable(cmd, opt_design_constraints)) {
std::string dc_fname = cmd_context.option_value(cmd, opt_design_constraints);
VTR_ASSERT(false == dc_fname.empty());
repack_design_constraints = read_xml_repack_design_constraints(dc_fname.c_str());
}
pack_physical_pbs(g_vpr_ctx.device(),
g_vpr_ctx.atom(),
g_vpr_ctx.clustering(),
openfpga_ctx.mutable_vpr_device_annotation(),
openfpga_ctx.mutable_vpr_clustering_annotation(),
repack_design_constraints,
cmd_context.option_enable(cmd, opt_verbose));
build_physical_lut_truth_tables(openfpga_ctx.mutable_vpr_clustering_annotation(),

View File

@ -83,8 +83,6 @@ int write_pnr_sdc(const OpenfpgaContext& openfpga_ctx,
/* Execute only when sdc is enabled */
if (true == options.generate_sdc_pnr()) {
print_pnr_sdc(options,
1./openfpga_ctx.simulation_setting().programming_clock_frequency(),
1./openfpga_ctx.simulation_setting().operating_clock_frequency(),
g_vpr_ctx.device(),
openfpga_ctx.vpr_device_annotation(),
openfpga_ctx.device_rr_gsb(),
@ -92,6 +90,7 @@ int write_pnr_sdc(const OpenfpgaContext& openfpga_ctx,
openfpga_ctx.mux_lib(),
openfpga_ctx.arch().circuit_lib,
openfpga_ctx.fabric_global_port_info(),
openfpga_ctx.simulation_setting(),
openfpga_ctx.flow_manager().compress_routing());
}
@ -190,7 +189,7 @@ int write_analysis_sdc(const OpenfpgaContext& openfpga_ctx,
if (true == options.generate_sdc_analysis()) {
print_analysis_sdc(options,
1./openfpga_ctx.simulation_setting().operating_clock_frequency(),
1./openfpga_ctx.simulation_setting().default_operating_clock_frequency(),
g_vpr_ctx,
openfpga_ctx,
openfpga_ctx.flow_manager().compress_routing());

View File

@ -3,6 +3,7 @@
* which introduces generality of OpenFPGA framework
*******************************************************************/
#include "openfpga_title.h"
#include "openfpga_version.h"
/********************************************************************
* Generate a string of openfpga title introduction
@ -49,5 +50,13 @@ std::string create_openfpga_title() {
title += std::string("THE SOFTWARE.\n");
title += std::string("\n");
/* Display version */
title += std::string("Version: " + std::string(openfpga::VERSION) + "\n");
title += std::string("Revision: " + std::string(openfpga::VCS_REVISION) + "\n");
title += std::string("Compiled: " + std::string(openfpga::BUILD_TIMESTAMP) + "\n");
title += std::string("Compiler: " + std::string(openfpga::COMPILER) + "\n");
title += std::string("Build Info: " + std::string(openfpga::BUILD_INFO) + "\n");
title += std::string("\n");
return title;
}

View File

@ -11,6 +11,9 @@
#include "verilog_api.h"
#include "openfpga_verilog.h"
/* Headers from pcf library */
#include "read_xml_pin_constraints.h"
/* Include global variables of VPR */
#include "globals.h"
@ -62,6 +65,7 @@ int write_verilog_testbench(OpenfpgaContext& openfpga_ctx,
CommandOptionId opt_output_dir = cmd.option("file");
CommandOptionId opt_fabric_netlist = cmd.option("fabric_netlist_file_path");
CommandOptionId opt_pcf = cmd.option("pin_constraints_file");
CommandOptionId opt_reference_benchmark = cmd.option("reference_benchmark_file_path");
CommandOptionId opt_print_top_testbench = cmd.option("print_top_testbench");
CommandOptionId opt_fast_configuration = cmd.option("fast_configuration");
@ -89,22 +93,26 @@ int write_verilog_testbench(OpenfpgaContext& openfpga_ctx,
options.set_include_signal_init(cmd_context.option_enable(cmd, opt_include_signal_init));
options.set_support_icarus_simulator(cmd_context.option_enable(cmd, opt_support_icarus_simulator));
options.set_verbose_output(cmd_context.option_enable(cmd, opt_verbose));
fpga_verilog_testbench(openfpga_ctx.module_graph(),
openfpga_ctx.bitstream_manager(),
openfpga_ctx.fabric_bitstream(),
g_vpr_ctx.atom(),
g_vpr_ctx.placement(),
openfpga_ctx.io_location_map(),
openfpga_ctx.fabric_global_port_info(),
openfpga_ctx.vpr_netlist_annotation(),
openfpga_ctx.arch().circuit_lib,
openfpga_ctx.simulation_setting(),
openfpga_ctx.arch().config_protocol,
options);
/* TODO: should identify the error code from internal function execution */
return CMD_EXEC_SUCCESS;
/* If pin constraints are enabled by command options, read the file */
PinConstraints pin_constraints;
if (true == cmd_context.option_enable(cmd, opt_pcf)) {
pin_constraints = read_xml_pin_constraints(cmd_context.option_value(cmd, opt_pcf).c_str());
}
return fpga_verilog_testbench(openfpga_ctx.module_graph(),
openfpga_ctx.bitstream_manager(),
openfpga_ctx.fabric_bitstream(),
g_vpr_ctx.atom(),
g_vpr_ctx.placement(),
pin_constraints,
openfpga_ctx.io_location_map(),
openfpga_ctx.fabric_global_port_info(),
openfpga_ctx.vpr_netlist_annotation(),
openfpga_ctx.arch().circuit_lib,
openfpga_ctx.simulation_setting(),
openfpga_ctx.arch().config_protocol,
options);
}
} /* end namespace openfpga */

View File

@ -70,6 +70,11 @@ ShellCommandId add_openfpga_write_verilog_testbench_command(openfpga::Shell<Open
CommandOptionId fabric_netlist_opt = shell_cmd.add_option("fabric_netlist_file_path", false, "Specify the file path to the fabric Verilog netlist");
shell_cmd.set_option_require_value(fabric_netlist_opt, openfpga::OPT_STRING);
/* Add an option '--pin_constraints_file in short '-pcf' */
CommandOptionId pcf_opt = shell_cmd.add_option("pin_constraints_file", false, "Specify the file path to the pin constraints");
shell_cmd.set_option_short_name(pcf_opt, "pcf");
shell_cmd.set_option_require_value(pcf_opt, openfpga::OPT_STRING);
/* Add an option '--reference_benchmark_file_path'*/
CommandOptionId ref_bm_opt = shell_cmd.add_option("reference_benchmark_file_path", true, "Specify the file path to the reference Verilog netlist");
shell_cmd.set_option_require_value(ref_bm_opt, openfpga::OPT_STRING);

View File

@ -77,8 +77,6 @@ void add_module_input_nets_to_mem_modules(ModuleManager& module_manager,
* j-th pin of output port of the i-th child module is wired to the j + i*W -th
* pin of output port of the memory module, where W is the size of port
* 3. It assumes fixed port name for output ports
*
* We cache the module nets that have been created because they will be used later
********************************************************************/
static
std::vector<ModuleNetId> add_module_output_nets_to_chain_mem_modules(ModuleManager& module_manager,
@ -165,15 +163,11 @@ void add_module_output_nets_to_mem_modules(ModuleManager& module_manager,
* add_module_nets_cmos_memory_chain_config_bus() !!!
*********************************************************************/
static
void add_module_nets_to_cmos_memory_chain_module(ModuleManager& module_manager,
const ModuleId& parent_module,
const std::vector<ModuleNetId>& output_nets,
const CircuitLibrary& circuit_lib,
const CircuitPortId& model_input_port,
const CircuitPortId& model_output_port) {
/* Counter for the nets */
size_t net_counter = 0;
void add_module_nets_to_cmos_memory_config_chain_module(ModuleManager& module_manager,
const ModuleId& parent_module,
const CircuitLibrary& circuit_lib,
const CircuitPortId& model_input_port,
const CircuitPortId& model_output_port) {
for (size_t mem_index = 0; mem_index < module_manager.configurable_children(parent_module).size(); ++mem_index) {
ModuleId net_src_module_id;
size_t net_src_instance_id;
@ -219,21 +213,9 @@ void add_module_nets_to_cmos_memory_chain_module(ModuleManager& module_manager,
/* Create a net for each pin */
for (size_t pin_id = 0; pin_id < net_src_port.pins().size(); ++pin_id) {
/* Create a net and add source and sink to it */
ModuleNetId net;
if (0 == mem_index) {
net = module_manager.create_module_net(parent_module);
} else {
net = output_nets[net_counter];
}
/* Add net source */
module_manager.add_module_net_source(parent_module, net, net_src_module_id, net_src_instance_id, net_src_port_id, net_src_port.pins()[pin_id]);
ModuleNetId net = create_module_source_pin_net(module_manager, parent_module, net_src_module_id, net_src_instance_id, net_src_port_id, net_src_port.pins()[pin_id]);
/* Add net sink */
module_manager.add_module_net_sink(parent_module, net, net_sink_module_id, net_sink_instance_id, net_sink_port_id, net_sink_port.pins()[pin_id]);
/* Update net counter */
if (0 < mem_index) {
net_counter++;
}
}
}
@ -263,17 +245,90 @@ void add_module_nets_to_cmos_memory_chain_module(ModuleManager& module_manager,
/* Create a net for each pin */
for (size_t pin_id = 0; pin_id < net_src_port.pins().size(); ++pin_id) {
/* Create a net and add source and sink to it */
ModuleNetId net = output_nets[net_counter];
/* Add net source */
module_manager.add_module_net_source(parent_module, net, net_src_module_id, net_src_instance_id, net_src_port_id, net_src_port.pins()[pin_id]);
ModuleNetId net = create_module_source_pin_net(module_manager, parent_module, net_src_module_id, net_src_instance_id, net_src_port_id, net_src_port.pins()[pin_id]);
/* Add net sink */
module_manager.add_module_net_sink(parent_module, net, net_sink_module_id, net_sink_instance_id, net_sink_port_id, net_sink_port.pins()[pin_id]);
/* Update net counter */
net_counter++;
}
}
VTR_ASSERT(net_counter == output_nets.size());
/********************************************************************
* Connect the scan input of all the memory modules
* under the parent module in a chain
*
* +--------+ +--------+ +--------+
* ccff_head --->| Memory |--->| Memory |--->... --->| Memory |
* | Module | | Module | | Module |
* | [0] | | [1] | | [N-1] |
* +--------+ +--------+ +--------+
* For the 1st memory module:
* net source is the configuration chain head of the primitive module
* net sink is the scan input of the next memory module
*
* For the rest of memory modules:
* net source is the configuration chain tail of the previous memory module
* net sink is the scan input of the next memory module
*
* Note that:
* This function is designed for memory modules ONLY!
* Do not use it to replace the
* add_module_nets_cmos_memory_chain_config_bus() !!!
*********************************************************************/
static
void add_module_nets_to_cmos_memory_scan_chain_module(ModuleManager& module_manager,
const ModuleId& parent_module,
const CircuitLibrary& circuit_lib,
const CircuitPortId& model_input_port,
const CircuitPortId& model_output_port) {
for (size_t mem_index = 0; mem_index < module_manager.configurable_children(parent_module).size(); ++mem_index) {
ModuleId net_src_module_id;
size_t net_src_instance_id;
ModulePortId net_src_port_id;
ModuleId net_sink_module_id;
size_t net_sink_instance_id;
ModulePortId net_sink_port_id;
if (0 == mem_index) {
/* Find the port name of configuration chain head */
std::string src_port_name = generate_configuration_chain_head_name();
net_src_module_id = parent_module;
net_src_instance_id = 0;
net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name);
/* Find the port name of next memory module */
std::string sink_port_name = circuit_lib.port_prefix(model_input_port);
net_sink_module_id = module_manager.configurable_children(parent_module)[mem_index];
net_sink_instance_id = module_manager.configurable_child_instances(parent_module)[mem_index];
net_sink_port_id = module_manager.find_module_port(net_sink_module_id, sink_port_name);
} else {
/* Find the port name of previous memory module */
std::string src_port_name = circuit_lib.port_prefix(model_output_port);
net_src_module_id = module_manager.configurable_children(parent_module)[mem_index - 1];
net_src_instance_id = module_manager.configurable_child_instances(parent_module)[mem_index - 1];
net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name);
/* Find the port name of next memory module */
std::string sink_port_name = circuit_lib.port_prefix(model_input_port);
net_sink_module_id = module_manager.configurable_children(parent_module)[mem_index];
net_sink_instance_id = module_manager.configurable_child_instances(parent_module)[mem_index];
net_sink_port_id = module_manager.find_module_port(net_sink_module_id, sink_port_name);
}
/* Get the pin id for source port */
BasicPort net_src_port = module_manager.module_port(net_src_module_id, net_src_port_id);
/* Get the pin id for sink port */
BasicPort net_sink_port = module_manager.module_port(net_sink_module_id, net_sink_port_id);
/* Port sizes of source and sink should match */
VTR_ASSERT(net_src_port.get_width() == net_sink_port.get_width());
/* Create a net for each pin */
for (size_t pin_id = 0; pin_id < net_src_port.pins().size(); ++pin_id) {
/* Create a net and add source and sink to it */
ModuleNetId net = create_module_source_pin_net(module_manager, parent_module, net_src_module_id, net_src_instance_id, net_src_port_id, net_src_port.pins()[pin_id]);
/* Add net sink */
module_manager.add_module_net_sink(parent_module, net, net_sink_module_id, net_sink_instance_id, net_sink_port_id, net_sink_port.pins()[pin_id]);
}
}
}
/*********************************************************************
@ -382,7 +437,7 @@ void build_memory_flatten_module(ModuleManager& module_manager,
* scan-chain--->| CCFF |--->| CCFF |--->... --->| CCFF |---->scan-chain
* input&clock | [0] | | [1] | | [N-1] | output
* +-------+ +-------+ +-------+
* | | ... |
* | | ... | config-memory output
* v v v
* +-----------------------------------------+
* | Multiplexer Configuration port |
@ -397,12 +452,15 @@ void build_memory_chain_module(ModuleManager& module_manager,
/* Get the input ports from the SRAM */
std::vector<CircuitPortId> sram_input_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_INPUT, true);
/* Should have only 1 input port */
VTR_ASSERT( 1 == sram_input_ports.size() );
/* Should have only 1 or 2 input port */
VTR_ASSERT( (1 == sram_input_ports.size())
|| (2 == sram_input_ports.size()) );
/* Get the output ports from the SRAM */
std::vector<CircuitPortId> sram_output_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_OUTPUT, true);
/* Should have only 1 or 2 output port */
VTR_ASSERT( (1 == sram_output_ports.size()) || ( 2 == sram_output_ports.size()) );
/* Should have only 1 or 2 or 3 output port */
VTR_ASSERT( (1 == sram_output_ports.size())
|| (2 == sram_output_ports.size())
|| (3 == sram_output_ports.size()) );
/* Create a module and add to the module manager */
ModuleId mem_module = module_manager.add_module(module_name);
@ -428,13 +486,27 @@ void build_memory_chain_module(ModuleManager& module_manager,
circuit_lib.port_size(sram_output_ports[0]));
module_manager.add_port(mem_module, chain_tail_port, ModuleManager::MODULE_OUTPUT_PORT);
/* Add each output port: port width should match the number of memories */
for (size_t iport = 0; iport < sram_output_ports.size(); ++iport) {
/* There could be 3 conditions w.r.t. the number of output ports:
* - Only one output port is defined. In this case, the 1st port is the Q
* In such case, only Q will be considered as data output ports
* - Two output port is defined. In this case, the 1st port is the Q while the 2nd port is the QN
* In such case, both Q and QN will be considered as data output ports
* - Three output port is defined.
* In this case:
* - the 1st port is the Q (the chain output)
* - the 2nd port is the QN (the inverted data output)
* - the 3nd port is the configure-enabled Q
* In such case, configure-enabled Q and QN will be considered as data output ports
*/
size_t num_data_output_ports = sram_output_ports.size();
if (3 == sram_output_ports.size()) {
num_data_output_ports = 2;
}
for (size_t iport = 0; iport < num_data_output_ports; ++iport) {
std::string port_name;
if (0 == iport) {
port_name = generate_configurable_memory_data_out_name();
} else {
VTR_ASSERT( 1 == iport);
} else if (1 == iport) {
port_name = generate_configurable_memory_inverted_data_out_name();
}
BasicPort output_port(port_name, num_mems);
@ -444,9 +516,6 @@ void build_memory_chain_module(ModuleManager& module_manager,
/* Find the sram module in the module manager */
ModuleId sram_mem_module = module_manager.find_module(circuit_lib.model_name(sram_model));
/* Cache the output nets for non-inverted data output */
std::vector<ModuleNetId> mem_output_nets;
/* Instanciate each submodule */
for (size_t i = 0; i < num_mems; ++i) {
size_t sram_mem_instance = module_manager.num_instance(mem_module, sram_mem_module);
@ -454,7 +523,7 @@ void build_memory_chain_module(ModuleManager& module_manager,
module_manager.add_configurable_child(mem_module, sram_mem_module, sram_mem_instance);
/* Build module nets to wire outputs of sram modules to outputs of memory module */
for (size_t iport = 0; iport < sram_output_ports.size(); ++iport) {
for (size_t iport = 0; iport < num_data_output_ports; ++iport) {
std::string port_name;
if (0 == iport) {
port_name = generate_configurable_memory_data_out_name();
@ -462,20 +531,32 @@ void build_memory_chain_module(ModuleManager& module_manager,
VTR_ASSERT( 1 == iport);
port_name = generate_configurable_memory_inverted_data_out_name();
}
/* Find the proper data output port
* The exception is when there are 3 output ports defined
* The 3rd port is the regular data output port to be used
*/
CircuitPortId data_output_port_to_connect = sram_output_ports[iport];
if ((3 == sram_output_ports.size()) && (0 == iport)) {
data_output_port_to_connect = sram_output_ports.back();
}
std::vector<ModuleNetId> output_nets = add_module_output_nets_to_chain_mem_modules(module_manager, mem_module,
port_name, circuit_lib, sram_output_ports[iport],
port_name, circuit_lib, data_output_port_to_connect,
sram_mem_module, i, sram_mem_instance);
/* Cache only for regular data outputs */
if (0 == iport) {
mem_output_nets.insert(mem_output_nets.end(), output_nets.begin(), output_nets.end());
}
}
}
/* Build module nets to wire the configuration chain */
add_module_nets_to_cmos_memory_chain_module(module_manager, mem_module, mem_output_nets,
circuit_lib, sram_input_ports[0], sram_output_ports[0]);
add_module_nets_to_cmos_memory_config_chain_module(module_manager, mem_module,
circuit_lib, sram_input_ports[0], sram_output_ports[0]);
/* If there is a second input defined,
* add nets to short wire the 2nd inputs to the first inputs
*/
if (2 == sram_input_ports.size()) {
add_module_nets_to_cmos_memory_scan_chain_module(module_manager, mem_module,
circuit_lib, sram_input_ports[1], sram_output_ports[0]);
}
/* Add global ports to the pb_module:
* This is a much easier job after adding sub modules (instances),

View File

@ -695,33 +695,44 @@ void add_top_module_nets_connect_grids_and_gsbs(ModuleManager& module_manager,
* that are defined as global in tile annotation
*******************************************************************/
static
void build_top_module_global_net_for_given_grid_module(ModuleManager& module_manager,
const ModuleId& top_module,
const ModulePortId& top_module_port,
const TileAnnotation& tile_annotation,
const TileGlobalPortId& tile_global_port,
const DeviceGrid& grids,
const vtr::Point<size_t>& grid_coordinate,
const e_side& border_side,
const vtr::Matrix<size_t>& grid_instance_ids) {
int build_top_module_global_net_for_given_grid_module(ModuleManager& module_manager,
const ModuleId& top_module,
const ModulePortId& top_module_port,
const TileAnnotation& tile_annotation,
const TileGlobalPortId& tile_global_port,
const BasicPort& tile_port_to_connect,
const DeviceGrid& grids,
const vtr::Point<size_t>& grid_coordinate,
const e_side& border_side,
const vtr::Matrix<size_t>& grid_instance_ids) {
t_physical_tile_type_ptr physical_tile = grids[grid_coordinate.x()][grid_coordinate.y()].type;
/* Ensure physical tile matches the global port definition */
VTR_ASSERT(std::string(physical_tile->name) == tile_annotation.global_port_tile_name(tile_global_port));
/* Find the port of the grid module according to the tile annotation */
int grid_pin_index = physical_tile->num_pins;
int grid_pin_start_index = physical_tile->num_pins;
t_physical_tile_port physical_tile_port;
for (const t_physical_tile_port& tile_port : physical_tile->ports) {
if (std::string(tile_port.name) == tile_annotation.global_port_tile_port(tile_global_port).get_name()) {
if (std::string(tile_port.name) == tile_port_to_connect.get_name()) {
BasicPort ref_tile_port(tile_port.name, tile_port.num_pins);
/* Port size must match!!! */
VTR_ASSERT(size_t(tile_port.num_pins) == tile_annotation.global_port_tile_port(tile_global_port).get_width());
/* TODO: Should check there is only port matching!!! */
grid_pin_index = tile_port.absolute_first_pin_index;
if (false == ref_tile_port.contained(tile_port_to_connect)) {
VTR_LOG_ERROR("Tile annotation '%s' port '%s[%lu:%lu]' is out of the range of physical tile port '%s[%lu:%lu]'!",
tile_annotation.global_port_name(tile_global_port).c_str(),
tile_port_to_connect.get_name().c_str(),
tile_port_to_connect.get_lsb(),
tile_port_to_connect.get_msb(),
ref_tile_port.get_name().c_str(),
ref_tile_port.get_lsb(),
ref_tile_port.get_msb());
return CMD_EXEC_FATAL_ERROR;
}
grid_pin_start_index = tile_port.absolute_first_pin_index;
physical_tile_port = tile_port;
break;
}
}
/* Ensure the pin index is valid */
VTR_ASSERT(grid_pin_index < physical_tile->num_pins);
VTR_ASSERT(grid_pin_start_index < physical_tile->num_pins);
/* Find the module name for this type of grid */
std::string grid_module_name_prefix(GRID_MODULE_NAME_PREFIX);
@ -730,23 +741,46 @@ void build_top_module_global_net_for_given_grid_module(ModuleManager& module_man
VTR_ASSERT(true == module_manager.valid_module_id(grid_module));
size_t grid_instance = grid_instance_ids[grid_coordinate.x()][grid_coordinate.y()];
/* Find the module pin */
size_t grid_pin_width = physical_tile->pin_width_offset[grid_pin_index];
size_t grid_pin_height = physical_tile->pin_height_offset[grid_pin_index];
std::vector<e_side> pin_sides = find_physical_tile_pin_side(physical_tile, grid_pin_index, border_side);
for (const e_side& pin_side : pin_sides) {
std::string grid_port_name = generate_grid_port_name(grid_coordinate,
grid_pin_width, grid_pin_height,
pin_side,
grid_pin_index, false);
ModulePortId grid_port_id = module_manager.find_module_port(grid_module, grid_port_name);
VTR_ASSERT(true == module_manager.valid_module_port_id(grid_module, grid_port_id));
VTR_ASSERT(1 == physical_tile->equivalent_sites.size());
/* Build nets */
add_module_bus_nets(module_manager, top_module,
top_module, 0, top_module_port,
grid_module, grid_instance, grid_port_id);
/* Ensure port width is in range */
BasicPort src_port = module_manager.module_port(top_module, top_module_port);
VTR_ASSERT(src_port.get_width() >= size_t(physical_tile_port.num_pins));
/* A tile may consist of multiple subtile, connect to all the pins from sub tiles */
for (int iz = 0; iz < physical_tile->capacity; ++iz) {
for (size_t pin_id = 0; pin_id < size_t(physical_tile_port.num_pins); ++pin_id) {
/* TODO: This should be replaced by using a pin mapping data structure from physical tile! */
int grid_pin_index = grid_pin_start_index + iz * physical_tile->equivalent_sites[0]->pb_type->num_pins + pin_id;
/* Find the module pin */
size_t grid_pin_width = physical_tile->pin_width_offset[grid_pin_index];
size_t grid_pin_height = physical_tile->pin_height_offset[grid_pin_index];
std::vector<e_side> pin_sides = find_physical_tile_pin_side(physical_tile, grid_pin_index, border_side);
/* Build nets */
for (const e_side& pin_side : pin_sides) {
std::string grid_port_name = generate_grid_port_name(grid_coordinate,
grid_pin_width, grid_pin_height,
pin_side,
grid_pin_index, false);
ModulePortId grid_port_id = module_manager.find_module_port(grid_module, grid_port_name);
VTR_ASSERT(true == module_manager.valid_module_port_id(grid_module, grid_port_id));
VTR_ASSERT(1 == module_manager.module_port(grid_module, grid_port_id).get_width());
ModuleNetId net = create_module_source_pin_net(module_manager, top_module,
top_module, 0,
top_module_port, src_port.pins()[pin_id]);
VTR_ASSERT(ModuleNetId::INVALID() != net);
/* Configure the net sink */
BasicPort sink_port = module_manager.module_port(grid_module, grid_port_id);
module_manager.add_module_net_sink(top_module, net, grid_module, grid_instance, grid_port_id, sink_port.pins()[0]);
}
}
}
return CMD_EXEC_SUCCESS;
}
/********************************************************************
@ -757,17 +791,23 @@ int add_top_module_global_ports_from_grid_modules(ModuleManager& module_manager,
const TileAnnotation& tile_annotation,
const DeviceGrid& grids,
const vtr::Matrix<size_t>& grid_instance_ids) {
int status = CMD_EXEC_SUCCESS;
/* Add the global ports which are yet added to the top-level module
/* Add the global ports which are NOT yet added to the top-level module
* (in different names than the global ports defined in circuit library
*/
std::vector<BasicPort> global_ports_to_add;
for (const TileGlobalPortId& tile_global_port : tile_annotation.global_ports()) {
ModulePortId module_port = module_manager.find_module_port(top_module, tile_annotation.global_port_name(tile_global_port));
/* The global port size is derived from the maximum port size among all the tile port defintion */
if (ModulePortId::INVALID() == module_port) {
BasicPort global_port_to_add;
global_port_to_add.set_name(tile_annotation.global_port_name(tile_global_port));
global_port_to_add.set_width(tile_annotation.global_port_tile_port(tile_global_port).get_width());
size_t max_port_size = 0;
for (const BasicPort& tile_port : tile_annotation.global_port_tile_ports(tile_global_port)) {
max_port_size = std::max(tile_port.get_width(), max_port_size);
}
global_port_to_add.set_width(max_port_size);
global_ports_to_add.push_back(global_port_to_add);
}
}
@ -784,72 +824,130 @@ int add_top_module_global_ports_from_grid_modules(ModuleManager& module_manager,
ModulePortId top_module_port = module_manager.find_module_port(top_module, tile_annotation.global_port_name(tile_global_port));
VTR_ASSERT(ModulePortId::INVALID() != top_module_port);
/* Spot the port from child modules from core grids */
for (size_t ix = 1; ix < grids.width() - 1; ++ix) {
for (size_t iy = 1; iy < grids.height() - 1; ++iy) {
/* Bypass EMPTY tiles */
if (true == is_empty_type(grids[ix][iy].type)) {
continue;
}
/* Skip width or height > 1 tiles (mostly heterogeneous blocks) */
if ( (0 < grids[ix][iy].width_offset)
|| (0 < grids[ix][iy].height_offset)) {
continue;
}
for (size_t tile_info_id = 0; tile_info_id < tile_annotation.global_port_tile_names(tile_global_port).size(); ++tile_info_id) {
std::string tile_name = tile_annotation.global_port_tile_names(tile_global_port)[tile_info_id];
BasicPort tile_port = tile_annotation.global_port_tile_ports(tile_global_port)[tile_info_id];
/* Find the coordinates for the wanted tiles */
vtr::Point<size_t> start_coord(1, 1);
vtr::Point<size_t> end_coord(grids.width() - 1, grids.height() - 1);
vtr::Point<size_t> range = tile_annotation.global_port_tile_coordinates(tile_global_port)[tile_info_id];
bool out_of_range = false;
/* Bypass the tiles whose names do not match */
if (std::string(grids[ix][iy].type->name) != tile_annotation.global_port_tile_name(tile_global_port)) {
continue;
/* -1 means all the x should be considered */
if (size_t(-1) != range.x()) {
if ((range.x() < start_coord.x()) || (range.x() > end_coord.x())) {
out_of_range = true;
} else {
/* Set the range */
start_coord.set_x(range.x());
end_coord.set_x(range.x());
}
/* Create nets and finish connection build-up */
build_top_module_global_net_for_given_grid_module(module_manager,
top_module,
top_module_port,
tile_annotation,
tile_global_port,
grids,
vtr::Point<size_t>(ix, iy),
NUM_SIDES,
grid_instance_ids);
}
}
/* Walk through all the grids on the perimeter, which are I/O grids */
for (const e_side& io_side : FPGA_SIDES_CLOCKWISE) {
for (const vtr::Point<size_t>& io_coordinate : io_coordinates[io_side]) {
/* Bypass EMPTY grid */
if (true == is_empty_type(grids[io_coordinate.x()][io_coordinate.y()].type)) {
continue;
}
/* -1 means all the y should be considered */
if (size_t(-1) != range.y()) {
if ((range.y() < start_coord.y()) || (range.y() > end_coord.y())) {
out_of_range = true;
} else {
/* Set the range */
start_coord.set_y(range.y());
end_coord.set_y(range.y());
}
}
/* Error out immediately if the coordinate is not valid! */
if (true == out_of_range) {
VTR_LOG_ERROR("Coordinate (%lu, %lu) in tile annotation for tile '%s' is out of range (%lu:%lu, %lu:%lu)!",
range.x(), range.y(), tile_name.c_str(),
start_coord.x(), end_coord.x(), start_coord.y(), end_coord.y());
return CMD_EXEC_FATAL_ERROR;
}
/* Spot the port from child modules from core grids */
for (size_t ix = start_coord.x(); ix < end_coord.x(); ++ix) {
for (size_t iy = start_coord.y(); iy < end_coord.y(); ++iy) {
/* Bypass EMPTY tiles */
if (true == is_empty_type(grids[ix][iy].type)) {
continue;
}
/* Skip width or height > 1 tiles (mostly heterogeneous blocks) */
if ( (0 < grids[ix][iy].width_offset)
|| (0 < grids[ix][iy].height_offset)) {
continue;
}
/* Bypass the tiles whose names do not match */
if (std::string(grids[ix][iy].type->name) != tile_name) {
continue;
}
/* Create nets and finish connection build-up */
status = build_top_module_global_net_for_given_grid_module(module_manager,
top_module,
top_module_port,
tile_annotation,
tile_global_port,
tile_port,
grids,
vtr::Point<size_t>(ix, iy),
NUM_SIDES,
grid_instance_ids);
if (CMD_EXEC_FATAL_ERROR == status) {
return status;
}
}
}
/* Walk through all the grids on the perimeter, which are I/O grids */
for (const e_side& io_side : FPGA_SIDES_CLOCKWISE) {
for (const vtr::Point<size_t>& io_coordinate : io_coordinates[io_side]) {
/* Bypass EMPTY grid */
if (true == is_empty_type(grids[io_coordinate.x()][io_coordinate.y()].type)) {
continue;
}
/* Skip width or height > 1 tiles (mostly heterogeneous blocks) */
if ( (0 < grids[io_coordinate.x()][io_coordinate.y()].width_offset)
|| (0 < grids[io_coordinate.x()][io_coordinate.y()].height_offset)) {
continue;
}
/* Skip width or height > 1 tiles (mostly heterogeneous blocks) */
if ( (0 < grids[io_coordinate.x()][io_coordinate.y()].width_offset)
|| (0 < grids[io_coordinate.x()][io_coordinate.y()].height_offset)) {
continue;
}
/* Bypass the tiles whose names do not match */
if (std::string(grids[io_coordinate.x()][io_coordinate.y()].type->name) != tile_annotation.global_port_tile_name(tile_global_port)) {
continue;
}
/* Bypass the tiles whose names do not match */
if (std::string(grids[io_coordinate.x()][io_coordinate.y()].type->name) != tile_name) {
continue;
}
/* Create nets and finish connection build-up */
build_top_module_global_net_for_given_grid_module(module_manager,
top_module,
top_module_port,
tile_annotation,
tile_global_port,
grids,
io_coordinate,
io_side,
grid_instance_ids);
/* Check if the coordinate satisfy the tile coordinate defintion
* - Bypass if the x is a specific number (!= -1), and io_coordinate is different
* - Bypass if the y is a specific number (!= -1), and io_coordinate is different
*/
if ((size_t(-1) != range.x()) && (range.x() != io_coordinate.x())) {
continue;
}
if ((size_t(-1) != range.y()) && (range.y() != io_coordinate.y())) {
continue;
}
/* Create nets and finish connection build-up */
status = build_top_module_global_net_for_given_grid_module(module_manager,
top_module,
top_module_port,
tile_annotation,
tile_global_port,
tile_port,
grids,
io_coordinate,
io_side,
grid_instance_ids);
if (CMD_EXEC_FATAL_ERROR == status) {
return status;
}
}
}
}
}
return CMD_EXEC_SUCCESS;
return status;
}
} /* end namespace openfpga */

View File

@ -21,6 +21,9 @@ FabricBitstream::FabricBitstream() {
num_regions_ = 0;
invalid_region_ids_.clear();
use_address_ = false;
use_wl_address_ = false;
}
/**************************************************

View File

@ -241,7 +241,10 @@ void print_analysis_sdc(const AnalysisSdcOption& option,
ModuleId top_module = openfpga_ctx.module_graph().find_module(generate_fpga_top_module_name());
VTR_ASSERT(true == openfpga_ctx.module_graph().valid_module_id(top_module));
/* Create clock and set I/O ports with input/output delays */
/* Create clock and set I/O ports with input/output delays
* FIXME: Now different I/Os have different delays due to multiple clock frequency
* We need to consider these impacts and constrain different I/Os with different delays!!!
*/
print_analysis_sdc_io_delays(fp, option.time_unit(),
vpr_ctx.atom(), vpr_ctx.placement(),
openfpga_ctx.vpr_netlist_annotation(), openfpga_ctx.io_location_map(),

View File

@ -59,11 +59,10 @@ void print_pnr_sdc_clock_port(std::fstream& fp,
*******************************************************************/
static
void print_pnr_sdc_global_clock_ports(std::fstream& fp,
const float& programming_critical_path_delay,
const float& operating_critical_path_delay,
const ModuleManager& module_manager,
const ModuleId& top_module,
const FabricGlobalPortInfo& fabric_global_port_info) {
const FabricGlobalPortInfo& fabric_global_port_info,
const SimulationSetting& sim_setting) {
valid_file_stream(fp);
@ -73,11 +72,11 @@ void print_pnr_sdc_global_clock_ports(std::fstream& fp,
continue;
}
/* Reach here, it means a clock port and we need print constraints */
float clock_period = operating_critical_path_delay;
float clock_period = 1./sim_setting.default_operating_clock_frequency();
/* For programming clock, we give a fixed period */
if (true == fabric_global_port_info.global_port_is_prog(global_port)) {
clock_period = programming_critical_path_delay;
clock_period = 1./sim_setting.programming_clock_frequency();
/* Print comments */
fp << "##################################################" << std::endl;
fp << "# Create programmable clock " << std::endl;
@ -93,6 +92,15 @@ void print_pnr_sdc_global_clock_ports(std::fstream& fp,
for (const size_t& pin : clock_port.pins()) {
BasicPort port_to_constrain(clock_port.get_name(), pin, pin);
/* Should try to find a port defintion from simulation parameters
* If found, it means that we need to use special clock name!
*/
for (const SimulationClockId& sim_clock : sim_setting.clocks()) {
if (port_to_constrain == sim_setting.clock_port(sim_clock)) {
clock_period = 1./sim_setting.clock_frequency(sim_clock);
}
}
print_pnr_sdc_clock_port(fp,
port_to_constrain,
clock_period);
@ -153,11 +161,10 @@ void print_pnr_sdc_global_non_clock_ports(std::fstream& fp,
* In general, we do not recommend to do this
*******************************************************************/
void print_pnr_sdc_global_ports(const std::string& sdc_dir,
const float& programming_critical_path_delay,
const float& operating_critical_path_delay,
const ModuleManager& module_manager,
const ModuleId& top_module,
const FabricGlobalPortInfo& global_ports,
const SimulationSetting& sim_setting,
const bool& constrain_non_clock_port) {
/* Create the file name for Verilog netlist */
@ -177,14 +184,12 @@ void print_pnr_sdc_global_ports(const std::string& sdc_dir,
print_sdc_file_header(fp, std::string("Clock contraints for PnR"));
print_pnr_sdc_global_clock_ports(fp,
programming_critical_path_delay,
operating_critical_path_delay,
module_manager, top_module,
global_ports);
global_ports, sim_setting);
if (true == constrain_non_clock_port) {
print_pnr_sdc_global_non_clock_ports(fp,
operating_critical_path_delay,
1./sim_setting.default_operating_clock_frequency(),
module_manager, top_module,
global_ports);

View File

@ -8,6 +8,7 @@
#include <vector>
#include "module_manager.h"
#include "fabric_global_port_info.h"
#include "simulation_setting.h"
/********************************************************************
* Function declaration
@ -17,11 +18,10 @@
namespace openfpga {
void print_pnr_sdc_global_ports(const std::string& sdc_dir,
const float& programming_critical_path_delay,
const float& operating_critical_path_delay,
const ModuleManager& module_manager,
const ModuleId& top_module,
const FabricGlobalPortInfo& global_ports,
const SimulationSetting& sim_setting,
const bool& constrain_non_clock_port);
} /* end namespace openfpga */

View File

@ -319,8 +319,6 @@ void print_pnr_sdc_compact_routing_disable_switch_block_outputs(const std::strin
* 4. Design constraints for breaking the combinational loops in FPGA fabric
*******************************************************************/
void print_pnr_sdc(const PnrSdcOption& sdc_options,
const float& programming_critical_path_delay,
const float& operating_critical_path_delay,
const DeviceContext& device_ctx,
const VprDeviceAnnotation& device_annotation,
const DeviceRRGSB& device_rr_gsb,
@ -328,6 +326,7 @@ void print_pnr_sdc(const PnrSdcOption& sdc_options,
const MuxLibrary& mux_lib,
const CircuitLibrary& circuit_lib,
const FabricGlobalPortInfo& global_ports,
const SimulationSetting& sim_setting,
const bool& compact_routing_hierarchy) {
std::string top_module_name = generate_fpga_top_module_name();
@ -337,9 +336,8 @@ void print_pnr_sdc(const PnrSdcOption& sdc_options,
/* Constrain global ports */
if (true == sdc_options.constrain_global_port()) {
print_pnr_sdc_global_ports(sdc_options.sdc_dir(),
programming_critical_path_delay,
operating_critical_path_delay,
module_manager, top_module, global_ports,
sim_setting,
sdc_options.constrain_non_clock_global_port());
}

View File

@ -12,6 +12,7 @@
#include "module_manager.h"
#include "mux_library.h"
#include "circuit_library.h"
#include "simulation_setting.h"
#include "fabric_global_port_info.h"
#include "pnr_sdc_option.h"
@ -23,8 +24,6 @@
namespace openfpga {
void print_pnr_sdc(const PnrSdcOption& sdc_options,
const float& programming_critical_path_delay,
const float& operating_critical_path_delay,
const DeviceContext& device_ctx,
const VprDeviceAnnotation& device_annotation,
const DeviceRRGSB& device_rr_gsb,
@ -32,6 +31,7 @@ void print_pnr_sdc(const PnrSdcOption& sdc_options,
const MuxLibrary& mux_lib,
const CircuitLibrary& circuit_lib,
const FabricGlobalPortInfo& global_ports,
const SimulationSetting& sim_setting,
const bool& compact_routing_hierarchy);
} /* end namespace openfpga */

View File

@ -7,6 +7,8 @@
#include "vtr_assert.h"
#include "vtr_time.h"
#include "command_exit_codes.h"
#include "circuit_library_utils.h"
/* Headers from openfpgautil library */
@ -147,18 +149,19 @@ void fpga_fabric_verilog(ModuleManager &module_manager,
* This testbench is created for quick verification and formal verification purpose.
* - Verilog netlist including preprocessing flags and all the Verilog netlists that have been generated
********************************************************************/
void fpga_verilog_testbench(const ModuleManager &module_manager,
const BitstreamManager &bitstream_manager,
const FabricBitstream &fabric_bitstream,
const AtomContext &atom_ctx,
const PlacementContext &place_ctx,
const IoLocationMap &io_location_map,
const FabricGlobalPortInfo &fabric_global_port_info,
const VprNetlistAnnotation &netlist_annotation,
const CircuitLibrary &circuit_lib,
const SimulationSetting &simulation_setting,
const ConfigProtocol &config_protocol,
const VerilogTestbenchOption &options) {
int fpga_verilog_testbench(const ModuleManager &module_manager,
const BitstreamManager &bitstream_manager,
const FabricBitstream &fabric_bitstream,
const AtomContext &atom_ctx,
const PlacementContext &place_ctx,
const PinConstraints& pin_constraints,
const IoLocationMap &io_location_map,
const FabricGlobalPortInfo &fabric_global_port_info,
const VprNetlistAnnotation &netlist_annotation,
const CircuitLibrary &circuit_lib,
const SimulationSetting &simulation_setting,
const ConfigProtocol &config_protocol,
const VerilogTestbenchOption &options) {
vtr::ScopedStartFinishTimer timer("Write Verilog testbenches for FPGA fabric\n");
@ -166,6 +169,8 @@ void fpga_verilog_testbench(const ModuleManager &module_manager,
std::string netlist_name = atom_ctx.nlist.netlist_name();
int status = CMD_EXEC_SUCCESS;
/* Create directories */
create_directory(src_dir_path);
@ -176,14 +181,19 @@ void fpga_verilog_testbench(const ModuleManager &module_manager,
/* Generate wrapper module for FPGA fabric (mapped by the input benchmark and pre-configured testbench for verification */
if (true == options.print_formal_verification_top_netlist()) {
std::string formal_verification_top_netlist_file_path = src_dir_path + netlist_name + std::string(FORMAL_VERIFICATION_VERILOG_FILE_POSTFIX);
print_verilog_preconfig_top_module(module_manager, bitstream_manager,
config_protocol,
circuit_lib, fabric_global_port_info,
atom_ctx, place_ctx, io_location_map,
netlist_annotation,
netlist_name,
formal_verification_top_netlist_file_path,
options.explicit_port_mapping());
status = print_verilog_preconfig_top_module(module_manager, bitstream_manager,
config_protocol,
circuit_lib, fabric_global_port_info,
atom_ctx, place_ctx,
pin_constraints,
io_location_map,
netlist_annotation,
netlist_name,
formal_verification_top_netlist_file_path,
options.explicit_port_mapping());
if (status == CMD_EXEC_FATAL_ERROR) {
return status;
}
}
if (true == options.print_preconfig_top_testbench()) {
@ -193,6 +203,7 @@ void fpga_verilog_testbench(const ModuleManager &module_manager,
random_top_testbench_file_path,
atom_ctx,
netlist_annotation,
pin_constraints,
simulation_setting,
options.explicit_port_mapping());
}
@ -205,7 +216,9 @@ void fpga_verilog_testbench(const ModuleManager &module_manager,
circuit_lib,
config_protocol,
fabric_global_port_info,
atom_ctx, place_ctx, io_location_map,
atom_ctx, place_ctx,
pin_constraints,
io_location_map,
netlist_annotation,
netlist_name,
top_testbench_file_path,
@ -226,7 +239,7 @@ void fpga_verilog_testbench(const ModuleManager &module_manager,
bitstream_manager.num_bits(),
simulation_setting.num_clock_cycles(),
simulation_setting.programming_clock_frequency(),
simulation_setting.operating_clock_frequency());
simulation_setting.default_operating_clock_frequency());
}
/* Generate a Verilog file including all the netlists that have been generated */
@ -234,6 +247,8 @@ void fpga_verilog_testbench(const ModuleManager &module_manager,
netlist_name,
options.fabric_netlist_file_path(),
options.reference_benchmark_file_path());
return status;
}
} /* end namespace openfpga */

View File

@ -19,6 +19,7 @@
#include "bitstream_manager.h"
#include "fabric_bitstream.h"
#include "simulation_setting.h"
#include "pin_constraints.h"
#include "io_location_map.h"
#include "fabric_global_port_info.h"
#include "vpr_netlist_annotation.h"
@ -42,18 +43,19 @@ void fpga_fabric_verilog(ModuleManager& module_manager,
const DeviceRRGSB& device_rr_gsb,
const FabricVerilogOption& options);
void fpga_verilog_testbench(const ModuleManager& module_manager,
const BitstreamManager& bitstream_manager,
const FabricBitstream& fabric_bitstream,
const AtomContext& atom_ctx,
const PlacementContext& place_ctx,
const IoLocationMap& io_location_map,
const FabricGlobalPortInfo &fabric_global_port_info,
const VprNetlistAnnotation& netlist_annotation,
const CircuitLibrary& circuit_lib,
const SimulationSetting& simulation_parameters,
const ConfigProtocol& config_protocol,
const VerilogTestbenchOption& options);
int fpga_verilog_testbench(const ModuleManager& module_manager,
const BitstreamManager& bitstream_manager,
const FabricBitstream& fabric_bitstream,
const AtomContext& atom_ctx,
const PlacementContext& place_ctx,
const PinConstraints& pin_constraints,
const IoLocationMap& io_location_map,
const FabricGlobalPortInfo &fabric_global_port_info,
const VprNetlistAnnotation& netlist_annotation,
const CircuitLibrary& circuit_lib,
const SimulationSetting& simulation_parameters,
const ConfigProtocol& config_protocol,
const VerilogTestbenchOption& options);
} /* end namespace openfpga */

View File

@ -65,9 +65,11 @@ void print_verilog_top_random_testbench_ports(std::fstream& fp,
/* Create a clock port if the benchmark does not have one!
* The clock is used for counting and synchronizing input stimulus
*/
BasicPort clock_port = generate_verilog_testbench_clock_port(clock_port_names, std::string(DEFAULT_CLOCK_NAME));
std::vector<BasicPort> clock_ports = generate_verilog_testbench_clock_port(clock_port_names, std::string(DEFAULT_CLOCK_NAME));
print_verilog_comment(fp, std::string("----- Default clock port is added here since benchmark does not contain one -------"));
fp << "\t" << generate_verilog_port(VERILOG_PORT_REG, clock_port) << ";" << std::endl;
for (const BasicPort& clock_port : clock_ports) {
fp << "\t" << generate_verilog_port(VERILOG_PORT_REG, clock_port) << ";" << std::endl;
}
/* Add an empty line as splitter */
fp << std::endl;
@ -192,6 +194,7 @@ void print_verilog_random_top_testbench(const std::string& circuit_name,
const std::string& verilog_fname,
const AtomContext& atom_ctx,
const VprNetlistAnnotation& netlist_annotation,
const PinConstraints& pin_constraints,
const SimulationSetting& simulation_parameters,
const bool& explicit_port_mapping) {
std::string timer_message = std::string("Write configuration-skip testbench for FPGA top-level Verilog netlist implemented by '") + circuit_name.c_str() + std::string("'");
@ -227,16 +230,18 @@ void print_verilog_random_top_testbench(const std::string& circuit_name,
explicit_port_mapping);
/* Find clock port to be used */
BasicPort clock_port = generate_verilog_testbench_clock_port(clock_port_names, std::string(DEFAULT_CLOCK_NAME));
std::vector<BasicPort> clock_ports = generate_verilog_testbench_clock_port(clock_port_names, std::string(DEFAULT_CLOCK_NAME));
/* Add stimuli for reset, set, clock and iopad signals */
print_verilog_testbench_clock_stimuli(fp, simulation_parameters,
clock_port);
print_verilog_testbench_clock_stimuli(fp,
pin_constraints,
simulation_parameters,
clock_ports);
print_verilog_testbench_random_stimuli(fp, atom_ctx,
netlist_annotation,
clock_port_names,
std::string(CHECKFLAG_PORT_POSTFIX),
clock_port);
clock_ports);
print_verilog_testbench_check(fp,
std::string(AUTOCHECKED_SIMULATION_FLAG),
@ -252,7 +257,7 @@ void print_verilog_random_top_testbench(const std::string& circuit_name,
float simulation_time = find_operating_phase_simulation_time(MAGIC_NUMBER_FOR_SIMULATION_TIME,
simulation_parameters.num_clock_cycles(),
1./simulation_parameters.operating_clock_frequency(),
1./simulation_parameters.default_operating_clock_frequency(),
VERILOG_SIM_TIMESCALE);
/* Add Icarus requirement */

View File

@ -6,6 +6,7 @@
*******************************************************************/
#include <string>
#include "vpr_context.h"
#include "pin_constraints.h"
#include "simulation_setting.h"
/********************************************************************
@ -19,6 +20,7 @@ void print_verilog_random_top_testbench(const std::string& circuit_name,
const std::string& verilog_fname,
const AtomContext& atom_ctx,
const VprNetlistAnnotation& netlist_annotation,
const PinConstraints& pin_constraints,
const SimulationSetting& simulation_parameters,
const bool& explicit_port_mapping);

View File

@ -9,6 +9,8 @@
#include "vtr_log.h"
#include "vtr_time.h"
#include "command_exit_codes.h"
/* Headers from openfpgautil library */
#include "openfpga_port.h"
#include "openfpga_digest.h"
@ -24,254 +26,218 @@
#include "verilog_preconfig_top_module.h"
/* begin namespace openfpga */
namespace openfpga
{
namespace openfpga {
/********************************************************************
/********************************************************************
* Print module declaration and ports for the pre-configured
* FPGA top module
* The module ports do exactly match the input benchmark
*******************************************************************/
static void print_verilog_preconfig_top_module_ports(std::fstream &fp,
const std::string &circuit_name,
const AtomContext &atom_ctx,
const VprNetlistAnnotation &netlist_annotation)
{
static
void print_verilog_preconfig_top_module_ports(std::fstream &fp,
const std::string &circuit_name,
const AtomContext &atom_ctx,
const VprNetlistAnnotation &netlist_annotation) {
/* Validate the file stream */
valid_file_stream(fp);
/* Validate the file stream */
valid_file_stream(fp);
/* Module declaration */
fp << "module " << circuit_name << std::string(FORMAL_VERIFICATION_TOP_MODULE_POSTFIX);
fp << " (" << std::endl;
/* Module declaration */
fp << "module " << circuit_name << std::string(FORMAL_VERIFICATION_TOP_MODULE_POSTFIX);
fp << " (" << std::endl;
/* Add module ports */
size_t port_counter = 0;
/* Add module ports */
size_t port_counter = 0;
/* Port type-to-type mapping */
std::map<AtomBlockType, enum e_dump_verilog_port_type> port_type2type_map;
port_type2type_map[AtomBlockType::INPAD] = VERILOG_PORT_INPUT;
port_type2type_map[AtomBlockType::OUTPAD] = VERILOG_PORT_OUTPUT;
/* Port type-to-type mapping */
std::map<AtomBlockType, enum e_dump_verilog_port_type> port_type2type_map;
port_type2type_map[AtomBlockType::INPAD] = VERILOG_PORT_INPUT;
port_type2type_map[AtomBlockType::OUTPAD] = VERILOG_PORT_OUTPUT;
/* Print all the I/Os of the circuit implementation to be tested*/
for (const AtomBlockId &atom_blk : atom_ctx.nlist.blocks())
{
/* We only care I/O logical blocks !*/
if ((AtomBlockType::INPAD != atom_ctx.nlist.block_type(atom_blk)) && (AtomBlockType::OUTPAD != atom_ctx.nlist.block_type(atom_blk)))
{
continue;
}
/* The block may be renamed as it contains special characters which violate Verilog syntax */
std::string block_name = atom_ctx.nlist.block_name(atom_blk);
if (true == netlist_annotation.is_block_renamed(atom_blk))
{
block_name = netlist_annotation.block_name(atom_blk);
}
if (0 < port_counter)
{
fp << "," << std::endl;
}
/* Both input and output ports have only size of 1 */
BasicPort module_port(std::string(block_name + std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX)), 1);
fp << generate_verilog_port(port_type2type_map[atom_ctx.nlist.block_type(atom_blk)], module_port);
/* Update port counter */
port_counter++;
/* Print all the I/Os of the circuit implementation to be tested*/
for (const AtomBlockId &atom_blk : atom_ctx.nlist.blocks()) {
/* We only care I/O logical blocks !*/
if ((AtomBlockType::INPAD != atom_ctx.nlist.block_type(atom_blk)) && (AtomBlockType::OUTPAD != atom_ctx.nlist.block_type(atom_blk))) {
continue;
}
fp << ");" << std::endl;
/* The block may be renamed as it contains special characters which violate Verilog syntax */
std::string block_name = atom_ctx.nlist.block_name(atom_blk);
if (true == netlist_annotation.is_block_renamed(atom_blk)) {
block_name = netlist_annotation.block_name(atom_blk);
}
/* Add an empty line as a splitter */
fp << std::endl;
if (0 < port_counter) {
fp << "," << std::endl;
}
/* Both input and output ports have only size of 1 */
BasicPort module_port(std::string(block_name + std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX)), 1);
fp << generate_verilog_port(port_type2type_map[atom_ctx.nlist.block_type(atom_blk)], module_port);
/* Update port counter */
port_counter++;
}
/********************************************************************
fp << ");" << std::endl;
/* Add an empty line as a splitter */
fp << std::endl;
}
/********************************************************************
* Print internal wires for the pre-configured FPGA top module
* The internal wires are tailored for the ports of FPGA top module
* which will be different in various configuration protocols
*******************************************************************/
static void print_verilog_preconfig_top_module_internal_wires(std::fstream &fp,
const ModuleManager &module_manager,
const ModuleId &top_module)
{
/* Validate the file stream */
valid_file_stream(fp);
static
void print_verilog_preconfig_top_module_internal_wires(std::fstream &fp,
const ModuleManager &module_manager,
const ModuleId &top_module) {
/* Validate the file stream */
valid_file_stream(fp);
/* Global ports of top-level module */
print_verilog_comment(fp, std::string("----- Local wires for FPGA fabric -----"));
for (const ModulePortId &module_port_id : module_manager.module_ports(top_module))
{
BasicPort module_port = module_manager.module_port(top_module, module_port_id);
fp << generate_verilog_port(VERILOG_PORT_WIRE, module_port) << ";" << std::endl;
}
/* Add an empty line as a splitter */
fp << std::endl;
/* Global ports of top-level module */
print_verilog_comment(fp, std::string("----- Local wires for FPGA fabric -----"));
for (const ModulePortId &module_port_id : module_manager.module_ports(top_module)) {
BasicPort module_port = module_manager.module_port(top_module, module_port_id);
fp << generate_verilog_port(VERILOG_PORT_WIRE, module_port) << ";" << std::endl;
}
/* Add an empty line as a splitter */
fp << std::endl;
}
/********************************************************************
/********************************************************************
* Connect global ports of FPGA top module to constants except:
* 1. operating clock, which should be wired to the clock port of
* this pre-configured FPGA top module
*******************************************************************/
static void print_verilog_preconfig_top_module_connect_global_ports(std::fstream &fp,
const ModuleManager &module_manager,
const ModuleId &top_module,
const FabricGlobalPortInfo &fabric_global_ports,
const std::vector<std::string> &benchmark_clock_port_names)
{
/* Validate the file stream */
valid_file_stream(fp);
static
int print_verilog_preconfig_top_module_connect_global_ports(std::fstream &fp,
const ModuleManager &module_manager,
const ModuleId &top_module,
const PinConstraints& pin_constraints,
const FabricGlobalPortInfo &fabric_global_ports,
const std::vector<std::string> &benchmark_clock_port_names) {
/* Validate the file stream */
valid_file_stream(fp);
print_verilog_comment(fp, std::string("----- Begin Connect Global ports of FPGA top module -----"));
print_verilog_comment(fp, std::string("----- Begin Connect Global ports of FPGA top module -----"));
for (const FabricGlobalPortId& global_port_id : fabric_global_ports.global_ports()) {
ModulePortId module_global_port_id = fabric_global_ports.global_module_port(global_port_id);
VTR_ASSERT(ModuleManager::MODULE_GLOBAL_PORT == module_manager.port_type(top_module, module_global_port_id));
BasicPort module_global_port = module_manager.module_port(top_module, module_global_port_id);
/* Now, for operating clock port, we should wire it to the clock of benchmark! */
if ((true == fabric_global_ports.global_port_is_clock(global_port_id))
&& (false == fabric_global_ports.global_port_is_prog(global_port_id))) {
/* Wiring to each pin of the global port: benchmark clock is always 1-bit */
for (const size_t &pin : module_global_port.pins()) {
for (const std::string &clock_port_name : benchmark_clock_port_names) {
BasicPort module_clock_pin(module_global_port.get_name(), pin, pin);
BasicPort benchmark_clock_pin(clock_port_name + std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX), 1);
print_verilog_wire_connection(fp, module_clock_pin, benchmark_clock_pin, false);
for (const FabricGlobalPortId& global_port_id : fabric_global_ports.global_ports()) {
ModulePortId module_global_port_id = fabric_global_ports.global_module_port(global_port_id);
VTR_ASSERT(ModuleManager::MODULE_GLOBAL_PORT == module_manager.port_type(top_module, module_global_port_id));
BasicPort module_global_port = module_manager.module_port(top_module, module_global_port_id);
/* Now, for operating clock port, we should wire it to the clock of benchmark! */
if ((true == fabric_global_ports.global_port_is_clock(global_port_id))
&& (false == fabric_global_ports.global_port_is_prog(global_port_id))) {
/* Wiring to each pin of the global port: benchmark clock is always 1-bit */
for (size_t pin_id = 0; pin_id < module_global_port.pins().size(); ++pin_id) {
BasicPort module_clock_pin(module_global_port.get_name(), module_global_port.pins()[pin_id], module_global_port.pins()[pin_id]);
/* If the clock port name is in the pin constraints, we should wire it to the constrained pin */
std::string constrained_net_name;
for (const PinConstraintId& pin_constraint : pin_constraints.pin_constraints()) {
if (module_clock_pin == pin_constraints.pin(pin_constraint)) {
constrained_net_name = pin_constraints.net(pin_constraint);
break;
}
}
/* Finish, go to the next */
continue;
}
/* For other ports, give an default value */
std::vector<size_t> default_values(module_global_port.get_width(), fabric_global_ports.global_port_default_value(global_port_id));
print_verilog_wire_constant_values(fp, module_global_port, default_values);
/* If constrained to an open net or there is no clock in the benchmark, we assign it to a default value */
if ( (std::string(PIN_CONSTRAINT_OPEN_NET) == constrained_net_name)
|| (true == benchmark_clock_port_names.empty())) {
std::vector<size_t> default_values(1, fabric_global_ports.global_port_default_value(global_port_id));
print_verilog_wire_constant_values(fp, module_clock_pin, default_values);
continue;
}
std::string clock_name_to_connect;
if (!constrained_net_name.empty()) {
clock_name_to_connect = constrained_net_name;
} else {
/* Otherwise, we must have a clear one-to-one clock net corresponding!!! */
if (benchmark_clock_port_names.size() != module_global_port.get_width()) {
VTR_LOG_ERROR("Unable to map %lu benchmark clocks to %lu clock pins of FPGA!\nRequire clear pin constraints!\n",
benchmark_clock_port_names.size(),
module_global_port.get_width());
return CMD_EXEC_FATAL_ERROR;
}
clock_name_to_connect = benchmark_clock_port_names[pin_id];
}
BasicPort benchmark_clock_pin(clock_name_to_connect + std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX), 1);
print_verilog_wire_connection(fp, module_clock_pin, benchmark_clock_pin, false);
}
/* Finish, go to the next */
continue;
}
print_verilog_comment(fp, std::string("----- End Connect Global ports of FPGA top module -----"));
/* Add an empty line as a splitter */
fp << std::endl;
/* For other ports, give an default value */
std::vector<size_t> default_values(module_global_port.get_width(), fabric_global_ports.global_port_default_value(global_port_id));
print_verilog_wire_constant_values(fp, module_global_port, default_values);
}
/********************************************************************
print_verilog_comment(fp, std::string("----- End Connect Global ports of FPGA top module -----"));
/* Add an empty line as a splitter */
fp << std::endl;
return CMD_EXEC_SUCCESS;
}
/********************************************************************
* Impose the bitstream on the configuration memories
* This function uses 'assign' syntax to impost the bitstream at mem port
* while uses 'force' syntax to impost the bitstream at mem_inv port
*******************************************************************/
static void print_verilog_preconfig_top_module_assign_bitstream(std::fstream &fp,
const ModuleManager &module_manager,
const ModuleId &top_module,
const BitstreamManager &bitstream_manager,
const bool& output_datab_bits)
{
/* Validate the file stream */
valid_file_stream(fp);
static
void print_verilog_preconfig_top_module_assign_bitstream(std::fstream &fp,
const ModuleManager &module_manager,
const ModuleId &top_module,
const BitstreamManager &bitstream_manager,
const bool& output_datab_bits) {
/* Validate the file stream */
valid_file_stream(fp);
print_verilog_comment(fp, std::string("----- Begin assign bitstream to configuration memories -----"));
print_verilog_comment(fp, std::string("----- Begin assign bitstream to configuration memories -----"));
for (const ConfigBlockId &config_block_id : bitstream_manager.blocks())
{
/* We only cares blocks with configuration bits */
if (0 == bitstream_manager.block_bits(config_block_id).size())
{
continue;
}
/* Build the hierarchical path of the configuration bit in modules */
std::vector<ConfigBlockId> block_hierarchy = find_bitstream_manager_block_hierarchy(bitstream_manager, config_block_id);
/* Drop the first block, which is the top module, it should be replaced by the instance name here */
/* Ensure that this is the module we want to drop! */
VTR_ASSERT(0 == module_manager.module_name(top_module).compare(bitstream_manager.block_name(block_hierarchy[0])));
block_hierarchy.erase(block_hierarchy.begin());
/* Build the full hierarchy path */
std::string bit_hierarchy_path(FORMAL_VERIFICATION_TOP_MODULE_UUT_NAME);
for (const ConfigBlockId &temp_block : block_hierarchy)
{
bit_hierarchy_path += std::string(".");
bit_hierarchy_path += bitstream_manager.block_name(temp_block);
}
for (const ConfigBlockId &config_block_id : bitstream_manager.blocks()) {
/* We only cares blocks with configuration bits */
if (0 == bitstream_manager.block_bits(config_block_id).size()) {
continue;
}
/* Build the hierarchical path of the configuration bit in modules */
std::vector<ConfigBlockId> block_hierarchy = find_bitstream_manager_block_hierarchy(bitstream_manager, config_block_id);
/* Drop the first block, which is the top module, it should be replaced by the instance name here */
/* Ensure that this is the module we want to drop! */
VTR_ASSERT(0 == module_manager.module_name(top_module).compare(bitstream_manager.block_name(block_hierarchy[0])));
block_hierarchy.erase(block_hierarchy.begin());
/* Build the full hierarchy path */
std::string bit_hierarchy_path(FORMAL_VERIFICATION_TOP_MODULE_UUT_NAME);
for (const ConfigBlockId &temp_block : block_hierarchy) {
bit_hierarchy_path += std::string(".");
/* Find the bit index in the parent block */
BasicPort config_data_port(bit_hierarchy_path + generate_configurable_memory_data_out_name(),
bitstream_manager.block_bits(config_block_id).size());
/* Wire it to the configuration bit: access both data out and data outb ports */
std::vector<size_t> config_data_values;
for (const ConfigBitId config_bit : bitstream_manager.block_bits(config_block_id))
{
config_data_values.push_back(bitstream_manager.bit_value(config_bit));
}
print_verilog_wire_constant_values(fp, config_data_port, config_data_values);
bit_hierarchy_path += bitstream_manager.block_name(temp_block);
}
bit_hierarchy_path += std::string(".");
if (true == output_datab_bits) {
fp << "initial begin" << std::endl;
/* Find the bit index in the parent block */
BasicPort config_data_port(bit_hierarchy_path + generate_configurable_memory_data_out_name(),
bitstream_manager.block_bits(config_block_id).size());
for (const ConfigBlockId &config_block_id : bitstream_manager.blocks())
{
/* We only cares blocks with configuration bits */
if (0 == bitstream_manager.block_bits(config_block_id).size())
{
continue;
}
/* Build the hierarchical path of the configuration bit in modules */
std::vector<ConfigBlockId> block_hierarchy = find_bitstream_manager_block_hierarchy(bitstream_manager, config_block_id);
/* Drop the first block, which is the top module, it should be replaced by the instance name here */
/* Ensure that this is the module we want to drop! */
VTR_ASSERT(0 == module_manager.module_name(top_module).compare(bitstream_manager.block_name(block_hierarchy[0])));
block_hierarchy.erase(block_hierarchy.begin());
/* Build the full hierarchy path */
std::string bit_hierarchy_path(FORMAL_VERIFICATION_TOP_MODULE_UUT_NAME);
for (const ConfigBlockId &temp_block : block_hierarchy)
{
bit_hierarchy_path += std::string(".");
bit_hierarchy_path += bitstream_manager.block_name(temp_block);
}
bit_hierarchy_path += std::string(".");
/* Find the bit index in the parent block */
BasicPort config_datab_port(bit_hierarchy_path + generate_configurable_memory_inverted_data_out_name(),
bitstream_manager.block_bits(config_block_id).size());
std::vector<size_t> config_datab_values;
for (const ConfigBitId config_bit : bitstream_manager.block_bits(config_block_id))
{
config_datab_values.push_back(!bitstream_manager.bit_value(config_bit));
}
print_verilog_force_wire_constant_values(fp, config_datab_port, config_datab_values);
}
fp << "end" << std::endl;
/* Wire it to the configuration bit: access both data out and data outb ports */
std::vector<size_t> config_data_values;
for (const ConfigBitId config_bit : bitstream_manager.block_bits(config_block_id)) {
config_data_values.push_back(bitstream_manager.bit_value(config_bit));
}
print_verilog_comment(fp, std::string("----- End assign bitstream to configuration memories -----"));
print_verilog_wire_constant_values(fp, config_data_port, config_data_values);
}
/********************************************************************
* Impose the bitstream on the configuration memories
* This function uses '$deposit' syntax to do so
*******************************************************************/
static void print_verilog_preconfig_top_module_deposit_bitstream(std::fstream &fp,
const ModuleManager &module_manager,
const ModuleId &top_module,
const BitstreamManager &bitstream_manager,
const bool& output_datab_bits)
{
/* Validate the file stream */
valid_file_stream(fp);
print_verilog_comment(fp, std::string("----- Begin deposit bitstream to configuration memories -----"));
if (true == output_datab_bits) {
fp << "initial begin" << std::endl;
for (const ConfigBlockId &config_block_id : bitstream_manager.blocks())
{
for (const ConfigBlockId &config_block_id : bitstream_manager.blocks()) {
/* We only cares blocks with configuration bits */
if (0 == bitstream_manager.block_bits(config_block_id).size())
{
if (0 == bitstream_manager.block_bits(config_block_id).size()) {
continue;
}
/* Build the hierarchical path of the configuration bit in modules */
@ -282,94 +248,144 @@ namespace openfpga
block_hierarchy.erase(block_hierarchy.begin());
/* Build the full hierarchy path */
std::string bit_hierarchy_path(FORMAL_VERIFICATION_TOP_MODULE_UUT_NAME);
for (const ConfigBlockId &temp_block : block_hierarchy)
{
for (const ConfigBlockId &temp_block : block_hierarchy) {
bit_hierarchy_path += std::string(".");
bit_hierarchy_path += bitstream_manager.block_name(temp_block);
}
bit_hierarchy_path += std::string(".");
/* Find the bit index in the parent block */
BasicPort config_data_port(bit_hierarchy_path + generate_configurable_memory_data_out_name(),
bitstream_manager.block_bits(config_block_id).size());
/* Wire it to the configuration bit: access both data out and data outb ports */
std::vector<size_t> config_data_values;
for (const ConfigBitId config_bit : bitstream_manager.block_bits(config_block_id))
{
config_data_values.push_back(bitstream_manager.bit_value(config_bit));
}
print_verilog_deposit_wire_constant_values(fp, config_data_port, config_data_values);
/* Skip datab ports if specified */
if (false == output_datab_bits) {
continue;
}
BasicPort config_datab_port(bit_hierarchy_path + generate_configurable_memory_inverted_data_out_name(),
bitstream_manager.block_bits(config_block_id).size());
std::vector<size_t> config_datab_values;
for (const ConfigBitId config_bit : bitstream_manager.block_bits(config_block_id))
{
for (const ConfigBitId config_bit : bitstream_manager.block_bits(config_block_id)) {
config_datab_values.push_back(!bitstream_manager.bit_value(config_bit));
}
print_verilog_deposit_wire_constant_values(fp, config_datab_port, config_datab_values);
print_verilog_force_wire_constant_values(fp, config_datab_port, config_datab_values);
}
fp << "end" << std::endl;
print_verilog_comment(fp, std::string("----- End deposit bitstream to configuration memories -----"));
}
/********************************************************************
print_verilog_comment(fp, std::string("----- End assign bitstream to configuration memories -----"));
}
/********************************************************************
* Impose the bitstream on the configuration memories
* This function uses '$deposit' syntax to do so
*******************************************************************/
static
void print_verilog_preconfig_top_module_deposit_bitstream(std::fstream &fp,
const ModuleManager &module_manager,
const ModuleId &top_module,
const BitstreamManager &bitstream_manager,
const bool& output_datab_bits) {
/* Validate the file stream */
valid_file_stream(fp);
print_verilog_comment(fp, std::string("----- Begin deposit bitstream to configuration memories -----"));
fp << "initial begin" << std::endl;
for (const ConfigBlockId &config_block_id : bitstream_manager.blocks()) {
/* We only cares blocks with configuration bits */
if (0 == bitstream_manager.block_bits(config_block_id).size()) {
continue;
}
/* Build the hierarchical path of the configuration bit in modules */
std::vector<ConfigBlockId> block_hierarchy = find_bitstream_manager_block_hierarchy(bitstream_manager, config_block_id);
/* Drop the first block, which is the top module, it should be replaced by the instance name here */
/* Ensure that this is the module we want to drop! */
VTR_ASSERT(0 == module_manager.module_name(top_module).compare(bitstream_manager.block_name(block_hierarchy[0])));
block_hierarchy.erase(block_hierarchy.begin());
/* Build the full hierarchy path */
std::string bit_hierarchy_path(FORMAL_VERIFICATION_TOP_MODULE_UUT_NAME);
for (const ConfigBlockId &temp_block : block_hierarchy) {
bit_hierarchy_path += std::string(".");
bit_hierarchy_path += bitstream_manager.block_name(temp_block);
}
bit_hierarchy_path += std::string(".");
/* Find the bit index in the parent block */
BasicPort config_data_port(bit_hierarchy_path + generate_configurable_memory_data_out_name(),
bitstream_manager.block_bits(config_block_id).size());
/* Wire it to the configuration bit: access both data out and data outb ports */
std::vector<size_t> config_data_values;
for (const ConfigBitId config_bit : bitstream_manager.block_bits(config_block_id)) {
config_data_values.push_back(bitstream_manager.bit_value(config_bit));
}
print_verilog_deposit_wire_constant_values(fp, config_data_port, config_data_values);
/* Skip datab ports if specified */
if (false == output_datab_bits) {
continue;
}
BasicPort config_datab_port(bit_hierarchy_path + generate_configurable_memory_inverted_data_out_name(),
bitstream_manager.block_bits(config_block_id).size());
std::vector<size_t> config_datab_values;
for (const ConfigBitId config_bit : bitstream_manager.block_bits(config_block_id)) {
config_datab_values.push_back(!bitstream_manager.bit_value(config_bit));
}
print_verilog_deposit_wire_constant_values(fp, config_datab_port, config_datab_values);
}
fp << "end" << std::endl;
print_verilog_comment(fp, std::string("----- End deposit bitstream to configuration memories -----"));
}
/********************************************************************
* Impose the bitstream on the configuration memories
* We branch here for different simulators:
* 1. iVerilog Icarus prefers using 'assign' syntax to force the values
* 2. Mentor Modelsim prefers using '$deposit' syntax to do so
*******************************************************************/
static void print_verilog_preconfig_top_module_load_bitstream(std::fstream &fp,
const ModuleManager &module_manager,
const ModuleId &top_module,
const CircuitLibrary& circuit_lib,
const CircuitModelId& mem_model,
const BitstreamManager &bitstream_manager)
{
static
void print_verilog_preconfig_top_module_load_bitstream(std::fstream &fp,
const ModuleManager &module_manager,
const ModuleId &top_module,
const CircuitLibrary& circuit_lib,
const CircuitModelId& mem_model,
const BitstreamManager &bitstream_manager) {
/* Skip the datab port if there is only 1 output port in memory model
* Currently, it assumes that the data output port is always defined while datab is optional
* If we see only 1 port, we assume datab is not defined by default.
* TODO: this switch could be smarter: it should identify if only data or datab
* ports are defined.
*/
bool output_datab_bits = true;
if (1 == circuit_lib.model_ports_by_type(mem_model, CIRCUIT_MODEL_PORT_OUTPUT).size()) {
output_datab_bits = false;
}
print_verilog_comment(fp, std::string("----- Begin load bitstream to configuration memories -----"));
print_verilog_preprocessing_flag(fp, std::string(ICARUS_SIMULATOR_FLAG));
/* Use assign syntax for Icarus simulator */
print_verilog_preconfig_top_module_assign_bitstream(fp, module_manager, top_module,
bitstream_manager,
output_datab_bits);
fp << "`else" << std::endl;
/* Use assign syntax for Icarus simulator */
print_verilog_preconfig_top_module_deposit_bitstream(fp, module_manager, top_module,
bitstream_manager,
output_datab_bits);
print_verilog_endif(fp);
print_verilog_comment(fp, std::string("----- End load bitstream to configuration memories -----"));
/* Skip the datab port if there is only 1 output port in memory model
* Currently, it assumes that the data output port is always defined while datab is optional
* If we see only 1 port, we assume datab is not defined by default.
* TODO: this switch could be smarter: it should identify if only data or datab
* ports are defined.
*/
bool output_datab_bits = true;
if (1 == circuit_lib.model_ports_by_type(mem_model, CIRCUIT_MODEL_PORT_OUTPUT).size()) {
output_datab_bits = false;
}
/********************************************************************
print_verilog_comment(fp, std::string("----- Begin load bitstream to configuration memories -----"));
print_verilog_preprocessing_flag(fp, std::string(ICARUS_SIMULATOR_FLAG));
/* Use assign syntax for Icarus simulator */
print_verilog_preconfig_top_module_assign_bitstream(fp, module_manager, top_module,
bitstream_manager,
output_datab_bits);
fp << "`else" << std::endl;
/* Use assign syntax for Icarus simulator */
print_verilog_preconfig_top_module_deposit_bitstream(fp, module_manager, top_module,
bitstream_manager,
output_datab_bits);
print_verilog_endif(fp);
print_verilog_comment(fp, std::string("----- End load bitstream to configuration memories -----"));
}
/********************************************************************
* Top-level function to generate a Verilog module of
* a pre-configured FPGA fabric.
*
@ -401,87 +417,94 @@ namespace openfpga
* It includes wires to force constant values to part of FPGA datapath I/Os
* All these are hard to implement as a module in module manager
*******************************************************************/
void print_verilog_preconfig_top_module(const ModuleManager &module_manager,
const BitstreamManager &bitstream_manager,
const ConfigProtocol &config_protocol,
const CircuitLibrary &circuit_lib,
const FabricGlobalPortInfo &global_ports,
const AtomContext &atom_ctx,
const PlacementContext &place_ctx,
const IoLocationMap &io_location_map,
const VprNetlistAnnotation &netlist_annotation,
const std::string &circuit_name,
const std::string &verilog_fname,
const bool &explicit_port_mapping)
{
std::string timer_message = std::string("Write pre-configured FPGA top-level Verilog netlist for design '") + circuit_name + std::string("'");
int print_verilog_preconfig_top_module(const ModuleManager &module_manager,
const BitstreamManager &bitstream_manager,
const ConfigProtocol &config_protocol,
const CircuitLibrary &circuit_lib,
const FabricGlobalPortInfo &global_ports,
const AtomContext &atom_ctx,
const PlacementContext &place_ctx,
const PinConstraints& pin_constraints,
const IoLocationMap &io_location_map,
const VprNetlistAnnotation &netlist_annotation,
const std::string &circuit_name,
const std::string &verilog_fname,
const bool &explicit_port_mapping) {
std::string timer_message = std::string("Write pre-configured FPGA top-level Verilog netlist for design '") + circuit_name + std::string("'");
/* Start time count */
vtr::ScopedStartFinishTimer timer(timer_message);
int status = CMD_EXEC_SUCCESS;
/* Create the file stream */
std::fstream fp;
fp.open(verilog_fname, std::fstream::out | std::fstream::trunc);
/* Start time count */
vtr::ScopedStartFinishTimer timer(timer_message);
/* Validate the file stream */
check_file_stream(verilog_fname.c_str(), fp);
/* Create the file stream */
std::fstream fp;
fp.open(verilog_fname, std::fstream::out | std::fstream::trunc);
/* Generate a brief description on the Verilog file*/
std::string title = std::string("Verilog netlist for pre-configured FPGA fabric by design: ") + circuit_name;
print_verilog_file_header(fp, title);
/* Validate the file stream */
check_file_stream(verilog_fname.c_str(), fp);
/* Print module declaration and ports */
print_verilog_preconfig_top_module_ports(fp, circuit_name, atom_ctx, netlist_annotation);
/* Generate a brief description on the Verilog file*/
std::string title = std::string("Verilog netlist for pre-configured FPGA fabric by design: ") + circuit_name;
print_verilog_file_header(fp, title);
/* Find the top_module */
ModuleId top_module = module_manager.find_module(generate_fpga_top_module_name());
VTR_ASSERT(true == module_manager.valid_module_id(top_module));
/* Print module declaration and ports */
print_verilog_preconfig_top_module_ports(fp, circuit_name, atom_ctx, netlist_annotation);
/* Print internal wires */
print_verilog_preconfig_top_module_internal_wires(fp, module_manager, top_module);
/* Find the top_module */
ModuleId top_module = module_manager.find_module(generate_fpga_top_module_name());
VTR_ASSERT(true == module_manager.valid_module_id(top_module));
/* Instanciate FPGA top-level module */
print_verilog_testbench_fpga_instance(fp, module_manager, top_module,
std::string(FORMAL_VERIFICATION_TOP_MODULE_UUT_NAME),
explicit_port_mapping);
/* Print internal wires */
print_verilog_preconfig_top_module_internal_wires(fp, module_manager, top_module);
/* Find clock ports in benchmark */
std::vector<std::string> benchmark_clock_port_names = find_atom_netlist_clock_port_names(atom_ctx.nlist, netlist_annotation);
/* Instanciate FPGA top-level module */
print_verilog_testbench_fpga_instance(fp, module_manager, top_module,
std::string(FORMAL_VERIFICATION_TOP_MODULE_UUT_NAME),
explicit_port_mapping);
/* Connect FPGA top module global ports to constant or benchmark global signals! */
print_verilog_preconfig_top_module_connect_global_ports(fp, module_manager, top_module,
global_ports,
benchmark_clock_port_names);
/* Find clock ports in benchmark */
std::vector<std::string> benchmark_clock_port_names = find_atom_netlist_clock_port_names(atom_ctx.nlist, netlist_annotation);
/* Connect I/Os to benchmark I/Os or constant driver */
print_verilog_testbench_connect_fpga_ios(fp, module_manager, top_module,
atom_ctx, place_ctx, io_location_map,
netlist_annotation,
std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX),
std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX),
(size_t)VERILOG_DEFAULT_SIGNAL_INIT_VALUE);
/* Assign the SRAM model applied to the FPGA fabric */
CircuitModelId sram_model = config_protocol.memory_model();
VTR_ASSERT(true == circuit_lib.valid_model_id(sram_model));
/* Assign FPGA internal SRAM/Memory ports to bitstream values */
print_verilog_preconfig_top_module_load_bitstream(fp, module_manager, top_module,
circuit_lib, sram_model,
bitstream_manager);
/* Add signal initialization */
print_verilog_testbench_signal_initialization(fp,
std::string(FORMAL_VERIFICATION_TOP_MODULE_UUT_NAME),
circuit_lib,
module_manager,
top_module);
/* Testbench ends*/
print_verilog_module_end(fp, std::string(circuit_name) + std::string(FORMAL_VERIFICATION_TOP_MODULE_POSTFIX));
/* Close the file stream */
fp.close();
/* Connect FPGA top module global ports to constant or benchmark global signals! */
status = print_verilog_preconfig_top_module_connect_global_ports(fp, module_manager, top_module,
pin_constraints, global_ports,
benchmark_clock_port_names);
if (CMD_EXEC_FATAL_ERROR == status) {
return status;
}
/* Connect I/Os to benchmark I/Os or constant driver */
print_verilog_testbench_connect_fpga_ios(fp, module_manager, top_module,
atom_ctx, place_ctx, io_location_map,
netlist_annotation,
std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX),
std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX),
(size_t)VERILOG_DEFAULT_SIGNAL_INIT_VALUE);
/* Assign the SRAM model applied to the FPGA fabric */
CircuitModelId sram_model = config_protocol.memory_model();
VTR_ASSERT(true == circuit_lib.valid_model_id(sram_model));
/* Assign FPGA internal SRAM/Memory ports to bitstream values */
print_verilog_preconfig_top_module_load_bitstream(fp, module_manager, top_module,
circuit_lib, sram_model,
bitstream_manager);
/* Add signal initialization */
print_verilog_testbench_signal_initialization(fp,
std::string(FORMAL_VERIFICATION_TOP_MODULE_UUT_NAME),
circuit_lib,
module_manager,
top_module);
/* Testbench ends*/
print_verilog_module_end(fp, std::string(circuit_name) + std::string(FORMAL_VERIFICATION_TOP_MODULE_POSTFIX));
/* Close the file stream */
fp.close();
return status;
}
} /* end namespace openfpga */

View File

@ -10,6 +10,7 @@
#include "vpr_context.h"
#include "module_manager.h"
#include "bitstream_manager.h"
#include "pin_constraints.h"
#include "io_location_map.h"
#include "fabric_global_port_info.h"
#include "config_protocol.h"
@ -22,18 +23,19 @@
/* begin namespace openfpga */
namespace openfpga {
void print_verilog_preconfig_top_module(const ModuleManager& module_manager,
const BitstreamManager& bitstream_manager,
const ConfigProtocol &config_protocol,
const CircuitLibrary& circuit_lib,
const FabricGlobalPortInfo &global_ports,
const AtomContext& atom_ctx,
const PlacementContext& place_ctx,
const IoLocationMap& io_location_map,
const VprNetlistAnnotation& netlist_annotation,
const std::string& circuit_name,
const std::string& verilog_fname,
const bool& explicit_port_mapping);
int print_verilog_preconfig_top_module(const ModuleManager& module_manager,
const BitstreamManager& bitstream_manager,
const ConfigProtocol &config_protocol,
const CircuitLibrary& circuit_lib,
const FabricGlobalPortInfo &global_ports,
const AtomContext& atom_ctx,
const PlacementContext& place_ctx,
const PinConstraints& pin_constraints,
const IoLocationMap& io_location_map,
const VprNetlistAnnotation& netlist_annotation,
const std::string& circuit_name,
const std::string& verilog_fname,
const bool& explicit_port_mapping);
} /* end namespace openfpga */

View File

@ -273,6 +273,11 @@ void print_verilog_testbench_connect_fpga_ios(std::fstream& fp,
continue;
}
/* Bypass unused output pads */
if (ModuleManager::MODULE_GPOUT_PORT == module_manager.port_type(top_module, module_io_port_id)) {
continue;
}
/* Wire to a contant */
BasicPort module_unused_io_port = module_manager.module_port(top_module, module_io_port_id);
/* Set the port pin index */
@ -347,14 +352,18 @@ void print_verilog_timeout_and_vcd(std::fstream& fp,
* Restrictions:
* Assume this is a single clock benchmark
*******************************************************************/
BasicPort generate_verilog_testbench_clock_port(const std::vector<std::string>& clock_port_names,
const std::string& default_clock_name) {
std::vector<BasicPort> generate_verilog_testbench_clock_port(const std::vector<std::string>& clock_port_names,
const std::string& default_clock_name) {
std::vector<BasicPort> clock_ports;
if (0 == clock_port_names.size()) {
return BasicPort(default_clock_name, 1);
clock_ports.push_back(BasicPort(default_clock_name, 1));
} else {
for (const std::string& clock_port_name : clock_port_names) {
clock_ports.push_back(BasicPort(clock_port_name, 1));
}
}
VTR_ASSERT(1 == clock_port_names.size());
return BasicPort(clock_port_names[0], 1);
return clock_ports;
}
/********************************************************************
@ -382,7 +391,7 @@ void print_verilog_testbench_check(std::fstream& fp,
print_verilog_comment(fp, std::string("----- Begin checking output vectors -------"));
BasicPort clock_port = generate_verilog_testbench_clock_port(clock_port_names, default_clock_name);
std::vector<BasicPort> clock_ports = generate_verilog_testbench_clock_port(clock_port_names, default_clock_name);
print_verilog_comment(fp, std::string("----- Skip the first falling edge of clock, it is for initialization -------"));
@ -391,7 +400,14 @@ void print_verilog_testbench_check(std::fstream& fp,
fp << "\t" << generate_verilog_port(VERILOG_PORT_REG, sim_start_port) << ";" << std::endl;
fp << std::endl;
fp << "\talways@(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, clock_port) << ") begin" << std::endl;
/* TODO: This is limitation when multiple clock signals exist
* Ideally, all the input signals are generated by different clock edges,
* depending which clock domain the signals belong to
* Currently, as we lack the information, we only use the first clock signal
*/
VTR_ASSERT(1 <= clock_ports.size());
fp << "\talways@(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, clock_ports[0]) << ") begin" << std::endl;
fp << "\t\tif (1'b1 == " << generate_verilog_port(VERILOG_PORT_CONKT, sim_start_port) << ") begin" << std::endl;
fp << "\t\t";
print_verilog_register_connection(fp, sim_start_port, sim_start_port, true);
@ -465,28 +481,53 @@ void print_verilog_testbench_check(std::fstream& fp,
* but be only used as a synchronizer in verification
*******************************************************************/
void print_verilog_testbench_clock_stimuli(std::fstream& fp,
const PinConstraints& pin_constraints,
const SimulationSetting& simulation_parameters,
const BasicPort& clock_port) {
const std::vector<BasicPort>& clock_ports) {
/* Validate the file stream */
valid_file_stream(fp);
print_verilog_comment(fp, std::string("----- Clock Initialization -------"));
for (const BasicPort& clock_port : clock_ports) {
print_verilog_comment(fp, std::string("----- Clock '") + clock_port.get_name() + std::string("' Initialization -------"));
fp << "\tinitial begin" << std::endl;
/* Create clock stimuli */
fp << "\t\t" << generate_verilog_port(VERILOG_PORT_CONKT, clock_port) << " <= 1'b0;" << std::endl;
fp << "\t\twhile(1) begin" << std::endl;
fp << "\t\t\t#" << std::setprecision(10) << ((0.5/simulation_parameters.operating_clock_frequency())/VERILOG_SIM_TIMESCALE) << std::endl;
fp << "\t\t\t" << generate_verilog_port(VERILOG_PORT_CONKT, clock_port);
fp << " <= !";
fp << generate_verilog_port(VERILOG_PORT_CONKT, clock_port);
fp << ";" << std::endl;
fp << "\t\tend" << std::endl;
/* Find the corresponding clock frequency from the simulation parameters */
float clk_freq_to_use = (0.5 / simulation_parameters.default_operating_clock_frequency()) / VERILOG_SIM_TIMESCALE;
/* Check pin constraints to see if this clock is constrained to a specific pin
* If constrained,
* - connect this clock to default values if it is set to be OPEN
* - connect this clock to a specific clock source from simulation settings!!!
*/
VTR_ASSERT(1 == clock_port.get_width());
for (const PinConstraintId& pin_constraint : pin_constraints.pin_constraints()) {
if (clock_port.get_name() != pin_constraints.net(pin_constraint)) {
continue;
}
/* Skip all the unrelated pin constraints */
VTR_ASSERT(clock_port.get_name() == pin_constraints.net(pin_constraint));
/* Try to find which clock source is considered in simulation settings for this pin */
for (const SimulationClockId& sim_clock_id : simulation_parameters.clocks()) {
if (pin_constraints.pin(pin_constraint) == simulation_parameters.clock_port(sim_clock_id)) {
clk_freq_to_use = (0.5 / simulation_parameters.clock_frequency(sim_clock_id)) / VERILOG_SIM_TIMESCALE;
}
}
}
fp << "\tend" << std::endl;
fp << "\tinitial begin" << std::endl;
/* Create clock stimuli */
fp << "\t\t" << generate_verilog_port(VERILOG_PORT_CONKT, clock_port) << " <= 1'b0;" << std::endl;
fp << "\t\twhile(1) begin" << std::endl;
fp << "\t\t\t#" << std::setprecision(10) << clk_freq_to_use << std::endl;
fp << "\t\t\t" << generate_verilog_port(VERILOG_PORT_CONKT, clock_port);
fp << " <= !";
fp << generate_verilog_port(VERILOG_PORT_CONKT, clock_port);
fp << ";" << std::endl;
fp << "\t\tend" << std::endl;
/* Add an empty line as splitter */
fp << std::endl;
fp << "\tend" << std::endl;
/* Add an empty line as splitter */
fp << std::endl;
}
}
/********************************************************************
@ -498,7 +539,7 @@ void print_verilog_testbench_random_stimuli(std::fstream& fp,
const VprNetlistAnnotation& netlist_annotation,
const std::vector<std::string>& clock_port_names,
const std::string& check_flag_port_postfix,
const BasicPort& clock_port) {
const std::vector<BasicPort>& clock_ports) {
/* Validate the file stream */
valid_file_stream(fp);
@ -557,25 +598,14 @@ void print_verilog_testbench_random_stimuli(std::fstream& fp,
/* Add an empty line as splitter */
fp << std::endl;
// Not ready yet to determine if input is reset
/*
fprintf(fp, "//----- Reset Stimulis\n");
fprintf(fp, " initial begin\n");
fprintf(fp, " #%.3f\n",(rand() % 10) + 0.001);
fprintf(fp, " %s <= !%s;\n", reset_input_name, reset_input_name);
fprintf(fp, " #%.3f\n",(rand() % 10) + 0.001);
fprintf(fp, " %s <= !%s;\n", reset_input_name, reset_input_name);
fprintf(fp, " while(1) begin\n");
fprintf(fp, " #%.3f\n", (rand() % 15) + 0.5);
fprintf(fp, " %s <= !%s;\n", reset_input_name, reset_input_name);
fprintf(fp, " #%.3f\n", (rand() % 10000) + 200);
fprintf(fp, " %s <= !%s;\n", reset_input_name, reset_input_name);
fprintf(fp, " end\n");
fprintf(fp, " end\n\n");
*/
print_verilog_comment(fp, std::string("----- Input Stimulus -------"));
fp << "\talways@(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, clock_port) << ") begin" << std::endl;
/* TODO: This is limitation when multiple clock signals exist
* Ideally, all the input signals are generated by different clock edges,
* depending which clock domain the signals belong to
* Currently, as we lack the information, we only use the first clock signal
*/
VTR_ASSERT(1 <= clock_ports.size());
fp << "\talways@(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, clock_ports[0]) << ") begin" << std::endl;
for (const AtomBlockId& atom_blk : atom_ctx.nlist.blocks()) {
/* Bypass non-I/O atom blocks ! */

View File

@ -12,6 +12,7 @@
#include "vpr_context.h"
#include "io_location_map.h"
#include "vpr_netlist_annotation.h"
#include "pin_constraints.h"
#include "simulation_setting.h"
/********************************************************************
@ -60,8 +61,8 @@ void print_verilog_timeout_and_vcd(std::fstream& fp,
const std::string& error_counter_name,
const float& simulation_time);
BasicPort generate_verilog_testbench_clock_port(const std::vector<std::string>& clock_port_names,
const std::string& default_clock_name);
std::vector<BasicPort> generate_verilog_testbench_clock_port(const std::vector<std::string>& clock_port_names,
const std::string& default_clock_name);
void print_verilog_testbench_check(std::fstream& fp,
const std::string& autochecked_preprocessing_flag,
@ -76,15 +77,16 @@ void print_verilog_testbench_check(std::fstream& fp,
const std::string& default_clock_name);
void print_verilog_testbench_clock_stimuli(std::fstream& fp,
const PinConstraints& pin_constraints,
const SimulationSetting& simulation_parameters,
const BasicPort& clock_port);
const std::vector<BasicPort>& clock_ports);
void print_verilog_testbench_random_stimuli(std::fstream& fp,
const AtomContext& atom_ctx,
const VprNetlistAnnotation& netlist_annotation,
const std::vector<std::string>& clock_port_names,
const std::string& check_flag_port_postfix,
const BasicPort& clock_port);
const std::vector<BasicPort>& clock_ports);
void print_verilog_testbench_shared_ports(std::fstream& fp,
const AtomContext& atom_ctx,

View File

@ -56,12 +56,24 @@ constexpr char* TOP_TB_PROG_RESET_PORT_NAME = "prog_reset";
constexpr char* TOP_TB_PROG_SET_PORT_NAME = "prog_set";
constexpr char* TOP_TB_CONFIG_DONE_PORT_NAME = "config_done";
constexpr char* TOP_TB_OP_CLOCK_PORT_NAME = "op_clock";
constexpr char* TOP_TB_OP_CLOCK_PORT_PREFIX = "operating_clk_";
constexpr char* TOP_TB_PROG_CLOCK_PORT_NAME = "prog_clock";
constexpr char* TOP_TB_INOUT_REG_POSTFIX = "_reg";
constexpr char* TOP_TB_CLOCK_REG_POSTFIX = "_reg";
constexpr char* AUTOCHECK_TOP_TESTBENCH_VERILOG_MODULE_POSTFIX = "_autocheck_top_tb";
/********************************************************************
* Generate a simulation clock port name
* This function is designed to produce a uniform clock naming for these ports
*******************************************************************/
static
std::string generate_top_testbench_clock_name(const std::string& prefix,
const std::string& port_name) {
return prefix + port_name;
}
/********************************************************************
* Print local wires for flatten memory (standalone) configuration protocols
*******************************************************************/
@ -253,6 +265,7 @@ void print_verilog_top_testbench_global_ports_stimuli(std::fstream& fp,
const ModuleManager& module_manager,
const ModuleId& top_module,
const FabricGlobalPortInfo& fabric_global_port_info,
const SimulationSetting& simulation_parameters,
const bool& active_global_prog_reset,
const bool& active_global_prog_set) {
/* Validate the file stream */
@ -288,9 +301,21 @@ void print_verilog_top_testbench_global_ports_stimuli(std::fstream& fp,
* The wiring will be inverted if the default value of the global port is 1
* Otherwise, the wiring will not be inverted!
*/
print_verilog_wire_connection(fp, module_manager.module_port(top_module, module_global_port),
stimuli_clock_port,
1 == fabric_global_port_info.global_port_default_value(fabric_global_port));
for (const size_t& pin : module_manager.module_port(top_module, module_global_port).pins()) {
BasicPort global_port_to_connect(module_manager.module_port(top_module, module_global_port).get_name(), pin, pin);
/* Should try to find a port defintion from simulation parameters
* If found, it means that we need to use special clock name!
*/
for (const SimulationClockId& sim_clock : simulation_parameters.clocks()) {
if (global_port_to_connect == simulation_parameters.clock_port(sim_clock)) {
stimuli_clock_port.set_name(generate_top_testbench_clock_name(std::string(TOP_TB_OP_CLOCK_PORT_PREFIX), simulation_parameters.clock_name(sim_clock)));
}
}
print_verilog_wire_connection(fp, global_port_to_connect,
stimuli_clock_port,
1 == fabric_global_port_info.global_port_default_value(fabric_global_port));
}
}
/* Connect global configuration done ports to configuration done signal */
@ -457,6 +482,71 @@ void print_verilog_top_testbench_global_ports_stimuli(std::fstream& fp,
print_verilog_comment(fp, std::string("----- End connecting global ports of FPGA fabric to stimuli -----"));
}
/********************************************************************
* This function prints the clock ports for all the benchmark clock nets
* It will search the pin constraints to see if a clock is constrained to a specific pin
* If constrained,
* - connect this clock to default values if it is set to be OPEN
* - connect this clock to a specific clock source from simulation settings!!!
* Otherwise,
* - connect this clock to the default clock port
*******************************************************************/
static
void print_verilog_top_testbench_benchmark_clock_ports(std::fstream& fp,
const ModuleManager& module_manager,
const ModuleId& top_module,
const std::vector<std::string>& clock_port_names,
const PinConstraints& pin_constraints,
const SimulationSetting& simulation_parameters,
const BasicPort& default_clock_port) {
/* Create a clock port if the benchmark have one but not in the default name!
* We will wire the clock directly to the operating clock directly
*/
for (const std::string clock_port_name : clock_port_names) {
if (0 == clock_port_name.compare(default_clock_port.get_name())) {
continue;
}
/* Ensure the clock port name is not a duplication of global ports of the FPGA module */
bool print_clock_port = true;
for (const BasicPort& module_port : module_manager.module_ports_by_type(top_module, ModuleManager::MODULE_GLOBAL_PORT)) {
if (0 == clock_port_name.compare(module_port.get_name())) {
print_clock_port = false;
}
}
if (false == print_clock_port) {
continue;
}
BasicPort clock_source_to_connect = default_clock_port;
/* Check pin constraints to see if this clock is constrained to a specific pin
* If constrained,
* - connect this clock to default values if it is set to be OPEN
* - connect this clock to a specific clock source from simulation settings!!!
*/
for (const PinConstraintId& pin_constraint : pin_constraints.pin_constraints()) {
if (clock_port_name != pin_constraints.net(pin_constraint)) {
continue;
}
/* Skip all the unrelated pin constraints */
VTR_ASSERT(clock_port_name == pin_constraints.net(pin_constraint));
/* Try to find which clock source is considered in simulation settings for this pin */
for (const SimulationClockId& sim_clock_id : simulation_parameters.clocks()) {
if (pin_constraints.pin(pin_constraint) == simulation_parameters.clock_port(sim_clock_id)) {
std::string sim_clock_port_name = generate_top_testbench_clock_name(std::string(TOP_TB_OP_CLOCK_PORT_PREFIX), simulation_parameters.clock_name(sim_clock_id));
clock_source_to_connect = BasicPort(sim_clock_port_name, 1);
}
}
}
/* Print the clock and wire it to the clock source */
print_verilog_comment(fp, std::string("----- Create a clock for benchmark and wire it to " + clock_source_to_connect.get_name() + " -------"));
BasicPort clock_port(clock_port_name, 1);
fp << "\t" << generate_verilog_port(VERILOG_PORT_WIRE, clock_port) << ";" << std::endl;
print_verilog_wire_connection(fp, clock_port, clock_source_to_connect, false);
}
}
/********************************************************************
* This function prints the top testbench module declaration
* and internal wires/port declaration
@ -481,6 +571,8 @@ void print_verilog_top_testbench_ports(std::fstream& fp,
const AtomContext& atom_ctx,
const VprNetlistAnnotation& netlist_annotation,
const std::vector<std::string>& clock_port_names,
const PinConstraints& pin_constraints,
const SimulationSetting& simulation_parameters,
const ConfigProtocol& config_protocol,
const std::string& circuit_name){
/* Validate the file stream */
@ -536,7 +628,21 @@ void print_verilog_top_testbench_ports(std::fstream& fp,
BasicPort prog_clock_register_port(std::string(std::string(TOP_TB_PROG_CLOCK_PORT_NAME) + std::string(TOP_TB_CLOCK_REG_POSTFIX)), 1);
fp << generate_verilog_port(VERILOG_PORT_REG, prog_clock_register_port) << ";" << std::endl;
/* Operating clock */
/* Multiple operating clocks based on the simulation settings */
for (const SimulationClockId& sim_clock : simulation_parameters.clocks()) {
std::string sim_clock_port_name = generate_top_testbench_clock_name(std::string(TOP_TB_OP_CLOCK_PORT_PREFIX), simulation_parameters.clock_name(sim_clock));
BasicPort sim_clock_port(sim_clock_port_name, 1);
fp << generate_verilog_port(VERILOG_PORT_WIRE, sim_clock_port) << ";" << std::endl;
BasicPort sim_clock_register_port(std::string(sim_clock_port_name + std::string(TOP_TB_CLOCK_REG_POSTFIX)), 1);
fp << generate_verilog_port(VERILOG_PORT_REG, sim_clock_register_port) << ";" << std::endl;
}
/* FIXME: Actually, for multi-clock implementations, input and output ports
* should be synchronized by different clocks. Currently, we lack the information
* about what inputs are driven by which clock. Therefore, we use a unified clock
* signal to do the job. However, this has to be fixed later!!!
* Create an operating clock_port to synchronize checkers stimulus generator
*/
BasicPort op_clock_port(std::string(TOP_TB_OP_CLOCK_PORT_NAME), 1);
fp << generate_verilog_port(VERILOG_PORT_WIRE, op_clock_port) << ";" << std::endl;
BasicPort op_clock_register_port(std::string(std::string(TOP_TB_OP_CLOCK_PORT_NAME) + std::string(TOP_TB_CLOCK_REG_POSTFIX)), 1);
@ -558,30 +664,13 @@ void print_verilog_top_testbench_ports(std::fstream& fp,
print_verilog_top_testbench_config_protocol_port(fp, config_protocol,
module_manager, top_module);
/* Create a clock port if the benchmark have one but not in the default name!
* We will wire the clock directly to the operating clock directly
*/
for (const std::string clock_port_name : clock_port_names) {
if (0 == clock_port_name.compare(op_clock_port.get_name())) {
continue;
}
/* Ensure the clock port name is not a duplication of global ports of the FPGA module */
bool print_clock_port = true;
for (const BasicPort& module_port : module_manager.module_ports_by_type(top_module, ModuleManager::MODULE_GLOBAL_PORT)) {
if (0 == clock_port_name.compare(module_port.get_name())) {
print_clock_port = false;
}
}
if (false == print_clock_port) {
continue;
}
/* Print the clock and wire it to op_clock */
print_verilog_comment(fp, std::string("----- Create a clock for benchmark and wire it to op_clock -------"));
BasicPort clock_port(clock_port_name, 1);
fp << "\t" << generate_verilog_port(VERILOG_PORT_WIRE, clock_port) << ";" << std::endl;
print_verilog_wire_connection(fp, clock_port, op_clock_port, false);
}
/* Print clock ports */
print_verilog_top_testbench_benchmark_clock_ports(fp,
module_manager, top_module,
clock_port_names,
pin_constraints,
simulation_parameters,
op_clock_port);
print_verilog_testbench_shared_ports(fp, atom_ctx, netlist_annotation,
clock_port_names,
@ -962,6 +1051,7 @@ void print_verilog_top_testbench_load_bitstream_task(std::fstream& fp,
*******************************************************************/
static
void print_verilog_top_testbench_generic_stimulus(std::fstream& fp,
const SimulationSetting& simulation_parameters,
const size_t& num_config_clock_cycles,
const float& prog_clock_period,
const float& op_clock_period,
@ -1014,6 +1104,32 @@ void print_verilog_top_testbench_generic_stimulus(std::fstream& fp,
fp << std::endl;
/* Generate stimuli waveform for multiple user-defined operating clock signals */
for (const SimulationClockId& sim_clock : simulation_parameters.clocks()) {
print_verilog_comment(fp, "----- Begin raw operating clock signal '" + simulation_parameters.clock_name(sim_clock) + "' generation -----");
std::string sim_clock_port_name = generate_top_testbench_clock_name(std::string(TOP_TB_OP_CLOCK_PORT_PREFIX), simulation_parameters.clock_name(sim_clock));
BasicPort sim_clock_port(sim_clock_port_name, 1);
BasicPort sim_clock_register_port(std::string(sim_clock_port_name + std::string(TOP_TB_CLOCK_REG_POSTFIX)), 1);
float sim_clock_period = 1. / simulation_parameters.clock_frequency(sim_clock);
print_verilog_clock_stimuli(fp, sim_clock_register_port,
0, /* Initial value */
0.5 * sim_clock_period / timescale,
std::string("~" + reset_port.get_name()));
print_verilog_comment(fp, "----- End raw operating clock signal generation -----");
/* Operation clock should be enabled after programming phase finishes.
* Before configuration is done (config_done is enabled), operation clock should be always zero.
*/
print_verilog_comment(fp, std::string("----- Actual operating clock is triggered only when " + config_done_port.get_name() + " is enabled -----"));
fp << "\tassign " << generate_verilog_port(VERILOG_PORT_CONKT, sim_clock_port);
fp << " = " << generate_verilog_port(VERILOG_PORT_CONKT, sim_clock_register_port);
fp << " & " << generate_verilog_port(VERILOG_PORT_CONKT, config_done_port);
fp << ";" << std::endl;
fp << std::endl;
}
/* Generate stimuli waveform for operating clock signals */
print_verilog_comment(fp, "----- Begin raw operating clock signal generation -----");
print_verilog_clock_stimuli(fp, op_clock_register_port,
@ -1774,6 +1890,7 @@ void print_verilog_top_testbench(const ModuleManager& module_manager,
const FabricGlobalPortInfo& global_ports,
const AtomContext& atom_ctx,
const PlacementContext& place_ctx,
const PinConstraints& pin_constraints,
const IoLocationMap& io_location_map,
const VprNetlistAnnotation& netlist_annotation,
const std::string& circuit_name,
@ -1826,13 +1943,20 @@ void print_verilog_top_testbench(const ModuleManager& module_manager,
/* Start of testbench */
print_verilog_top_testbench_ports(fp, module_manager, top_module,
atom_ctx, netlist_annotation, clock_port_names,
config_protocol,
atom_ctx, netlist_annotation,
clock_port_names,
pin_constraints,
simulation_parameters, config_protocol,
circuit_name);
/* Find the clock period */
float prog_clock_period = (1./simulation_parameters.programming_clock_frequency());
float op_clock_period = (1./simulation_parameters.operating_clock_frequency());
float default_op_clock_period = (1./simulation_parameters.default_operating_clock_frequency());
float max_op_clock_period = 0.;
for (const SimulationClockId& clock_id : simulation_parameters.clocks()) {
max_op_clock_period = std::max(max_op_clock_period, (float)(1./simulation_parameters.clock_frequency(clock_id)));
}
/* Estimate the number of configuration clock cycles */
size_t num_config_clock_cycles = calculate_num_config_clock_cycles(config_protocol.type(),
apply_fast_configuration,
@ -1842,9 +1966,10 @@ void print_verilog_top_testbench(const ModuleManager& module_manager,
/* Generate stimuli for general control signals */
print_verilog_top_testbench_generic_stimulus(fp,
simulation_parameters,
num_config_clock_cycles,
prog_clock_period,
op_clock_period,
default_op_clock_period,
VERILOG_SIM_TIMESCALE);
/* Generate stimuli for programming interface */
@ -1884,6 +2009,7 @@ void print_verilog_top_testbench(const ModuleManager& module_manager,
print_verilog_top_testbench_global_ports_stimuli(fp,
module_manager, top_module,
global_ports,
simulation_parameters,
active_global_prog_reset,
active_global_prog_set);
@ -1935,7 +2061,7 @@ void print_verilog_top_testbench(const ModuleManager& module_manager,
netlist_annotation,
clock_port_names,
std::string(TOP_TESTBENCH_CHECKFLAG_PORT_POSTFIX),
BasicPort(std::string(TOP_TB_OP_CLOCK_PORT_NAME), 1));
std::vector<BasicPort>(1, BasicPort(std::string(TOP_TB_OP_CLOCK_PORT_NAME), 1)));
/* Add output autocheck */
print_verilog_testbench_check(fp,
@ -1961,7 +2087,7 @@ void print_verilog_top_testbench(const ModuleManager& module_manager,
num_config_clock_cycles,
1./simulation_parameters.programming_clock_frequency(),
simulation_parameters.num_clock_cycles(),
1./simulation_parameters.operating_clock_frequency());
1./simulation_parameters.default_operating_clock_frequency());
/* Add Icarus requirement:

View File

@ -12,6 +12,7 @@
#include "circuit_library.h"
#include "config_protocol.h"
#include "vpr_context.h"
#include "pin_constraints.h"
#include "io_location_map.h"
#include "fabric_global_port_info.h"
#include "vpr_netlist_annotation.h"
@ -33,6 +34,7 @@ void print_verilog_top_testbench(const ModuleManager& module_manager,
const FabricGlobalPortInfo& global_ports,
const AtomContext& atom_ctx,
const PlacementContext& place_ctx,
const PinConstraints& pin_constraints,
const IoLocationMap& io_location_map,
const VprNetlistAnnotation& netlist_annotation,
const std::string& circuit_name,

View File

@ -240,9 +240,9 @@ std::vector<t_pb_graph_pin*> find_routed_pb_graph_pins_atom_net(const t_pb* pb,
* Note: this is ONLY applicable to the pb_pin of top-level pb_graph_node
***************************************************************************************/
static
int find_pb_route_remapped_source_pb_pin(const t_pb* pb,
const t_pb_graph_pin* source_pb_pin,
const AtomNetId& atom_net_id) {
std::vector<int> find_pb_route_remapped_source_pb_pin(const t_pb* pb,
const t_pb_graph_pin* source_pb_pin,
const AtomNetId& atom_net_id) {
VTR_ASSERT(true == source_pb_pin->parent_node->is_root());
std::vector<int> pb_route_indices;
@ -268,9 +268,7 @@ int find_pb_route_remapped_source_pb_pin(const t_pb* pb,
}
}
VTR_ASSERT(1 == pb_route_indices.size());
return pb_route_indices[0];
return pb_route_indices;
}
/***************************************************************************************
@ -339,6 +337,7 @@ void add_lb_router_nets(LbRouter& lb_router,
const VprDeviceAnnotation& device_annotation,
const ClusteringContext& clustering_ctx,
const VprClusteringAnnotation& clustering_annotation,
const RepackDesignConstraints& design_constraints,
const ClusterBlockId& block_id,
const bool& verbose) {
size_t net_counter = 0;
@ -409,31 +408,101 @@ void add_lb_router_nets(LbRouter& lb_router,
/* Find the net mapped to this pin in clustering results*/
AtomNetId atom_net_id = pb_pin_mapped_nets[source_pb_pin];
/* Bypass unmapped pins */
if (AtomNetId::INVALID() == atom_net_id) {
/* Check if the net information is constrained or not */
std::string constrained_net_name;
for (const RepackDesignConstraintId& design_constraint : design_constraints.design_constraints()) {
/* All the pin must have only 1 bit */
VTR_ASSERT_SAFE(1 == design_constraints.pin(design_constraint).get_width());
/* If found a constraint, record the net name */
if ( (std::string(lb_type->pb_type->name) == design_constraints.pb_type(design_constraint))
&& (std::string(source_pb_pin->port->name) == design_constraints.pin(design_constraint).get_name())
&& (size_t(source_pb_pin->pin_number) == design_constraints.pin(design_constraint).get_lsb())) {
constrained_net_name = design_constraints.net(design_constraint);
break;
}
}
/* Find the constrained net mapped to this pin in clustering results */
AtomNetId constrained_atom_net_id = AtomNetId::INVALID();
/* If the pin is constrained, we need to
* - if this is an open net, for invalid net then
* - if this is valid net name, find the net id from atom_netlist
* and overwrite the atom net id to mapped
*/
if (!constrained_net_name.empty()) {
if (std::string(REPACK_DESIGN_CONSTRAINT_OPEN_NET) != constrained_net_name) {
constrained_atom_net_id = atom_ctx.nlist.find_net(constrained_net_name);
if (false == atom_ctx.nlist.valid_net_id(constrained_atom_net_id)) {
VTR_LOG_WARN("Invalid net '%s' to be constrained! Will drop the constraint in repacking\n",
constrained_net_name.c_str());
}
}
} else {
VTR_ASSERT_SAFE(constrained_net_name.empty());
constrained_atom_net_id = atom_net_id;
}
/* Bypass unmapped pins. There are 4 conditions to consider
* +======+=================+=============+================================+
* | Case | Packing results | Constraints | Decision to route |
* +======+=================+=============+================================+
* | 0 | Unmapped | Unmapped | No routing needed |
* +======+=================+=============+================================+
* | 1 | Unmapped | Mapped | Find the pb source pin that |
* | | | | drives the constrained net and |
* | | | | use it to find sink nodes |
* +======+=================+=============+================================+
* | 2 | Mapped | Unmapped | No routing needed |
* +======+=================+=============+================================+
* | 3 | Mapped | Mapped | Route with the constrained net |
* | | | | but use the packing net id to |
* | | | | find the sink nodes to route |
* +======+=================+=============+================================+
*/
if (AtomNetId::INVALID() == constrained_atom_net_id) {
continue;
}
/* If we have a net to route, it must be the constrained net */
AtomNetId atom_net_id_to_route = constrained_atom_net_id;
/* The outputs of pb_graph_node is INTERMEDIATE node in the routing resource graph,
* they are all connected to a common source node
*/
LbRRNodeId source_lb_rr_node = lb_rr_graph.find_node(LB_INTERMEDIATE, source_pb_pin);
VTR_ASSERT(true == lb_rr_graph.valid_node_id(source_lb_rr_node));
int pb_route_index = find_pb_route_remapped_source_pb_pin(pb, source_pb_pin, atom_net_id);
/* As the pin remapping is allowed during routing, we should
* - Find the routing traces from packing results which is mapped to the net
* from the same port (as remapping is allowed for pins in the same port only)
* - Find the source pb_graph_pin that drives the routing traces during packing
* - Then we can find the sink nodes
*/
std::vector<int> pb_route_indices = find_pb_route_remapped_source_pb_pin(pb, source_pb_pin, atom_net_id_to_route);
/* It could happen that the constrained net is NOT used in this clb, we just skip it for routing
* For example, a clkB net is never mapped to any ports in the pb that is clocked by clkA net
* */
int pb_route_index;
if (0 == pb_route_indices.size()) {
continue;
} else {
VTR_ASSERT(1 == pb_route_indices.size());
pb_route_index = pb_route_indices[0];
}
t_pb_graph_pin* packing_source_pb_pin = get_pb_graph_node_pin_from_block_pin(block_id, pb_route_index);
VTR_ASSERT(nullptr != packing_source_pb_pin);
/* Find all the sink pins in the pb_route, we walk through the input pins and find the pin */
std::vector<t_pb_graph_pin*> sink_pb_graph_pins = find_routed_pb_graph_pins_atom_net(pb, source_pb_pin, packing_source_pb_pin, atom_net_id, device_annotation, pb_pin_mapped_nets, pb_graph_pin_lookup_from_index);
std::vector<t_pb_graph_pin*> sink_pb_graph_pins = find_routed_pb_graph_pins_atom_net(pb, source_pb_pin, packing_source_pb_pin, atom_net_id_to_route, device_annotation, pb_pin_mapped_nets, pb_graph_pin_lookup_from_index);
std::vector<LbRRNodeId> sink_lb_rr_nodes = find_lb_net_physical_sink_lb_rr_nodes(lb_rr_graph, sink_pb_graph_pins, device_annotation);
VTR_ASSERT(sink_lb_rr_nodes.size() == sink_pb_graph_pins.size());
/* Printf for debugging only, may be enabled if verbose is enabled
*/
/* Output verbose messages for debugging only */
VTR_LOGV(verbose,
"Pb route for Net %s:\n",
atom_ctx.nlist.net_name(atom_net_id).c_str());
atom_ctx.nlist.net_name(atom_net_id_to_route).c_str());
VTR_LOGV(verbose,
"Source node:\n\t%s -> %s\n",
source_pb_pin->to_string().c_str(),
@ -449,7 +518,7 @@ void add_lb_router_nets(LbRouter& lb_router,
add_lb_router_net_to_route(lb_router, lb_rr_graph,
std::vector<LbRRNodeId>(1, source_lb_rr_node),
sink_lb_rr_nodes,
atom_ctx, atom_net_id);
atom_ctx, atom_net_id_to_route);
net_counter++;
}
@ -542,6 +611,7 @@ void repack_cluster(const AtomContext& atom_ctx,
const ClusteringContext& clustering_ctx,
const VprDeviceAnnotation& device_annotation,
VprClusteringAnnotation& clustering_annotation,
const RepackDesignConstraints& design_constraints,
const ClusterBlockId& block_id,
const bool& verbose) {
/* Get the pb graph that current clustered block is mapped to */
@ -563,6 +633,7 @@ void repack_cluster(const AtomContext& atom_ctx,
/* Add nets to be routed with source and terminals */
add_lb_router_nets(lb_router, lb_type, lb_rr_graph, atom_ctx, device_annotation,
clustering_ctx, const_cast<const VprClusteringAnnotation&>(clustering_annotation),
design_constraints,
block_id, verbose);
/* Initialize the modes to expand routing trees with the physical modes in device annotation
@ -607,12 +678,15 @@ void repack_clusters(const AtomContext& atom_ctx,
const ClusteringContext& clustering_ctx,
const VprDeviceAnnotation& device_annotation,
VprClusteringAnnotation& clustering_annotation,
const RepackDesignConstraints& design_constraints,
const bool& verbose) {
vtr::ScopedStartFinishTimer timer("Repack clustered blocks to physical implementation of logical tile");
for (auto blk_id : clustering_ctx.clb_nlist.blocks()) {
repack_cluster(atom_ctx, clustering_ctx,
device_annotation, clustering_annotation,
device_annotation,
clustering_annotation,
design_constraints,
blk_id, verbose);
}
}
@ -632,6 +706,7 @@ void pack_physical_pbs(const DeviceContext& device_ctx,
const ClusteringContext& clustering_ctx,
VprDeviceAnnotation& device_annotation,
VprClusteringAnnotation& clustering_annotation,
const RepackDesignConstraints& design_constraints,
const bool& verbose) {
/* build the routing resource graph for each logical tile */
@ -642,6 +717,7 @@ void pack_physical_pbs(const DeviceContext& device_ctx,
/* Call the LbRouter to re-pack each clustered block to physical implementation */
repack_clusters(atom_ctx, clustering_ctx,
const_cast<const VprDeviceAnnotation&>(device_annotation), clustering_annotation,
design_constraints,
verbose);
}

View File

@ -8,6 +8,7 @@
#include "vpr_device_annotation.h"
#include "vpr_clustering_annotation.h"
#include "vpr_routing_annotation.h"
#include "repack_design_constraints.h"
/********************************************************************
* Function declaration
@ -21,6 +22,7 @@ void pack_physical_pbs(const DeviceContext& device_ctx,
const ClusteringContext& clustering_ctx,
VprDeviceAnnotation& device_annotation,
VprClusteringAnnotation& clustering_annotation,
const RepackDesignConstraints& design_constraints,
const bool& verbose);
} /* end namespace openfpga */

View File

@ -102,107 +102,125 @@ int check_tile_annotation_conflicts_with_physical_tile(const TileAnnotation& til
int num_err = 0;
for (const TileGlobalPortId& tile_global_port : tile_annotation.global_ports()) {
/* Must find a valid physical tile in the same name */
size_t found_matched_physical_tile = 0;
size_t found_matched_physical_tile_port = 0;
for (const t_physical_tile_type& physical_tile : physical_tile_types) {
if (std::string(physical_tile.name) != tile_annotation.global_port_tile_name(tile_global_port)) {
continue;
}
for (size_t tile_info_id = 0; tile_info_id < tile_annotation.global_port_tile_names(tile_global_port).size(); ++tile_info_id) {
/* Must find a valid physical tile in the same name */
size_t found_matched_physical_tile = 0;
size_t found_matched_physical_tile_port = 0;
/* Found a match, increment the counter */
found_matched_physical_tile++;
std::string required_tile_name = tile_annotation.global_port_tile_names(tile_global_port)[tile_info_id];
BasicPort required_tile_port = tile_annotation.global_port_tile_ports(tile_global_port)[tile_info_id];
/* Must found a valid port where both port name and port size must match!!! */
for (const t_physical_tile_port& tile_port : physical_tile.ports) {
if (std::string(tile_port.name) != tile_annotation.global_port_tile_port(tile_global_port).get_name()) {
for (const t_physical_tile_type& physical_tile : physical_tile_types) {
if (std::string(physical_tile.name) != required_tile_name) {
continue;
}
if (size_t(tile_port.num_pins) != tile_annotation.global_port_tile_port(tile_global_port).get_width()) {
continue;
/* Found a match, increment the counter */
found_matched_physical_tile++;
/* Must found a valid port where both port name and port size must match!!! */
for (const t_physical_tile_port& tile_port : physical_tile.ports) {
if (std::string(tile_port.name) != required_tile_port.get_name()) {
continue;
}
BasicPort ref_tile_port(tile_port.name, tile_port.num_pins);
/* Port size must be in range!!! */
if (false == ref_tile_port.contained(required_tile_port)) {
VTR_LOG_ERROR("Tile annotation port '%s[%lu:%lu]' is out of the range of physical tile port '%s[%lu:%lu]'!",
required_tile_port.get_name().c_str(),
required_tile_port.get_lsb(),
required_tile_port.get_msb(),
ref_tile_port.get_name().c_str(),
ref_tile_port.get_lsb(),
ref_tile_port.get_msb());
num_err++;
continue;
}
/* Check if port property matches */
int grid_pin_index = tile_port.absolute_first_pin_index;
if (tile_port.is_clock != tile_annotation.global_port_is_clock(tile_global_port)) {
VTR_LOGF_ERROR(__FILE__, __LINE__,
"Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' does not match physical tile port %s.%s in clock property (one is defined as clock while the other is not)!\n",
required_tile_name.c_str(),
required_tile_port.get_name().c_str(),
required_tile_port.get_lsb(),
required_tile_port.get_msb(),
tile_annotation.global_port_name(tile_global_port).c_str(),
physical_tile.name, tile_port.name);
num_err++;
}
if ((false == tile_port.is_clock)
&& (false == tile_port.is_non_clock_global)) {
VTR_LOGF_ERROR(__FILE__, __LINE__,
"Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' match physical tile port %s.%s but is not defined as a non-clock global port!\n",
required_tile_name.c_str(),
required_tile_port.get_name().c_str(),
required_tile_port.get_lsb(),
required_tile_port.get_msb(),
tile_annotation.global_port_name(tile_global_port).c_str(),
physical_tile.name, tile_port.name);
num_err++;
}
float pin_Fc = find_physical_tile_pin_Fc(&physical_tile, grid_pin_index);
if (0. != pin_Fc) {
VTR_LOGF_ERROR(__FILE__, __LINE__,
"Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' match physical tile port %s.%s but its Fc is not zero '%g' !\n",
required_tile_name.c_str(),
required_tile_port.get_name().c_str(),
required_tile_port.get_lsb(),
required_tile_port.get_msb(),
tile_annotation.global_port_name(tile_global_port).c_str(),
physical_tile.name, tile_port.name, pin_Fc);
}
found_matched_physical_tile_port++;
}
/* Check if port property matches */
int grid_pin_index = tile_port.absolute_first_pin_index;
if (tile_port.is_clock != tile_annotation.global_port_is_clock(tile_global_port)) {
VTR_LOGF_ERROR(__FILE__, __LINE__,
"Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' does not match physical tile port %s.%s in clock property (one is defined as clock while the other is not)!\n",
tile_annotation.global_port_tile_name(tile_global_port).c_str(),
tile_annotation.global_port_tile_port(tile_global_port).get_name().c_str(),
tile_annotation.global_port_tile_port(tile_global_port).get_lsb(),
tile_annotation.global_port_tile_port(tile_global_port).get_msb(),
tile_annotation.global_port_name(tile_global_port).c_str(),
physical_tile.name, tile_port.name);
num_err++;
}
if ((false == tile_port.is_clock)
&& (false == tile_port.is_non_clock_global)) {
VTR_LOGF_ERROR(__FILE__, __LINE__,
"Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' match physical tile port %s.%s but is not defined as a non-clock global port!\n",
tile_annotation.global_port_tile_name(tile_global_port).c_str(),
tile_annotation.global_port_tile_port(tile_global_port).get_name().c_str(),
tile_annotation.global_port_tile_port(tile_global_port).get_lsb(),
tile_annotation.global_port_tile_port(tile_global_port).get_msb(),
tile_annotation.global_port_name(tile_global_port).c_str(),
physical_tile.name, tile_port.name);
num_err++;
}
float pin_Fc = find_physical_tile_pin_Fc(&physical_tile, grid_pin_index);
if (0. != pin_Fc) {
VTR_LOGF_ERROR(__FILE__, __LINE__,
"Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' match physical tile port %s.%s but its Fc is not zero '%g' !\n",
tile_annotation.global_port_tile_name(tile_global_port).c_str(),
tile_annotation.global_port_tile_port(tile_global_port).get_name().c_str(),
tile_annotation.global_port_tile_port(tile_global_port).get_lsb(),
tile_annotation.global_port_tile_port(tile_global_port).get_msb(),
tile_annotation.global_port_name(tile_global_port).c_str(),
physical_tile.name, tile_port.name, pin_Fc);
}
found_matched_physical_tile_port++;
}
}
/* If we found no match, error out */
if (0 == found_matched_physical_tile) {
VTR_LOGF_ERROR(__FILE__, __LINE__,
"Tile name '%s' in tile annotation '%s' does not match any physical tile!\n",
tile_annotation.global_port_tile_name(tile_global_port).c_str(),
tile_annotation.global_port_name(tile_global_port).c_str());
num_err++;
}
if (0 == found_matched_physical_tile_port) {
VTR_LOGF_ERROR(__FILE__, __LINE__,
"Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' does not match any physical tile port!\n",
tile_annotation.global_port_tile_name(tile_global_port).c_str(),
tile_annotation.global_port_tile_port(tile_global_port).get_name().c_str(),
tile_annotation.global_port_tile_port(tile_global_port).get_lsb(),
tile_annotation.global_port_tile_port(tile_global_port).get_msb(),
tile_annotation.global_port_name(tile_global_port).c_str());
num_err++;
}
/* If we found no match, error out */
if (0 == found_matched_physical_tile) {
VTR_LOGF_ERROR(__FILE__, __LINE__,
"Tile name '%s' in tile annotation '%s' does not match any physical tile!\n",
required_tile_name.c_str(),
tile_annotation.global_port_name(tile_global_port).c_str());
num_err++;
}
if (0 == found_matched_physical_tile_port) {
VTR_LOGF_ERROR(__FILE__, __LINE__,
"Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' does not match any physical tile port!\n",
required_tile_name.c_str(),
required_tile_port.get_name().c_str(),
required_tile_port.get_lsb(),
required_tile_port.get_msb(),
tile_annotation.global_port_name(tile_global_port).c_str());
num_err++;
}
/* If we found more than 1 match, error out */
if (1 < found_matched_physical_tile) {
VTR_LOGF_ERROR(__FILE__, __LINE__,
"Tile name '%s' in tile annotation '%s' match more than 1 physical tile!\n",
tile_annotation.global_port_tile_name(tile_global_port).c_str(),
tile_annotation.global_port_name(tile_global_port).c_str());
num_err++;
}
if (1 < found_matched_physical_tile_port) {
VTR_LOGF_ERROR(__FILE__, __LINE__,
"Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' match more than 1physical tile port!\n",
tile_annotation.global_port_tile_name(tile_global_port).c_str(),
tile_annotation.global_port_tile_port(tile_global_port).get_name().c_str(),
tile_annotation.global_port_tile_port(tile_global_port).get_lsb(),
tile_annotation.global_port_tile_port(tile_global_port).get_msb(),
tile_annotation.global_port_name(tile_global_port).c_str());
num_err++;
/* If we found more than 1 match, error out */
if (1 < found_matched_physical_tile) {
VTR_LOGF_ERROR(__FILE__, __LINE__,
"Tile name '%s' in tile annotation '%s' match more than 1 physical tile!\n",
required_tile_name.c_str(),
tile_annotation.global_port_name(tile_global_port).c_str());
num_err++;
}
if (1 < found_matched_physical_tile_port) {
VTR_LOGF_ERROR(__FILE__, __LINE__,
"Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' match more than 1 physical tile port!\n",
required_tile_name.c_str(),
required_tile_port.get_name().c_str(),
required_tile_port.get_lsb(),
required_tile_port.get_msb(),
tile_annotation.global_port_name(tile_global_port).c_str());
num_err++;
}
}
}

View File

@ -0,0 +1,9 @@
clk 0.500000 2.000000
a 0.502000 0.197200
b 0.485400 0.202800
c 0.248000 0.176800
a_reg 0.502000 0.197200
b_reg 0.485400 0.202800
n10 0.248000 0.043259
n13 0.502000 0.098994
n17 0.485400 0.098439

View File

@ -0,0 +1,16 @@
# Benchmark "and2_pipelined" written by ABC on Sun Jan 10 10:26:01 2021
.model and2_pipelined
.inputs clk a b
.outputs c
.latch n10 c 2
.latch n13 a_reg 2
.latch n17 b_reg 2
.names a_reg b_reg n10
11 1
.names a n13
1 1
.names b n17
1 1
.end

View File

@ -0,0 +1,34 @@
/////////////////////////////////////////
// Functionality: a pipelined 2-input AND
// where inputs and outputs are registered
// Author: Xifan Tang
////////////////////////////////////////
`timescale 1ns / 1ps
module and2_pipelined(
clk,
a,
b,
c);
input wire clk;
input wire a;
input wire b;
output wire c;
reg a_reg;
reg b_reg;
reg c_reg;
always @(posedge clk) begin
a_reg <= a;
b_reg <= b;
end
always @(posedge clk) begin
c_reg <= a_reg & b_reg;
end
assign c = c_reg;
endmodule

View File

@ -0,0 +1,22 @@
clk0 0.505000 0.204400
rst0 0.491000 0.206000
clk1 0.472000 0.204400
rst1 0.501400 0.204600
q1[0] 0.278800 0.557400
q1[1] 0.240600 0.268800
q1[2] 0.178200 0.120000
q1[3] 0.098400 0.041600
q0[0] 0.283400 0.566600
q0[1] 0.246800 0.272000
q0[2] 0.181000 0.122200
q0[3] 0.093200 0.048800
n34 0.178200 0.068356
n38 0.098400 0.002698
$abc$226$new_n22_ 0.880800 0.004943
n42 0.283400 0.129291
n46 0.246800 0.084119
n50 0.181000 0.067113
n54 0.093200 0.002644
$abc$226$new_n27_ 0.883200 0.005398
n26 0.278800 0.038636
n30 0.240600 0.082416

View File

@ -0,0 +1,48 @@
# Benchmark "counter4bit_2clock" written by ABC on Wed Jan 13 13:27:00 2021
.model counter4bit_2clock
.inputs clk0 rst0 clk1 rst1
.outputs q0[0] q0[1] q0[2] q0[3] q1[0] q1[1] \
q1[2] q1[3]
.latch n26 q1[0] re clk1 2
.latch n30 q1[1] re clk1 2
.latch n34 q1[2] re clk1 2
.latch n38 q1[3] re clk1 2
.latch n42 q0[0] re clk0 2
.latch n46 q0[1] re clk0 2
.latch n50 q0[2] re clk0 2
.latch n54 q0[3] re clk0 2
.names q1[0] q1[1] rst1 q1[2] n34
-001 1
0-01 1
1100 1
.names rst1 $abc$226$new_n22_ n38
00 1
.names q1[2] q1[0] q1[1] q1[3] $abc$226$new_n22_
--00 1
-0-0 1
0--0 1
1111 1
.names rst0 q0[0] n42
00 1
.names rst0 q0[1] q0[0] n46
001 1
010 1
.names q0[1] q0[0] rst0 q0[2] n50
-001 1
0-01 1
1100 1
.names rst0 $abc$226$new_n27_ n54
00 1
.names q0[2] q0[1] q0[0] q0[3] $abc$226$new_n27_
--00 1
-0-0 1
0--0 1
1111 1
.names q1[0] rst1 n26
00 1
.names rst1 q1[0] q1[1] n30
001 1
010 1
.end

View File

@ -0,0 +1,29 @@
module counter4bit_2clock(clk0, rst0, clk1, rst1, q0, q1);
input clk0;
input rst0;
output [3:0] q0;
reg [3:0] q0;
input clk1;
input rst1;
output [3:0] q1;
reg [3:0] q1;
always @ (posedge clk0)
begin
if(rst0)
q0 <= 4'b0000;
else
q0 <= q0 + 1;
end
always @ (posedge clk1)
begin
if(rst1)
q1 <= 4'b0000;
else
q1 <= q1 + 1;
end
endmodule

View File

@ -0,0 +1,60 @@
/* Generated by Yosys 0.9+2406 (git sha1 a0606e09, gcc 8.4.0 -fPIC -Os) */
module counter4bit_2clock(clk0, rst0, clk1, rst1, \q0[0] , \q0[1] , \q0[2] , \q0[3] , \q1[0] , \q1[1] , \q1[2] , \q1[3] );
wire _00_;
wire _01_;
input clk0;
input clk1;
wire n26;
wire n30;
wire n34;
wire n38;
wire n42;
wire n46;
wire n50;
wire n54;
output \q0[0] ;
reg \q0[0] ;
output \q0[1] ;
reg \q0[1] ;
output \q0[2] ;
reg \q0[2] ;
output \q0[3] ;
reg \q0[3] ;
output \q1[0] ;
reg \q1[0] ;
output \q1[1] ;
reg \q1[1] ;
output \q1[2] ;
reg \q1[2] ;
output \q1[3] ;
reg \q1[3] ;
input rst0;
input rst1;
always @(posedge clk1)
\q1[0] <= n26;
always @(posedge clk1)
\q1[1] <= n30;
always @(posedge clk1)
\q1[2] <= n34;
always @(posedge clk1)
\q1[3] <= n38;
always @(posedge clk1)
\q0[0] <= n42;
always @(posedge clk1)
\q0[1] <= n46;
always @(posedge clk1)
\q0[2] <= n50;
always @(posedge clk1)
\q0[3] <= n54;
assign n38 = 4'h1 >> { _00_, rst1 };
assign _00_ = 16'h807f >> { \q1[3] , \q1[1] , \q1[0] , \q1[2] };
assign n42 = 4'h1 >> { \q0[0] , rst0 };
assign n46 = 8'h14 >> { \q0[0] , \q0[1] , rst0 };
assign n50 = 16'h0708 >> { \q0[2] , rst0, \q0[0] , \q0[1] };
assign n54 = 4'h1 >> { _01_, rst0 };
assign _01_ = 16'h807f >> { \q0[3] , \q0[0] , \q0[1] , \q0[2] };
assign n26 = 4'h1 >> { rst1, \q1[0] };
assign n30 = 8'h14 >> { \q1[1] , \q1[0] , rst1 };
assign n34 = 16'h0708 >> { \q1[2] , rst1, \q1[1] , \q1[0] };
endmodule

View File

@ -0,0 +1,42 @@
module counter4bit_2clock_tb;
reg clk0, rst0;
wire [3:0] q0;
reg clk1, rst1;
wire [3:0] q1;
counter_2clock C_1(
clk0,
q0,
rst0);
counter_2clock C_1(
clk1,
q1,
rst1);
initial begin
#0 rst0 = 1'b1; clk0 = 1'b0;
#100 rst0 = 1'b0;
end
always begin
#10 clk0 = ~clk0;
end
initial begin
#0 rst1 = 1'b1; clk1 = 1'b0;
#100 rst1 = 1'b0;
end
always begin
#20 clk1 = ~clk1;
end
initial begin
#5000 $stop;
end
endmodule

View File

@ -2,5 +2,5 @@
# Read verilog files
${READ_VERILOG_FILE}
synth_quicklogic -blif ${OUTPUT_BLIF} -family ap3 -vpr -openfpga -top ${TOP_MODULE}
synth_quicklogic -blif ${OUTPUT_BLIF} -openfpga -top ${TOP_MODULE}

View File

@ -21,9 +21,11 @@ Note that an OpenFPGA architecture can be applied to multiple VPR architecture f
- behavioral: If behavioral Verilog modeling is specified
- local\_encoder: If local encoders are used in routing multiplexer design
- spyio/spypad: If spy I/Os are used
- registerable\_io: If I/Os are registerable (can be either combinational or sequential)
- stdcell: If circuit designs are built with standard cells only
- tree\_mux: If routing multiplexers are built with a tree-like structure
- <feature_size>: The technology node which the delay numbers are extracted from.
- powergate : The FPGA has power-gating techniques applied. If not defined, there is no power-gating.
- GlobalTile<Int>Clk: How many clocks are defined through global ports from physical tiles. <Int> is the number of clocks
Other features are used in naming should be listed here.

View File

@ -0,0 +1,198 @@
<!-- Architecture annotation for OpenFPGA framework
This annotation supports the k6_N10_40nm.xml
- General purpose logic block
- K = 6, N = 10, I = 40
- Single mode
- Routing architecture
- L = 4, fc_in = 0.15, fc_out = 0.1
- 4 operating clocks
-->
<openfpga_architecture>
<technology_library>
<device_library>
<device_model name="logic" type="transistor">
<lib type="industry" corner="TOP_TT" ref="M" path="${OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.pm"/>
<design vdd="0.9" pn_ratio="2"/>
<pmos name="pch" chan_length="40e-9" min_width="140e-9" variation="logic_transistor_var"/>
<nmos name="nch" chan_length="40e-9" min_width="140e-9" variation="logic_transistor_var"/>
</device_model>
<device_model name="io" type="transistor">
<lib type="academia" ref="M" path="${OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.pm"/>
<design vdd="2.5" pn_ratio="3"/>
<pmos name="pch_25" chan_length="270e-9" min_width="320e-9" variation="io_transistor_var"/>
<nmos name="nch_25" chan_length="270e-9" min_width="320e-9" variation="io_transistor_var"/>
</device_model>
</device_library>
<variation_library>
<variation name="logic_transistor_var" abs_deviation="0.1" num_sigma="3"/>
<variation name="io_transistor_var" abs_deviation="0.1" num_sigma="3"/>
</variation_library>
</technology_library>
<circuit_library>
<circuit_model type="inv_buf" name="INVTX1" prefix="INVTX1" is_default="true">
<design_technology type="cmos" topology="inverter" size="1"/>
<device_technology device_model_name="logic"/>
<port type="input" prefix="in" size="1"/>
<port type="output" prefix="out" size="1"/>
<delay_matrix type="rise" in_port="in" out_port="out">
10e-12
</delay_matrix>
<delay_matrix type="fall" in_port="in" out_port="out">
10e-12
</delay_matrix>
</circuit_model>
<circuit_model type="inv_buf" name="buf4" prefix="buf4" is_default="false">
<design_technology type="cmos" topology="buffer" size="1" num_level="2" f_per_stage="4"/>
<device_technology device_model_name="logic"/>
<port type="input" prefix="in" size="1"/>
<port type="output" prefix="out" size="1"/>
<delay_matrix type="rise" in_port="in" out_port="out">
10e-12
</delay_matrix>
<delay_matrix type="fall" in_port="in" out_port="out">
10e-12
</delay_matrix>
</circuit_model>
<circuit_model type="inv_buf" name="tap_buf4" prefix="tap_buf4" is_default="false">
<design_technology type="cmos" topology="buffer" size="1" num_level="3" f_per_stage="4"/>
<device_technology device_model_name="logic"/>
<port type="input" prefix="in" size="1"/>
<port type="output" prefix="out" size="1"/>
<delay_matrix type="rise" in_port="in" out_port="out">
10e-12
</delay_matrix>
<delay_matrix type="fall" in_port="in" out_port="out">
10e-12
</delay_matrix>
</circuit_model>
<circuit_model type="pass_gate" name="TGATE" prefix="TGATE" is_default="true">
<design_technology type="cmos" topology="transmission_gate" nmos_size="1" pmos_size="2"/>
<device_technology device_model_name="logic"/>
<input_buffer exist="false"/>
<output_buffer exist="false"/>
<port type="input" prefix="in" size="1"/>
<port type="input" prefix="sel" size="1"/>
<port type="input" prefix="selb" size="1"/>
<port type="output" prefix="out" size="1"/>
<delay_matrix type="rise" in_port="in sel selb" out_port="out">
10e-12 5e-12 5e-12
</delay_matrix>
<delay_matrix type="fall" in_port="in sel selb" out_port="out">
10e-12 5e-12 5e-12
</delay_matrix>
</circuit_model>
<circuit_model type="chan_wire" name="chan_segment" prefix="track_seg" is_default="true">
<design_technology type="cmos"/>
<input_buffer exist="false"/>
<output_buffer exist="false"/>
<port type="input" prefix="in" size="1"/>
<port type="output" prefix="out" size="1"/>
<wire_param model_type="pi" R="101" C="22.5e-15" num_level="1"/> <!-- model_type could be T, res_val and cap_val DON'T CARE -->
</circuit_model>
<circuit_model type="wire" name="direct_interc" prefix="direct_interc" is_default="true">
<design_technology type="cmos"/>
<input_buffer exist="false"/>
<output_buffer exist="false"/>
<port type="input" prefix="in" size="1"/>
<port type="output" prefix="out" size="1"/>
<wire_param model_type="pi" R="0" C="0" num_level="1"/> <!-- model_type could be T, res_val cap_val should be defined -->
</circuit_model>
<circuit_model type="mux" name="mux_tree" prefix="mux_tree" dump_structural_verilog="true">
<design_technology type="cmos" structure="tree" add_const_input="true" const_input_val="1"/>
<input_buffer exist="true" circuit_model_name="INVTX1"/>
<output_buffer exist="true" circuit_model_name="INVTX1"/>
<pass_gate_logic circuit_model_name="TGATE"/>
<port type="input" prefix="in" size="1"/>
<port type="output" prefix="out" size="1"/>
<port type="sram" prefix="sram" size="1"/>
</circuit_model>
<circuit_model type="mux" name="mux_tree_tapbuf" prefix="mux_tree_tapbuf" is_default="true" dump_structural_verilog="true">
<design_technology type="cmos" structure="tree" add_const_input="true" const_input_val="1"/>
<input_buffer exist="true" circuit_model_name="INVTX1"/>
<output_buffer exist="true" circuit_model_name="tap_buf4"/>
<pass_gate_logic circuit_model_name="TGATE"/>
<port type="input" prefix="in" size="1"/>
<port type="output" prefix="out" size="1"/>
<port type="sram" prefix="sram" size="1"/>
</circuit_model>
<!--DFF subckt ports should be defined as <D> <Q> <CLK> <RESET> <SET> -->
<circuit_model type="ff" name="DFFSRQ" prefix="DFFSRQ" spice_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/spice/dff.sp" verilog_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/verilog/dff.v">
<design_technology type="cmos"/>
<input_buffer exist="true" circuit_model_name="INVTX1"/>
<output_buffer exist="true" circuit_model_name="INVTX1"/>
<port type="input" prefix="D" size="1"/>
<port type="input" prefix="set" lib_name="SET" size="1" is_global="true" default_val="0" is_set="true"/>
<port type="input" prefix="reset" lib_name="RST" size="1" is_global="true" default_val="0" is_reset="true"/>
<port type="output" prefix="Q" size="1"/>
<port type="clock" prefix="clk" lib_name="CK" size="1" is_global="false" default_val="0"/>
</circuit_model>
<circuit_model type="lut" name="lut4" prefix="lut4" dump_structural_verilog="true">
<design_technology type="cmos"/>
<input_buffer exist="true" circuit_model_name="INVTX1"/>
<output_buffer exist="true" circuit_model_name="INVTX1"/>
<lut_input_inverter exist="true" circuit_model_name="INVTX1"/>
<lut_input_buffer exist="true" circuit_model_name="buf4"/>
<pass_gate_logic circuit_model_name="TGATE"/>
<port type="input" prefix="in" size="4"/>
<port type="output" prefix="out" size="1"/>
<port type="sram" prefix="sram" size="16"/>
</circuit_model>
<!--Scan-chain DFF subckt ports should be defined as <D> <Q> <Qb> <CLK> <RESET> <SET> -->
<circuit_model type="ccff" name="DFF" prefix="DFF" spice_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/spice/dff.sp" verilog_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/verilog/dff.v">
<design_technology type="cmos"/>
<input_buffer exist="true" circuit_model_name="INVTX1"/>
<output_buffer exist="true" circuit_model_name="INVTX1"/>
<port type="input" prefix="D" size="1"/>
<port type="output" prefix="Q" size="1"/>
<port type="output" prefix="QN" size="1"/>
<port type="clock" prefix="prog_clk" lib_name="CK" size="1" is_global="true" default_val="0" is_prog="true"/>
</circuit_model>
<circuit_model type="iopad" name="GPIO" prefix="GPIO" spice_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/spice/gpio.sp" verilog_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/verilog/gpio.v">
<design_technology type="cmos"/>
<input_buffer exist="true" circuit_model_name="INVTX1"/>
<output_buffer exist="true" circuit_model_name="INVTX1"/>
<port type="inout" prefix="PAD" size="1" is_global="true" is_io="true" is_data_io="true"/>
<port type="sram" prefix="DIR" size="1" mode_select="true" circuit_model_name="DFF" default_val="1"/>
<port type="input" prefix="outpad" lib_name="A" size="1"/>
<port type="output" prefix="inpad" lib_name="Y" size="1"/>
</circuit_model>
</circuit_library>
<configuration_protocol>
<organization type="scan_chain" circuit_model_name="DFF"/>
</configuration_protocol>
<connection_block>
<switch name="ipin_cblock" circuit_model_name="mux_tree_tapbuf"/>
</connection_block>
<switch_block>
<switch name="0" circuit_model_name="mux_tree_tapbuf"/>
</switch_block>
<routing_segment>
<segment name="L4" circuit_model_name="chan_segment"/>
</routing_segment>
<tile_annotations>
<global_port name="clk" is_clock="true" default_val="0">
<!-- MUST explicitly define the number of clock bits
being consistent with physical tile port definition
-->
<tile name="clb" port="clk[0:3]" x="-1" y="-1"/>
</global_port>
</tile_annotations>
<pb_type_annotations>
<!-- physical pb_type binding in complex block IO -->
<pb_type name="io" physical_mode_name="physical" idle_mode_name="inpad"/>
<pb_type name="io[physical].iopad" circuit_model_name="GPIO" mode_bits="1"/>
<pb_type name="io[inpad].inpad" physical_pb_type_name="io[physical].iopad" mode_bits="1"/>
<pb_type name="io[outpad].outpad" physical_pb_type_name="io[physical].iopad" mode_bits="0"/>
<!-- End physical pb_type binding in complex block IO -->
<!-- physical pb_type binding in complex block CLB -->
<!-- physical mode will be the default mode if not specified -->
<pb_type name="clb">
<!-- Binding interconnect to circuit models as their physical implementation, if not defined, we use the default model -->
<interconnect name="crossbar" circuit_model_name="mux_tree"/>
</pb_type>
<pb_type name="clb.fle[n1_lut4].ble4.lut4" circuit_model_name="lut4"/>
<pb_type name="clb.fle[n1_lut4].ble4.ff" circuit_model_name="DFFSRQ"/>
<!-- End physical pb_type binding in complex block IO -->
</pb_type_annotations>
</openfpga_architecture>

View File

@ -169,7 +169,9 @@
<segment name="L4" circuit_model_name="chan_segment"/>
</routing_segment>
<tile_annotations>
<global_port name="clk" tile_port="clb.clk" is_clock="true" default_val="0"/>
<global_port name="clk" is_clock="true" default_val="0">
<tile name="clb" port="clk" x="-1" y="-1"/>
</global_port>
</tile_annotations>
<pb_type_annotations>
<!-- physical pb_type binding in complex block IO -->

View File

@ -0,0 +1,198 @@
<!-- Architecture annotation for OpenFPGA framework
This annotation supports the k6_N10_40nm.xml
- General purpose logic block
- K = 6, N = 10, I = 40
- Single mode
- Routing architecture
- L = 4, fc_in = 0.15, fc_out = 0.1
-->
<openfpga_architecture>
<technology_library>
<device_library>
<device_model name="logic" type="transistor">
<lib type="industry" corner="TOP_TT" ref="M" path="${OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.pm"/>
<design vdd="0.9" pn_ratio="2"/>
<pmos name="pch" chan_length="40e-9" min_width="140e-9" variation="logic_transistor_var"/>
<nmos name="nch" chan_length="40e-9" min_width="140e-9" variation="logic_transistor_var"/>
</device_model>
<device_model name="io" type="transistor">
<lib type="academia" ref="M" path="${OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.pm"/>
<design vdd="2.5" pn_ratio="3"/>
<pmos name="pch_25" chan_length="270e-9" min_width="320e-9" variation="io_transistor_var"/>
<nmos name="nch_25" chan_length="270e-9" min_width="320e-9" variation="io_transistor_var"/>
</device_model>
</device_library>
<variation_library>
<variation name="logic_transistor_var" abs_deviation="0.1" num_sigma="3"/>
<variation name="io_transistor_var" abs_deviation="0.1" num_sigma="3"/>
</variation_library>
</technology_library>
<circuit_library>
<circuit_model type="inv_buf" name="INVTX1" prefix="INVTX1" is_default="true">
<design_technology type="cmos" topology="inverter" size="1"/>
<device_technology device_model_name="logic"/>
<port type="input" prefix="in" size="1"/>
<port type="output" prefix="out" size="1"/>
<delay_matrix type="rise" in_port="in" out_port="out">
10e-12
</delay_matrix>
<delay_matrix type="fall" in_port="in" out_port="out">
10e-12
</delay_matrix>
</circuit_model>
<circuit_model type="inv_buf" name="buf4" prefix="buf4" is_default="false">
<design_technology type="cmos" topology="buffer" size="1" num_level="2" f_per_stage="4"/>
<device_technology device_model_name="logic"/>
<port type="input" prefix="in" size="1"/>
<port type="output" prefix="out" size="1"/>
<delay_matrix type="rise" in_port="in" out_port="out">
10e-12
</delay_matrix>
<delay_matrix type="fall" in_port="in" out_port="out">
10e-12
</delay_matrix>
</circuit_model>
<circuit_model type="inv_buf" name="tap_buf4" prefix="tap_buf4" is_default="false">
<design_technology type="cmos" topology="buffer" size="1" num_level="3" f_per_stage="4"/>
<device_technology device_model_name="logic"/>
<port type="input" prefix="in" size="1"/>
<port type="output" prefix="out" size="1"/>
<delay_matrix type="rise" in_port="in" out_port="out">
10e-12
</delay_matrix>
<delay_matrix type="fall" in_port="in" out_port="out">
10e-12
</delay_matrix>
</circuit_model>
<circuit_model type="pass_gate" name="TGATE" prefix="TGATE" is_default="true">
<design_technology type="cmos" topology="transmission_gate" nmos_size="1" pmos_size="2"/>
<device_technology device_model_name="logic"/>
<input_buffer exist="false"/>
<output_buffer exist="false"/>
<port type="input" prefix="in" size="1"/>
<port type="input" prefix="sel" size="1"/>
<port type="input" prefix="selb" size="1"/>
<port type="output" prefix="out" size="1"/>
<delay_matrix type="rise" in_port="in sel selb" out_port="out">
10e-12 5e-12 5e-12
</delay_matrix>
<delay_matrix type="fall" in_port="in sel selb" out_port="out">
10e-12 5e-12 5e-12
</delay_matrix>
</circuit_model>
<circuit_model type="chan_wire" name="chan_segment" prefix="track_seg" is_default="true">
<design_technology type="cmos"/>
<input_buffer exist="false"/>
<output_buffer exist="false"/>
<port type="input" prefix="in" size="1"/>
<port type="output" prefix="out" size="1"/>
<wire_param model_type="pi" R="101" C="22.5e-15" num_level="1"/> <!-- model_type could be T, res_val and cap_val DON'T CARE -->
</circuit_model>
<circuit_model type="wire" name="direct_interc" prefix="direct_interc" is_default="true">
<design_technology type="cmos"/>
<input_buffer exist="false"/>
<output_buffer exist="false"/>
<port type="input" prefix="in" size="1"/>
<port type="output" prefix="out" size="1"/>
<wire_param model_type="pi" R="0" C="0" num_level="1"/> <!-- model_type could be T, res_val cap_val should be defined -->
</circuit_model>
<circuit_model type="mux" name="mux_tree" prefix="mux_tree" dump_structural_verilog="true">
<design_technology type="cmos" structure="tree" add_const_input="true" const_input_val="1"/>
<input_buffer exist="true" circuit_model_name="INVTX1"/>
<output_buffer exist="true" circuit_model_name="INVTX1"/>
<pass_gate_logic circuit_model_name="TGATE"/>
<port type="input" prefix="in" size="1"/>
<port type="output" prefix="out" size="1"/>
<port type="sram" prefix="sram" size="1"/>
</circuit_model>
<circuit_model type="mux" name="mux_tree_tapbuf" prefix="mux_tree_tapbuf" is_default="true" dump_structural_verilog="true">
<design_technology type="cmos" structure="tree" add_const_input="true" const_input_val="1"/>
<input_buffer exist="true" circuit_model_name="INVTX1"/>
<output_buffer exist="true" circuit_model_name="tap_buf4"/>
<pass_gate_logic circuit_model_name="TGATE"/>
<port type="input" prefix="in" size="1"/>
<port type="output" prefix="out" size="1"/>
<port type="sram" prefix="sram" size="1"/>
</circuit_model>
<!--DFF subckt ports should be defined as <D> <Q> <CLK> <RESET> <SET> -->
<circuit_model type="ff" name="DFFSRQ" prefix="DFFSRQ" spice_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/spice/dff.sp" verilog_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/verilog/dff.v">
<design_technology type="cmos"/>
<input_buffer exist="true" circuit_model_name="INVTX1"/>
<output_buffer exist="true" circuit_model_name="INVTX1"/>
<port type="input" prefix="D" size="1"/>
<port type="input" prefix="set" lib_name="SET" size="1" is_global="true" default_val="0" is_set="true"/>
<port type="input" prefix="reset" lib_name="RST" size="1" is_global="true" default_val="0" is_reset="true"/>
<port type="output" prefix="Q" size="1"/>
<port type="clock" prefix="clk" lib_name="CK" size="1" is_global="false" default_val="0"/>
</circuit_model>
<circuit_model type="lut" name="lut4" prefix="lut4" dump_structural_verilog="true">
<design_technology type="cmos"/>
<input_buffer exist="true" circuit_model_name="INVTX1"/>
<output_buffer exist="true" circuit_model_name="INVTX1"/>
<lut_input_inverter exist="true" circuit_model_name="INVTX1"/>
<lut_input_buffer exist="true" circuit_model_name="buf4"/>
<pass_gate_logic circuit_model_name="TGATE"/>
<port type="input" prefix="in" size="4"/>
<port type="output" prefix="out" size="1"/>
<port type="sram" prefix="sram" size="16"/>
</circuit_model>
<!--Scan-chain DFF subckt ports should be defined as <D> <Q> <Qb> <CLK> <RESET> <SET> -->
<circuit_model type="ccff" name="DFF" prefix="DFF" spice_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/spice/dff.sp" verilog_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/verilog/dff.v">
<design_technology type="cmos"/>
<input_buffer exist="true" circuit_model_name="INVTX1"/>
<output_buffer exist="true" circuit_model_name="INVTX1"/>
<port type="input" prefix="D" size="1"/>
<port type="output" prefix="Q" size="1"/>
<port type="output" prefix="QN" size="1"/>
<port type="clock" prefix="prog_clk" lib_name="CK" size="1" is_global="true" default_val="0" is_prog="true"/>
</circuit_model>
<circuit_model type="iopad" name="GPIO" prefix="GPIO" spice_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/spice/gpio.sp" verilog_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/verilog/gpio.v">
<design_technology type="cmos"/>
<input_buffer exist="true" circuit_model_name="INVTX1"/>
<output_buffer exist="true" circuit_model_name="INVTX1"/>
<port type="inout" prefix="PAD" size="1" is_global="true" is_io="true" is_data_io="true"/>
<port type="sram" prefix="DIR" size="1" mode_select="true" circuit_model_name="DFF" default_val="1"/>
<port type="input" prefix="outpad" lib_name="A" size="1"/>
<port type="output" prefix="inpad" lib_name="Y" size="1"/>
</circuit_model>
</circuit_library>
<configuration_protocol>
<organization type="scan_chain" circuit_model_name="DFF"/>
</configuration_protocol>
<connection_block>
<switch name="ipin_cblock" circuit_model_name="mux_tree_tapbuf"/>
</connection_block>
<switch_block>
<switch name="0" circuit_model_name="mux_tree_tapbuf"/>
</switch_block>
<routing_segment>
<segment name="L4" circuit_model_name="chan_segment"/>
</routing_segment>
<tile_annotations>
<global_port name="clk" is_clock="true" default_val="0">
<tile name="clb" port="clk" x="-1" y="-1"/>
<tile name="io" port="clk" x="-1" y="-1"/>
</global_port>
</tile_annotations>
<pb_type_annotations>
<!-- physical pb_type binding in complex block IO -->
<pb_type name="io" physical_mode_name="physical" idle_mode_name="inpad"/>
<pb_type name="io[physical].iopad" circuit_model_name="GPIO" mode_bits="1"/>
<pb_type name="io[physical].ff" circuit_model_name="DFFSRQ"/>
<pb_type name="io[inpad].inpad" physical_pb_type_name="io[physical].iopad" mode_bits="1"/>
<pb_type name="io[inpad_registered].inpad" physical_pb_type_name="io[physical].iopad" mode_bits="1"/>
<pb_type name="io[inpad_registered].ff" physical_pb_type_name="io[physical].ff"/>
<pb_type name="io[outpad].outpad" physical_pb_type_name="io[physical].iopad" mode_bits="0"/>
<!-- End physical pb_type binding in complex block IO -->
<!-- physical pb_type binding in complex block CLB -->
<!-- physical mode will be the default mode if not specified -->
<pb_type name="clb">
<!-- Binding interconnect to circuit models as their physical implementation, if not defined, we use the default model -->
<interconnect name="crossbar" circuit_model_name="mux_tree"/>
</pb_type>
<pb_type name="clb.fle[n1_lut4].ble4.lut4" circuit_model_name="lut4"/>
<pb_type name="clb.fle[n1_lut4].ble4.ff" circuit_model_name="DFFSRQ"/>
<!-- End physical pb_type binding in complex block IO -->
</pb_type_annotations>
</openfpga_architecture>

View File

@ -0,0 +1,194 @@
<!-- Architecture annotation for OpenFPGA framework
This annotation supports the k6_N10_40nm.xml
- General purpose logic block
- K = 6, N = 10, I = 40
- Single mode
- Routing architecture
- L = 4, fc_in = 0.15, fc_out = 0.1
-->
<openfpga_architecture>
<technology_library>
<device_library>
<device_model name="logic" type="transistor">
<lib type="industry" corner="TOP_TT" ref="M" path="${OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.pm"/>
<design vdd="0.9" pn_ratio="2"/>
<pmos name="pch" chan_length="40e-9" min_width="140e-9" variation="logic_transistor_var"/>
<nmos name="nch" chan_length="40e-9" min_width="140e-9" variation="logic_transistor_var"/>
</device_model>
<device_model name="io" type="transistor">
<lib type="academia" ref="M" path="${OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.pm"/>
<design vdd="2.5" pn_ratio="3"/>
<pmos name="pch_25" chan_length="270e-9" min_width="320e-9" variation="io_transistor_var"/>
<nmos name="nch_25" chan_length="270e-9" min_width="320e-9" variation="io_transistor_var"/>
</device_model>
</device_library>
<variation_library>
<variation name="logic_transistor_var" abs_deviation="0.1" num_sigma="3"/>
<variation name="io_transistor_var" abs_deviation="0.1" num_sigma="3"/>
</variation_library>
</technology_library>
<circuit_library>
<circuit_model type="inv_buf" name="INVTX1" prefix="INVTX1" is_default="true">
<design_technology type="cmos" topology="inverter" size="1"/>
<device_technology device_model_name="logic"/>
<port type="input" prefix="in" size="1"/>
<port type="output" prefix="out" size="1"/>
<delay_matrix type="rise" in_port="in" out_port="out">
10e-12
</delay_matrix>
<delay_matrix type="fall" in_port="in" out_port="out">
10e-12
</delay_matrix>
</circuit_model>
<circuit_model type="inv_buf" name="buf4" prefix="buf4" is_default="false">
<design_technology type="cmos" topology="buffer" size="1" num_level="2" f_per_stage="4"/>
<device_technology device_model_name="logic"/>
<port type="input" prefix="in" size="1"/>
<port type="output" prefix="out" size="1"/>
<delay_matrix type="rise" in_port="in" out_port="out">
10e-12
</delay_matrix>
<delay_matrix type="fall" in_port="in" out_port="out">
10e-12
</delay_matrix>
</circuit_model>
<circuit_model type="inv_buf" name="tap_buf4" prefix="tap_buf4" is_default="false">
<design_technology type="cmos" topology="buffer" size="1" num_level="3" f_per_stage="4"/>
<device_technology device_model_name="logic"/>
<port type="input" prefix="in" size="1"/>
<port type="output" prefix="out" size="1"/>
<delay_matrix type="rise" in_port="in" out_port="out">
10e-12
</delay_matrix>
<delay_matrix type="fall" in_port="in" out_port="out">
10e-12
</delay_matrix>
</circuit_model>
<circuit_model type="pass_gate" name="TGATE" prefix="TGATE" is_default="true">
<design_technology type="cmos" topology="transmission_gate" nmos_size="1" pmos_size="2"/>
<device_technology device_model_name="logic"/>
<input_buffer exist="false"/>
<output_buffer exist="false"/>
<port type="input" prefix="in" size="1"/>
<port type="input" prefix="sel" size="1"/>
<port type="input" prefix="selb" size="1"/>
<port type="output" prefix="out" size="1"/>
<delay_matrix type="rise" in_port="in sel selb" out_port="out">
10e-12 5e-12 5e-12
</delay_matrix>
<delay_matrix type="fall" in_port="in sel selb" out_port="out">
10e-12 5e-12 5e-12
</delay_matrix>
</circuit_model>
<circuit_model type="chan_wire" name="chan_segment" prefix="track_seg" is_default="true">
<design_technology type="cmos"/>
<input_buffer exist="false"/>
<output_buffer exist="false"/>
<port type="input" prefix="in" size="1"/>
<port type="output" prefix="out" size="1"/>
<wire_param model_type="pi" R="101" C="22.5e-15" num_level="1"/> <!-- model_type could be T, res_val and cap_val DON'T CARE -->
</circuit_model>
<circuit_model type="wire" name="direct_interc" prefix="direct_interc" is_default="true">
<design_technology type="cmos"/>
<input_buffer exist="false"/>
<output_buffer exist="false"/>
<port type="input" prefix="in" size="1"/>
<port type="output" prefix="out" size="1"/>
<wire_param model_type="pi" R="0" C="0" num_level="1"/> <!-- model_type could be T, res_val cap_val should be defined -->
</circuit_model>
<circuit_model type="mux" name="mux_tree" prefix="mux_tree" dump_structural_verilog="true">
<design_technology type="cmos" structure="tree" add_const_input="true" const_input_val="1"/>
<input_buffer exist="true" circuit_model_name="INVTX1"/>
<output_buffer exist="true" circuit_model_name="INVTX1"/>
<pass_gate_logic circuit_model_name="TGATE"/>
<port type="input" prefix="in" size="1"/>
<port type="output" prefix="out" size="1"/>
<port type="sram" prefix="sram" size="1"/>
</circuit_model>
<circuit_model type="mux" name="mux_tree_tapbuf" prefix="mux_tree_tapbuf" is_default="true" dump_structural_verilog="true">
<design_technology type="cmos" structure="tree" add_const_input="true" const_input_val="1"/>
<input_buffer exist="true" circuit_model_name="INVTX1"/>
<output_buffer exist="true" circuit_model_name="tap_buf4"/>
<pass_gate_logic circuit_model_name="TGATE"/>
<port type="input" prefix="in" size="1"/>
<port type="output" prefix="out" size="1"/>
<port type="sram" prefix="sram" size="1"/>
</circuit_model>
<!--DFF subckt ports should be defined as <D> <Q> <CLK> <RESET> <SET> -->
<circuit_model type="ff" name="DFFSRQ" prefix="DFFSRQ" spice_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/spice/dff.sp" verilog_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/verilog/dff.v">
<design_technology type="cmos"/>
<input_buffer exist="true" circuit_model_name="INVTX1"/>
<output_buffer exist="true" circuit_model_name="INVTX1"/>
<port type="input" prefix="D" size="1"/>
<port type="input" prefix="set" lib_name="SET" size="1" is_global="true" default_val="0" is_set="true"/>
<port type="input" prefix="reset" lib_name="RST" size="1" is_global="true" default_val="0" is_reset="true"/>
<port type="output" prefix="Q" size="1"/>
<port type="clock" prefix="clk" lib_name="CK" size="1" is_global="true" default_val="0" />
</circuit_model>
<circuit_model type="lut" name="lut4" prefix="lut4" dump_structural_verilog="true">
<design_technology type="cmos"/>
<input_buffer exist="true" circuit_model_name="INVTX1"/>
<output_buffer exist="true" circuit_model_name="INVTX1"/>
<lut_input_inverter exist="true" circuit_model_name="INVTX1"/>
<lut_input_buffer exist="true" circuit_model_name="buf4"/>
<pass_gate_logic circuit_model_name="TGATE"/>
<port type="input" prefix="in" size="4"/>
<port type="output" prefix="out" size="1"/>
<port type="sram" prefix="sram" size="16"/>
</circuit_model>
<!--Scan-chain DFF subckt ports should be defined as <D> <Q> <Qb> <CLK> <RESET> <SET> -->
<circuit_model type="ccff" name="CFGSDFFR" prefix="CFGSDFFR" spice_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/spice/dff.sp" verilog_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/verilog/dff.v">
<design_technology type="cmos"/>
<input_buffer exist="true" circuit_model_name="INVTX1"/>
<output_buffer exist="true" circuit_model_name="INVTX1"/>
<port type="input" prefix="pReset" lib_name="RST" size="1" is_global="true" default_val="0" is_reset="true" is_prog="true"/>
<port type="input" prefix="SE" size="1" is_global="true" default_val="0"/>
<port type="input" prefix="config_enable" lib_name="CFGE" size="1" is_global="true" default_val="0" is_config_enable="true"/>
<port type="input" prefix="D" size="1"/>
<port type="input" prefix="SI" size="1"/>
<port type="output" prefix="Q" size="1"/>
<port type="output" prefix="CFGQN" size="1"/>
<port type="output" prefix="CFGQ" size="1"/>
<port type="clock" prefix="prog_clk" lib_name="CK" size="1" is_global="true" default_val="0" is_prog="true"/>
</circuit_model>
<circuit_model type="iopad" name="GPIO" prefix="GPIO" spice_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/spice/gpio.sp" verilog_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/verilog/gpio.v">
<design_technology type="cmos"/>
<input_buffer exist="true" circuit_model_name="INVTX1"/>
<output_buffer exist="true" circuit_model_name="INVTX1"/>
<port type="inout" prefix="PAD" size="1" is_global="true" is_io="true" is_data_io="true"/>
<port type="sram" prefix="DIR" size="1" mode_select="true" circuit_model_name="CFGSDFFR" default_val="1"/>
<port type="input" prefix="outpad" lib_name="A" size="1"/>
<port type="output" prefix="inpad" lib_name="Y" size="1"/>
</circuit_model>
</circuit_library>
<configuration_protocol>
<organization type="scan_chain" circuit_model_name="CFGSDFFR"/>
</configuration_protocol>
<connection_block>
<switch name="ipin_cblock" circuit_model_name="mux_tree_tapbuf"/>
</connection_block>
<switch_block>
<switch name="0" circuit_model_name="mux_tree_tapbuf"/>
</switch_block>
<routing_segment>
<segment name="L4" circuit_model_name="chan_segment"/>
</routing_segment>
<pb_type_annotations>
<!-- physical pb_type binding in complex block IO -->
<pb_type name="io" physical_mode_name="physical" idle_mode_name="inpad"/>
<pb_type name="io[physical].iopad" circuit_model_name="GPIO" mode_bits="1"/>
<pb_type name="io[inpad].inpad" physical_pb_type_name="io[physical].iopad" mode_bits="1"/>
<pb_type name="io[outpad].outpad" physical_pb_type_name="io[physical].iopad" mode_bits="0"/>
<!-- End physical pb_type binding in complex block IO -->
<!-- physical pb_type binding in complex block CLB -->
<!-- physical mode will be the default mode if not specified -->
<pb_type name="clb">
<!-- Binding interconnect to circuit models as their physical implementation, if not defined, we use the default model -->
<interconnect name="crossbar" circuit_model_name="mux_tree"/>
</pb_type>
<pb_type name="clb.fle[n1_lut4].ble4.lut4" circuit_model_name="lut4"/>
<pb_type name="clb.fle[n1_lut4].ble4.ff" circuit_model_name="DFFSRQ"/>
<!-- End physical pb_type binding in complex block IO -->
</pb_type_annotations>
</openfpga_architecture>

Some files were not shown because too many files have changed in this diff Show More