Merge remote-tracking branch 'lnis_origin/master' into ganesh_dev
This commit is contained in:
commit
fec1d8eeb2
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -136,6 +136,8 @@ Pass Gate Logic
|
|||
.. note:: pass-gate logic are used in building multiplexers and LUTs.
|
||||
|
||||
|
||||
.. _circuit_library_circuit_port:
|
||||
|
||||
Circuit Port
|
||||
^^^^^^^^^^^^
|
||||
|
||||
|
|
|
@ -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
|
||||
~~~~~~~~~~~
|
||||
|
||||
|
|
|
@ -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 |
|
@ -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 |
|
@ -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 |
|
@ -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>``
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
File Formats
|
||||
------------
|
||||
|
||||
OpenFPGA widely uses XML format for interchangable files
|
||||
|
||||
|
||||
.. _file_formats:
|
||||
File formats
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
pin_constraints_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.
|
|
@ -12,3 +12,5 @@ FPGA-Bitstream can generate two types of bitstreams:
|
|||
generic_bitstream
|
||||
|
||||
fabric_dependent_bitstream
|
||||
|
||||
repack_design_constraints
|
||||
|
|
|
@ -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
|
|
@ -16,3 +16,5 @@
|
|||
|
||||
fpga_bitstream/index
|
||||
|
||||
file_formats/index
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
- ``--verbose`` Show verbose log
|
||||
- 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!!!**
|
||||
|
||||
.. option:: --verbose
|
||||
|
||||
Show verbose log
|
||||
|
||||
build_architecture_bitstream
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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));
|
||||
|
|
|
@ -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_;
|
||||
|
|
|
@ -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");
|
||||
|
@ -38,7 +38,19 @@ 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());
|
||||
|
|
|
@ -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>";
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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})
|
|
@ -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 */
|
||||
|
|
|
@ -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@";
|
||||
}
|
|
@ -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
|
|
@ -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})
|
|
@ -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>
|
||||
|
|
@ -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] );
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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})
|
|
@ -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>
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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] );
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -23,8 +23,10 @@ target_link_libraries(libopenfpga
|
|||
libopenfpgashell
|
||||
libopenfpgautil
|
||||
libfabrickey
|
||||
librepackdc
|
||||
libfpgabitstream
|
||||
libini
|
||||
libpcf
|
||||
libvtrutil
|
||||
libvpr)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
@ -90,21 +94,25 @@ int write_verilog_testbench(OpenfpgaContext& openfpga_ctx,
|
|||
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);
|
||||
/* 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());
|
||||
}
|
||||
|
||||
/* TODO: should identify the error code from internal function execution */
|
||||
return CMD_EXEC_SUCCESS;
|
||||
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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
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],
|
||||
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());
|
||||
/* 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, data_output_port_to_connect,
|
||||
sram_mem_module, i, sram_mem_instance);
|
||||
}
|
||||
}
|
||||
|
||||
/* 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),
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* Bypass the tiles whose names do not match */
|
||||
if (std::string(grids[io_coordinate.x()][io_coordinate.y()].type->name) != tile_name) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return CMD_EXEC_SUCCESS;
|
||||
return status;
|
||||
}
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
|
|
@ -21,6 +21,9 @@ FabricBitstream::FabricBitstream() {
|
|||
|
||||
num_regions_ = 0;
|
||||
invalid_region_ids_.clear();
|
||||
|
||||
use_address_ = false;
|
||||
use_wl_address_ = false;
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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 ! */
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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()) {
|
||||
continue;
|
||||
}
|
||||
if (size_t(tile_port.num_pins) != tile_annotation.global_port_tile_port(tile_global_port).get_width()) {
|
||||
for (const t_physical_tile_type& physical_tile : physical_tile_types) {
|
||||
if (std::string(physical_tile.name) != required_tile_name) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Check if port property matches */
|
||||
int grid_pin_index = tile_port.absolute_first_pin_index;
|
||||
/* Found a match, increment the counter */
|
||||
found_matched_physical_tile++;
|
||||
|
||||
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++;
|
||||
/* 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++;
|
||||
}
|
||||
|
||||
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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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>
|
|
@ -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 -->
|
||||
|
|
|
@ -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>
|
|
@ -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
Loading…
Reference in New Issue