Merge branch 'master' into tutorials

This commit is contained in:
bbleaptrot 2021-06-16 14:00:31 -06:00 committed by GitHub
commit de550ac550
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
226 changed files with 12952 additions and 1390 deletions

View File

@ -7,26 +7,49 @@ assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
> **Describe the bug**
> A clear and concise description of what the bug is.
<!--- Uncomment relevant options --->
<!-- Which part of OpenFPGA is buggy -->
<!--- [ ] Documentation --->
<!--- [ ] OpenFPGA flow --->
<!--- [ ] FPGA-Verilog --->
<!--- [ ] FPGA-Bitstream --->
<!--- [ ] FPGA-SDC --->
<!--- [ ] FPGA-SPICE --->
<!--- [ ] VPR --->
<!--- [ ] Yosys --->
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
> **To Reproduce**
> Steps to reproduce the behavior:
> 1. Clone OpenFPGA repository and checkout commit id: <The problem commit id>
> 2. Execute OpenFPGA task or your own example: <more details>
> 3. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
> **Expected behavior**
> A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
> **Screenshots**
> If applicable, add screenshots to help explain your problem.
**Enviornment (please complete the following information):**
- OS: [e.g. CentOs, Ubuntu]
- Compiler [e.g. gcc, clang]
- Version [e.g. Github commit id]
> **Enviornment (please complete the following information):**
<!--- Uncomment relevant options --->
> - OS:
<!--- - [ ] CentOS 7 --->
<!--- - [ ] Ubuntu 18.04 --->
<!--- - [ ] Others. If so, please specify: --->
> - Compiler:
<!--- - [ ] gcc-5 --->
<!--- - [ ] gcc-6 --->
<!--- - [ ] gcc-7 --->
<!--- - [ ] gcc-8 --->
<!--- - [ ] gcc-9 --->
<!--- - [ ] clang-6 --->
<!--- - [ ] clang-8 --->
<!--- - [ ] Others. If so, please specify: --->
> - Version:
<!--- - [ ] Current master --->
<!--- - [ ] Others. If so, please specify Github commit id: --->
**Additional context**
Add any other context about the problem here.
> **Additional context**
> Add any other context about the problem here.

View File

@ -1,33 +1,39 @@
---
name: Pull request
about: Push a change to this project
---
> ### Motivate of the pull request
> - [ ] To address an existing issue. If so, please provide a link to the issue: <issue id>
> - [ ] Breaking new feature. If so, please describe details in the description part.
### Motivate of the pull request
- [ ] To address an existing issue. If so, please provide a link to the issue.
- [ ] Breaking new feature. If so, please decribe details in the description part.
> ### Describe the technical details
> #### What is currently done? (Provide issue link if applicable)
> <!-- Please provide a list of limitations if not specified in any issue -->
> <!-- Below is a template, uncomment upon your needs -->
> <!-- Currently, OpenFPGA has the following limitations: -->
> <!-- - [ ] technical details about limitation -->
> <!-- - [ ] more limitations -->
>
> #### What does this pull request change?
> <!-- Please provide a list of highlights of your changes. -->
> <!-- Below is a template, uncomment upon your needs -->
> <!-- This PR improves in the following aspects: -->
> <!-- - [ ] details about the technical highlight -->
> <!-- - [ ] <more technical highlights -->
### Describe the technical details
- What is currently done? (Provide issue link if applicable)
- What does this pull request change?
> ### Which part of the code base require a change
> <!-- In general, modification on existing submodules are not acceptable. You should push changes to upstream. -->
> - [ ] VPR
> - [ ] Tileable routing architecture generator
> - [ ] OpenFPGA libraries
> - [ ] FPGA-Verilog
> - [ ] FPGA-Bitstream
> - [ ] FPGA-SDC
> - [ ] FPGA-SPICE
> - [ ] Flow scripts
> - [ ] Architecture library
> - [ ] Cell library
> - [ ] Documentation
> - [ ] Regression tests
> - [ ] Continous Integration (CI) scripts
### Which part of the code base require a change
**In general, modification on existing submodules are not acceptable. You should push changes to upstream.**
- [ ] VPR
- [ ] OpenFPGA libraries
- [ ] FPGA-Verilog
- [ ] FPGA-Bitstream
- [ ] FPGA-SDC
- [ ] FPGA-SPICE
- [ ] Flow scripts
- [ ] Architecture library
- [ ] Cell library
> ### Impact of the pull request
### Checklist of the pull request
- [ ] Require code changes.
- [ ] Require new tests to be added
- [ ] Require an update on documentation
### Impact of the pull request
- [ ] Require a change on Quality of Results (QoR)
- [ ] Break back-compatibility. If so, please list who may be influenced.
> - [ ] Require a change on Quality of Results (QoR)
> - [ ] Break back-compatibility. If so, please list who may be influenced.

View File

@ -1,33 +1,39 @@
---
name: Pull request
about: Push a change to this project
---
> ### Motivate of the pull request
> - [ ] To address an existing issue. If so, please provide a link to the issue: <issue id>
> - [ ] Breaking new feature. If so, please describe details in the description part.
### Motivate of the pull request
- [ ] To address an existing issue. If so, please provide a link to the issue.
- [ ] Breaking new feature. If so, please decribe details in the description part.
> ### Describe the technical details
> #### What is currently done? (Provide issue link if applicable)
> <!-- Please provide a list of limitations if not specified in any issue -->
> <!-- Below is a template, uncomment upon your needs -->
> <!-- Currently, OpenFPGA has the following limitations: -->
> <!-- - [ ] technical details about limitation -->
> <!-- - [ ] more limitations -->
>
> #### What does this pull request change?
> <!-- Please provide a list of highlights of your changes. -->
> <!-- Below is a template, uncomment upon your needs -->
> <!-- This PR improves in the following aspects: -->
> <!-- - [ ] details about the technical highlight -->
> <!-- - [ ] <more technical highlights -->
### Describe the technical details
- What is currently done? (Provide issue link if applicable)
- What does this pull request change?
> ### Which part of the code base require a change
> <!-- In general, modification on existing submodules are not acceptable. You should push changes to upstream. -->
> - [ ] VPR
> - [ ] Tileable routing architecture generator
> - [ ] OpenFPGA libraries
> - [ ] FPGA-Verilog
> - [ ] FPGA-Bitstream
> - [ ] FPGA-SDC
> - [ ] FPGA-SPICE
> - [ ] Flow scripts
> - [ ] Architecture library
> - [ ] Cell library
> - [ ] Documentation
> - [ ] Regression tests
> - [ ] Continous Integration (CI) scripts
### Which part of the code base require a change
**In general, modification on existing submodules are not acceptable. You should push changes to upstream.**
- [ ] VPR
- [ ] OpenFPGA libraries
- [ ] FPGA-Verilog
- [ ] FPGA-Bitstream
- [ ] FPGA-SDC
- [ ] FPGA-SPICE
- [ ] Flow scripts
- [ ] Architecture library
- [ ] Cell library
> ### Impact of the pull request
### Checklist of the pull request
- [ ] Require code changes.
- [ ] Require new tests to be added
- [ ] Require an update on documentation
### Impact of the pull request
- [ ] Require a change on Quality of Results (QoR)
- [ ] Break back-compatibility. If so, please list who may be influenced.
> - [ ] Require a change on Quality of Results (QoR)
> - [ ] Break back-compatibility. If so, please list who may be influenced.

View File

@ -91,7 +91,6 @@ else ()
"-D__USE_FIXED_PROTOTYPES__"
"-ansi"
"-Wshadow"
"-Wcast-allign"
"-Wno-write-strings"
"-D_POSIX_SOURCE"
"-Wall" #Most warnings, typically good

View File

@ -223,7 +223,9 @@ The ``circuit_model_name`` should match the given name of a ``circuit_model`` de
.. note:: A ``<pb_type name="<string>">`` parent XML node is required for the interconnect-to-circuit bindings whose interconnects are defined under the ``pb_type`` in VPR architecture description.
.. option:: <port name="<string>" physical_mode_port="<string>"
physical_mode_pin_initial_offset="<int>" physical_mode_pin_rotate_offset="<int>"/>
physical_mode_pin_initial_offset="<int>"
physical_mode_pin_rotate_offset="<int>"/>
physical_mode_port_rotate_offset="<int>"/>
Link a port of an operating ``pb_type`` to a port of a physical ``pb_type``
@ -233,7 +235,6 @@ The ``circuit_model_name`` should match the given name of a ``circuit_model`` de
.. note:: Users can define multiple ports. For example: ``physical_mode_pin="a[0:1] b[2:2]"``. When multiple ports are used, the ``physical_mode_pin_initial_offset`` and ``physical_mode_pin_rotate_offset`` should also be adapt. For example: ``physical_mode_pin_rotate_offset="1 0"``)
- ``physical_mode_pin_initial_offset="<int>"`` aims to align the pin indices for ``port`` of ``pb_type`` between operating and physical modes, especially when part of port of operating mode is mapped to a port in physical ``pb_type``. When ``physical_mode_pin_initial_offset`` is larger than zero, the pin index of ``pb_type`` (whose index is large than 1) will be shifted by the given offset.
.. note:: A quick example to understand the initial offset
@ -249,7 +250,24 @@ The ``circuit_model_name`` should match the given name of a ``circuit_model`` de
.. note:: If not defined, the default value of ``physical_mode_pin_initial_offset`` is set to ``0``.
- ``physical_mode_pin_rotate_offset="<int>"`` aims to align the pin indices for ``port`` of ``pb_type`` between operating and physical modes, especially when an operating mode contains multiple ``pb_type`` (``num_pb``>1) that are linked to the same physical ``pb_type``. When ``physical_mode_pin_rotate_offset`` is larger than zero, the pin index of ``pb_type`` (whose index is large than 1) will be shifted by the given offset.
- ``physical_mode_pin_rotate_offset="<int>"`` aims to align the pin indices for ``port`` of ``pb_type`` between operating and physical modes, especially when an operating mode contains multiple ``pb_type`` (``num_pb``>1) that are linked to the same physical ``pb_type``. When ``physical_mode_pin_rotate_offset`` is larger than zero, the pin index of ``pb_type`` (whose index is large than 1) will be shifted by the given offset, **each time a pin in the operating mode is binded to a pin in the physical mode**.
.. note:: A quick example to understand the rotate offset
For example, a rotating offset of 9 is used to map
- operating pb_type ``mult_9x9[0].a[0]`` with a full path ``mult[frac].mult_9x9[0]``
- operating pb_type ``mult_9x9[1].a[1]`` with a full path ``mult[frac].mult_9x9[1]``
to
- physical pb_type ``mult_36x36.a[0]`` with a full path ``mult[physical].mult_36x36[0]``
- physical pb_type ``mult_36x36.a[9]`` with a full path ``mult[physical].mult_36x36[0]``
.. note:: If not defined, the default value of ``physical_mode_pin_rotate_offset`` is set to ``0``.
.. warning:: The result of using ``physical_mode_pin_rotate_offset`` is fundementally different than ``physical_mode_port_rotate_offset``!!! Please read the examples carefully and pick the one fitting your needs.
- ``physical_mode_port_rotate_offset="<int>"`` aims to align the port indices for ``port`` of ``pb_type`` between operating and physical modes, especially when an operating mode contains multiple ``pb_type`` (``num_pb``>1) that are linked to the same physical ``pb_type``. When ``physical_mode_port_rotate_offset`` is larger than zero, the pin index of ``pb_type`` (whose index is large than 1) will be shifted by the given offset, **only when all the pins of a port in the operating mode is binded to all the pins of a port in the physical mode**.
.. note:: A quick example to understand the rotate offset
For example, a rotating offset of 9 is used to map
@ -262,7 +280,8 @@ The ``circuit_model_name`` should match the given name of a ``circuit_model`` de
- physical pb_type ``mult_36x36.a[0:8]`` with a full path ``mult[physical].mult_36x36[0]``
- physical pb_type ``mult_36x36.a[9:17]`` with a full path ``mult[physical].mult_36x36[0]``
.. note:: If not defined, the default value of ``physical_mode_pin_rotate_offset`` is set to ``0``.
.. note:: If not defined, the default value of ``physical_mode_port_rotate_offset`` is set to ``0``.
.. note::
It is highly recommended that only one physical mode is defined for a multi-mode configurable block. Try not to use nested physical mode definition. This will ease the debugging and lead to clean XML description.

View File

@ -284,6 +284,8 @@ This example shows:
SRAMs
~~~~~
.. note:: OpenFPGA does not auto-generate any netlist for SRAM cells. Users should define the HDL modeling in external netlists and ensure consistency to physical designs.
Template
````````
@ -963,16 +965,17 @@ This example shows:
.. note:: If the embedded harden logic are driven partially by LUT outputs, users may use the :ref:`file_formats_bitstream_setting` to gaurantee correct bitstream generation for the LUTs.
Datapath Flip-Flops
~~~~~~~~~~~~~~~~~~~
Flip-Flops
~~~~~~~~~~
.. note:: OpenFPGA does not auto-generate any netlist for datapath flip-flops. Users should define the HDL modeling in external netlists and ensure consistency to physical designs.
Template
````````
.. code-block:: xml
<circuit_model type="ccff|ff" name="<string>" prefix="<string>" spice_netlist="<string>" verilog_netlist="<string>"/>
<circuit_model type="ff" name="<string>" prefix="<string>" spice_netlist="<string>" verilog_netlist="<string>"/>
<design_technology type="cmos"/>
<input_buffer exist="<string>" circuit_model_name="<string>"/>
<output_buffer exist="<string>" circuit_model_name="<string>"/>
@ -987,16 +990,14 @@ Template
.. note:: FPGA-Verilog/SPICE currently support only one clock domain in the FPGA. Therefore there should be only one clock port to be defined and the size of the clock port should be 1.
.. option:: <circuit_model type="ccff|ff" name="<string>" prefix="<string>" spice_netlist="<string>" verilog_netlist="<string>"/>
.. option:: type="ff"
- ``type="ccff|ff"`` Specify the type of a flip-flop. ``ff`` is a regular flip-flop while ``ccff`` denotes a configuration-chain flip-flop
``ff`` is a regular flip-flop to be used in datapath logic, e.g., a configurable logic block.
.. note:: A flip-flop should at least have three types of ports, ``input``, ``output`` and ``clock``.
.. note:: If the user provides a customized Verilog/SPICE netlist, the bandwidth of ports should be defined to the same as the Verilog/SPICE netlist.
.. note:: In a valid FPGA architecture, users should provide at least either a ``ccff`` or ``sram`` circuit model, so that the configurations can loaded to core logic.
.. _circuit_model_dff_example:
D-type Flip-Flop
@ -1029,6 +1030,70 @@ This example shows:
- The flip-flop has ``set`` and ``reset`` functionalities
- The flip-flop port names defined differently in standard cell library and VPR architecture. The ``lib_name`` capture the port name defined in standard cells, while ``prefix`` capture the port name defined in ``pb_type`` of VPR architecture file
.. _circuit_model_multi_mode_ff_example:
Multi-mode Flip-Flop
````````````````````
:numref:`fig_multi_mode_ff_circuit_model` illustrates an example of a flip-flop which can be operate in different modes.
.. _fig_multi_mode_ff_circuit_model:
.. figure:: ./figures/multi_mode_ff_circuit_model.svg
:scale: 150%
:alt: Multi-mode flip-flop example
An example of a flip-flop which can be operate in different modes
The code describing this FF is:
.. code-block:: xml
<circuit_model type="ff" name="frac_ff" prefix="frac_ff" verilog_netlist="frac_ff.v" spice_netlist="frac_ff.sp">
<port type="input" prefix="D" lib_name="D" size="1"/>
<port type="input" prefix="Reset" lib_name="RST_OP" size="1" is_global="true"/>
<port type="output" prefix="Q" lib_name="Q" size="1"/>
<port type="clock" prefix="clock" lib_name="CLK" size="1" is_global="true"/>
<port type="sram" prefix="MODE" lib_name="MODE" size="1" mode_select="true" circuit_model_name="CCFF" default_value="0"/>
</circuit_model>
This example shows:
- A multi-mode flip-flop which is defined in a Verilog netlist ``frac_ff.v`` and a SPICE netlist ``frac_ff.sp``
- The flip-flop has a ``reset`` pin which can be either active-low or active-high, depending on the mode selection pin ``MODE``.
- The mode-selection bit will be generated by a configurable memory outside the flip-flop, which will be implemented by a circuit model ``CCFF`` defined by users (see an example in :ref:`circuit_model_ccff_example`).
- The flip-flop port names defined differently in standard cell library and VPR architecture. The ``lib_name`` capture the port name defined in standard cells, while ``prefix`` capture the port name defined in ``pb_type`` of VPR architecture file
Configuration Chain Flip-Flop
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. note:: OpenFPGA does not auto-generate any netlist for configuration chain flip-flops. Users should define the HDL modeling in external netlists and ensure consistency to physical designs.
Template
````````
.. code-block:: xml
<circuit_model type="ccff" name="<string>" prefix="<string>" spice_netlist="<string>" verilog_netlist="<string>"/>
<design_technology type="cmos"/>
<input_buffer exist="<string>" circuit_model_name="<string>"/>
<output_buffer exist="<string>" circuit_model_name="<string>"/>
<port type="input" prefix="<string>" size="<int>"/>
<port type="output" prefix="<string>" size="<int>"/>
<port type="clock" prefix="<string>" size="<int>"/>
</circuit_model>
.. note:: The circuit designs of configurable memory elements are highly dependent on the technology node and well optimized by engineers. Therefore, FPGA-Verilog/SPICE requires users to provide their customized FF Verilog/SPICE/Verilog netlists. A sample Verilog/SPICE netlist of FF can be found in the directory SpiceNetlists in the released package.
The information of input and output buffer should be clearly specified according to the customized SPICE netlist! The existence of input/output buffers will influence the decision in creating SPICE testbenches, which may leads to larger errors in power analysis.
.. note:: FPGA-Verilog/SPICE currently support only one clock domain for any configuration protocols in the FPGA. Therefore there should be only one clock port to be defined and the size of the clock port should be 1.
.. note:: A flip-flop should at least have three types of ports, ``input``, ``output`` and ``clock``.
.. note:: If the user provides a customized Verilog/SPICE netlist, the bandwidth of ports should be defined to the same as the Verilog/SPICE netlist.
.. note:: In a valid FPGA architecture, users should provide at least either a ``ccff`` or ``sram`` circuit model, so that the configurations can loaded to core logic.
.. _circuit_model_ccff_example:
Regular Configuration-chain Flip-flop
@ -1147,6 +1212,8 @@ The code describing this FF is:
Hard Logics
~~~~~~~~~~~
.. note:: OpenFPGA does not auto-generate any netlist for the hard logics. Users should define the HDL modeling in external netlists and ensure consistency to physical designs.
Template
````````
@ -1175,6 +1242,13 @@ Template
Full Adder
``````````
.. figure:: ./figures/full_adder_1bit_circuit_model.svg
:scale: 200%
:alt: An example of a 1-bit full adder
An example of a 1-bit full adder.
The code describing the 1-bit full adder is:
.. code-block:: xml
@ -1189,6 +1263,134 @@ Full Adder
<port type="output" prefix="sumout" size="1"/>
</circuit_model>
This example shows:
- A 1-bit full adder which is defined in a Verilog netlist ``adder.v`` and a SPICE netlist ``adder.sp``
- The adder has three 1-bit inputs, i.e., ``a``, ``b`` and ``cin``, and two 2-bit outputs, i.e., ``cout``, ``sumout``.
.. _circuit_model_single_mode_mult8x8_example:
Multiplier
``````````
.. figure:: ./figures/single_mode_mult8x8_circuit_model.svg
:scale: 200%
:alt: An example of a 8-bit multiplier.
An example of a 8-bit multiplier.
The code describing the multiplier is:
.. code-block:: xml
<circuit_model type="hard_logic" name="mult8x8" prefix="mult8x8" spice_netlist="dsp.sp" verilog_netlist="dsp.v">
<design_technology type="cmos"/>
<input_buffer exist="true" circuit_model_name="inv1x"/>
<output_buffer exist="true" circuit_model_name="inv1x"/>
<port type="input" prefix="a" size="8"/>
<port type="input" prefix="b" size="8"/>
<port type="output" prefix="out" size="16"/>
</circuit_model>
This example shows:
- A 8-bit multiplier which is defined in a Verilog netlist ``dsp.v`` and a SPICE netlist ``dsp.sp``
.. _circuit_model_multi_mode_mult8x8_example:
Multi-mode Multiplier
`````````````````````
.. figure:: ./figures/multi_mode_mult8x8_circuit_model.svg
:scale: 200%
:alt: An example of a 8-bit multiplier which can operating in two modes: (1) dual 4-bit multipliers; and (2) 8-bit multiplier
An example of a 8-bit multiplier which can operating in two modes: (1) dual 4-bit multipliers; and (2) 8-bit multiplier
The code describing the multiplier is:
.. code-block:: xml
<circuit_model type="hard_logic" name="frac_mult8x8" prefix="frac_mult8x8" spice_netlist="dsp.sp" verilog_netlist="dsp.v">
<design_technology type="cmos"/>
<input_buffer exist="true" circuit_model_name="inv1x"/>
<output_buffer exist="true" circuit_model_name="inv1x"/>
<port type="input" prefix="a" size="8"/>
<port type="input" prefix="b" size="8"/>
<port type="output" prefix="out" size="16"/>
<port type="sram" prefix="mode" size="1" mode_select="true" circuit_model_name="CCFF" default_value="0"/>
</circuit_model>
This example shows:
- A multi-mode 8-bit multiplier which is defined in a Verilog netlist ``dsp.v`` and a SPICE netlist ``dsp.sp``
- The multi-mode multiplier can operating in two modes: (1) dual 4-bit multipliers; and (2) 8-bit multiplier
- The mode-selection bit will be generated by a configurable memory outside the flip-flop, which will be implemented by a circuit model ``CCFF`` defined by users (see an example in :ref:`circuit_model_ccff_example`).
.. _circuit_model_single_mode_dpram_example:
Dual Port Block RAM
```````````````````
.. figure:: ./figures/single_mode_dpram128x8_memory_circuit_model.svg
:scale: 150%
:alt: An example of a dual port block RAM with 128 addresses and 8-bit data width.
An example of a dual port block RAM with 128 addresses and 8-bit data width.
The code describing this block RAM is:
.. code-block:: xml
<circuit_model type="hard_logic" name="dpram_128x8" prefix="dpram_128x8" spice_netlist="dpram.sp" verilog_netlist="dpram.v">
<design_technology type="cmos"/>
<input_buffer exist="true" circuit_model_name="inv1x"/>
<output_buffer exist="true" circuit_model_name="inv1x"/>
<port type="input" prefix="waddr" size="7"/>
<port type="input" prefix="raddr" size="7"/>
<port type="input" prefix="data_in" size="8"/>
<port type="input" prefix="wen" size="1"/>
<port type="input" prefix="ren" size="1"/>
<port type="output" prefix="data_out" size="8"/>
<port type="clock" prefix="clock" size="1" is_global="true" default_val="0"/>
</circuit_model>
This example shows:
- A 128x8 dual port RAM which is defined in a Verilog netlist ``dpram.v`` and a SPICE netlist ``dpram.sp``
- The clock port of the RAM is controlled by a global signal (see details about global signal definition in :ref:`annotate_vpr_arch_physical_tile_annotation`).
.. _circuit_model_multi_mode_dpram_example:
Multi-mode Dual Port Block RAM
``````````````````````````````
.. figure:: ./figures/multi_mode_dpram128x8_memory_circuit_model.svg
:scale: 150%
:alt: An example of a multi-mode dual port block RAM with 128 addresses and 8-bit data width.
An example of a dual port block RAM which can operate in two modes: 128x8 and 256x4.
The code describing this block RAM is:
.. code-block:: xml
<circuit_model type="hard_logic" name="frac_dpram_128x8" prefix="frac_dpram_128x8" spice_netlist="frac_dpram.sp" verilog_netlist="frac_dpram.v">
<design_technology type="cmos"/>
<input_buffer exist="true" circuit_model_name="inv1x"/>
<output_buffer exist="true" circuit_model_name="inv1x"/>
<port type="input" prefix="waddr" size="8"/>
<port type="input" prefix="raddr" size="8"/>
<port type="input" prefix="data_in" size="8"/>
<port type="input" prefix="wen" size="1"/>
<port type="input" prefix="ren" size="1"/>
<port type="output" prefix="data_out" size="8"/>
<port type="clock" prefix="clock" size="1" is_global="true" default_val="0"/>
<port type="sram" prefix="mode" size="1" mode_select="true" circuit_model_name="CCFF" default_value="0"/>
</circuit_model>
This example shows:
- A fracturable dual port RAM which is defined in a Verilog netlist ``frac_dpram.v`` and a SPICE netlist ``frac_dpram.sp``
- The dual port RAM can operate in two modes: (1) 128 addresses with 8-bit data width; (2) 256 addresses with 4-bit data width
- The clock port of the RAM is controlled by a global signal (see details about global signal definition in :ref:`annotate_vpr_arch_physical_tile_annotation`).
- The mode-selection bit will be generated by a configurable memory outside the flip-flop, which will be implemented by a circuit model ``CCFF`` defined by users (see an example in :ref:`circuit_model_ccff_example`).
Routing Wire Segments
~~~~~~~~~~~~~~~~~~~~~
@ -1255,6 +1457,8 @@ This example shows
I/O pads
~~~~~~~~
.. note:: OpenFPGA does not auto-generate any netlist for I/O cells. Users should define the HDL modeling in external netlists and ensure consistency to physical designs.
Template
````````

View File

@ -0,0 +1,76 @@
<?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 xmlns:dc="http://purl.org/dc/elements/1.1/" version="1.1" xmlns:xl="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" viewBox="155.08 312.04775 148.51908 123.62449" width="148.51908" height="123.62449">
<defs>
<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="13" 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="-1256.384" 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>
<marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="FilledArrow_Marker" stroke-linejoin="miter" stroke-miterlimit="10" viewBox="-1 -2 5 4" markerWidth="5" markerHeight="4" color="black">
<g>
<path d="M 2.4 0 L 0 -.9 L 0 .9 Z" fill="currentColor" stroke="currentColor" stroke-width="1"/>
</g>
</marker>
</defs>
<metadata> Produced by OmniGraffle 7.18.5\n2021-05-24 20:57:16 +0000</metadata>
<g id="1-bit_full_adder" stroke-opacity="1" fill="none" stroke-dasharray="none" fill-opacity="1" stroke="none">
<title>1-bit full adder</title>
<g id="1-bit_full_adder_Layer_1">
<title>Layer 1</title>
<g id="Graphic_35772">
<rect x="192.24" y="344.52" width="57.6" height="58.68" fill="#ffffc0"/>
<rect x="192.24" y="344.52" width="57.6" height="58.68" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
<text transform="translate(197.24 366.06263)" fill="black">
<tspan font-family="Times New Roman" font-size="14" font-style="italic" font-weight="400" fill="black" x="7.4689445" y="12">adder</tspan>
</text>
</g>
<g id="Graphic_35773"/>
<g id="Graphic_35774">
<text transform="translate(211.44037 312.04775)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-style="italic" font-weight="400" fill="black" x="1.6587038" y="12">cin</tspan>
</text>
</g>
<g id="Graphic_35775">
<text transform="translate(155.08 351.9)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-style="italic" font-weight="400" fill="black" x="2.4363742" y="12">a</tspan>
</text>
</g>
<g id="Graphic_35776">
<text transform="translate(155.08 375.26)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-style="italic" font-weight="400" fill="black" x="2.4363742" y="12">b</tspan>
</text>
</g>
<g id="Line_35778">
<line x1="166.45275" y1="359.73463" x2="184.14042" y2="359.91665" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35779">
<line x1="166.45275" y1="382.93925" x2="184.14117" y2="382.63795" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35780">
<line x1="250.84" y1="373.86" x2="257.94" y2="373.86" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_35786">
<text transform="translate(266.04 366.08387)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-style="italic" font-weight="400" fill="black" x="0" y="12">sumout</tspan>
</text>
</g>
<g id="Line_35787">
<line x1="221.04" y1="327.6" x2="221.04" y2="335.42" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_35788">
<text transform="translate(206.52018 420.12)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-style="italic" font-weight="400" fill="black" x="3.3288927" y="12">cout</tspan>
</text>
</g>
<g id="Line_35789">
<line x1="221.04" y1="404.2" x2="221.04" y2="412.02" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

@ -0,0 +1,342 @@
<?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 xmlns:dc="http://purl.org/dc/elements/1.1/" version="1.1" xmlns:xl="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" viewBox="372.172 88.78 661.168 257.155" width="661.168" height="257.155">
<defs>
<font-face font-family="Times New Roman" font-size="13" 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>
<marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="FilledArrow_Marker" stroke-linejoin="miter" stroke-miterlimit="10" viewBox="-1 -2 5 4" markerWidth="5" markerHeight="4" color="black">
<g>
<path d="M 2.4 0 L 0 -.9 L 0 .9 Z" fill="currentColor" stroke="currentColor" stroke-width="1"/>
</g>
</marker>
<marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="FilledArrow_Marker_2" stroke-linejoin="miter" stroke-miterlimit="10" viewBox="-1 -4 10 8" markerWidth="10" markerHeight="8" color="black">
<g>
<path d="M 8 0 L 0 -3 L 0 3 Z" fill="currentColor" stroke="currentColor" stroke-width="1"/>
</g>
</marker>
<font-face font-family="Times New Roman" font-size="12" 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="Helvetica Neue" font-size="16" panose-1="2 0 8 3 0 0 0 9 0 4" units-per-em="1000" underline-position="-100" underline-thickness="50" slope="0" x-height="517" cap-height="714" ascent="975.0061" descent="-216.99524" font-weight="700">
<font-face-src>
<font-face-name name="HelveticaNeue-Bold"/>
</font-face-src>
</font-face>
<font-face font-family="STIXGeneral" font-size="13" units-per-em="1000" underline-position="-75" underline-thickness="50" slope="0" x-height="450" cap-height="662" ascent="1055.0021" descent="-455.0009" font-weight="400">
<font-face-src>
<font-face-name name="STIXGeneral-Regular"/>
</font-face-src>
</font-face>
</defs>
<metadata> Produced by OmniGraffle 7.18.5\n2021-05-24 20:15:49 +0000</metadata>
<g id="multi_mode_dual_port_bram_1" stroke-opacity="1" fill="none" stroke-dasharray="none" fill-opacity="1" stroke="none">
<title>multi_mode_dual_port_bram 1</title>
<g id="multi_mode_dual_port_bram_1_Layer_1">
<title>Layer 1</title>
<g id="Graphic_80">
<rect x="372.672" y="153.9355" width="309.24" height="120.61165" fill="white"/>
<rect x="372.672" y="153.9355" width="309.24" height="120.61165" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Graphic_79">
<rect x="723.6" y="89.28" width="309.24" height="128.37183" fill="white"/>
<rect x="723.6" y="89.28" width="309.24" height="128.37183" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Graphic_52">
<rect x="723.6" y="217.06317" width="309.24" height="128.37183" fill="white"/>
<rect x="723.6" y="217.06317" width="309.24" height="128.37183" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Graphic_2">
<rect x="431.28" y="178.56" width="180.36" height="90.36" fill="#ffffc0"/>
<rect x="431.28" y="178.56" width="180.36" height="90.36" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_3">
<path d="M 431.28 248.6386 L 443.16 253.9786 L 431.28 259.3186 Z" fill="#ccc"/>
<path d="M 431.28 248.6386 L 443.16 253.9786 L 431.28 259.3186 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Graphic_4">
<text transform="translate(443.16 246.20248)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-weight="400" fill="black" x="2.1677246" y="12">clock</tspan>
</text>
</g>
<g id="Graphic_6">
<text transform="translate(554.04 186.389)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-weight="400" fill="black" x="0" y="12">raddr[7:0]</tspan>
</text>
</g>
<g id="Graphic_7">
<text transform="translate(433.44 185.04)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-weight="400" fill="black" x="0" y="12">waddr[7:0]</tspan>
</text>
</g>
<g id="Graphic_8">
<text transform="translate(433.44 203.04)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-weight="400" fill="black" x="5.414551" y="12">wen</tspan>
</text>
</g>
<g id="Graphic_9">
<text transform="translate(581.9575 201.94124)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-weight="400" fill="black" x="5.414551" y="12">ren</tspan>
</text>
</g>
<g id="Graphic_10">
<text transform="translate(433.44 221.04)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-weight="400" fill="black" x=".17456055" y="12">data_in[7:0]</tspan>
</text>
</g>
<g id="Graphic_11">
<text transform="translate(537.7457 218.84248)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-weight="400" fill="black" x=".803154" y="12">data_out[7:0]</tspan>
</text>
</g>
<g id="Line_12">
<line x1="384.84" y1="192.96" x2="421.74" y2="193.01682" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_13">
<line x1="384.84" y1="209.21736" x2="419.94" y2="209.27141" marker-end="url(#FilledArrow_Marker_2)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Line_14">
<line x1="384.84" y1="228.31612" x2="421.74" y2="228.37295" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_15">
<line x1="384.84" y1="253.4786" x2="419.94" y2="253.53265" marker-end="url(#FilledArrow_Marker_2)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Line_16">
<line x1="613.08" y1="226.76248" x2="649.98" y2="226.8193" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_17">
<line x1="658.08" y1="209.93054" x2="622.98" y2="209.87648" marker-end="url(#FilledArrow_Marker_2)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Line_18">
<line x1="658.08" y1="193.0293" x2="621.18" y2="192.97247" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_19">
<line x1="406.25" y1="188.54" x2="399.8125" y2="198.1131" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_24">
<line x1="406.25" y1="222.47592" x2="399.8125" y2="232.04903" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_25">
<line x1="645.4375" y1="188.02956" x2="639" y2="197.60268" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_26">
<line x1="636.4375" y1="221.83204" x2="630" y2="231.40516" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_27">
<text transform="translate(571.8075 242.64)" fill="black">
<tspan font-family="Times New Roman" font-size="12" font-weight="400" fill="black" x="5.4590435" y="11">mode</tspan>
</text>
</g>
<g id="Line_29">
<line x1="656.64" y1="249.46418" x2="621.54" y2="249.41012" marker-end="url(#FilledArrow_Marker_2)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Graphic_51">
<rect x="782.208" y="119.715" width="180.36" height="90.36" fill="#c0ffff"/>
<rect x="782.208" y="119.715" width="180.36" height="90.36" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_50">
<path d="M 782.208 189.7936 L 794.088 195.1336 L 782.208 200.4736 Z" fill="#ccc"/>
<path d="M 782.208 189.7936 L 794.088 195.1336 L 782.208 200.4736 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Graphic_49">
<text transform="translate(794.088 187.35749)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-weight="400" fill="black" x="2.1677246" y="12">clock</tspan>
</text>
</g>
<g id="Graphic_48">
<text transform="translate(904.968 127.544)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-weight="400" fill="black" x="0" y="12">raddr[6:0]</tspan>
</text>
</g>
<g id="Graphic_47">
<text transform="translate(784.368 126.195)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-weight="400" fill="black" x="0" y="12">waddr[6:0]</tspan>
</text>
</g>
<g id="Graphic_46">
<text transform="translate(784.368 144.195)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-weight="400" fill="black" x="5.414551" y="12">wen</tspan>
</text>
</g>
<g id="Graphic_45">
<text transform="translate(932.8855 143.09625)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-weight="400" fill="black" x="5.414551" y="12">ren</tspan>
</text>
</g>
<g id="Graphic_44">
<text transform="translate(784.368 162.195)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-weight="400" fill="black" x=".17456055" y="12">data_in[7:0]</tspan>
</text>
</g>
<g id="Graphic_43">
<text transform="translate(888.6737 159.99749)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-weight="400" fill="black" x=".803154" y="12">data_out[7:0]</tspan>
</text>
</g>
<g id="Line_42">
<line x1="735.768" y1="134.115" x2="772.668" y2="134.17183" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_41">
<line x1="735.768" y1="150.37237" x2="770.868" y2="150.42642" marker-end="url(#FilledArrow_Marker_2)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Line_40">
<line x1="735.768" y1="169.47113" x2="772.668" y2="169.52796" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_39">
<line x1="735.768" y1="194.6336" x2="770.868" y2="194.68766" marker-end="url(#FilledArrow_Marker_2)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Line_38">
<line x1="964.008" y1="167.91749" x2="1000.908" y2="167.97431" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_37">
<line x1="1009.008" y1="151.08555" x2="973.908" y2="151.0315" marker-end="url(#FilledArrow_Marker_2)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Line_36">
<line x1="1009.008" y1="134.1843" x2="972.108" y2="134.12748" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_35">
<line x1="757.178" y1="129.695" x2="750.7405" y2="139.26812" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_34">
<line x1="757.178" y1="163.63093" x2="750.7405" y2="173.20404" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_33">
<line x1="996.3655" y1="129.18457" x2="989.928" y2="138.75769" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_32">
<line x1="987.3655" y1="162.98705" x2="980.928" y2="172.56017" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_31">
<text transform="translate(922.7355 183.795)" fill="black">
<tspan font-family="Times New Roman" font-size="12" font-weight="400" fill="black" x="5.4590435" y="11">mode</tspan>
</text>
</g>
<g id="Line_30">
<line x1="1007.568" y1="190.6192" x2="972.468" y2="190.56513" marker-end="url(#FilledArrow_Marker_2)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Graphic_53">
<text transform="translate(1010.048 178.44562)" fill="black">
<tspan font-family="Helvetica Neue" font-size="16" font-weight="700" fill="black" x="6394885e-19" y="16">1</tspan>
</text>
</g>
<g id="Graphic_75">
<rect x="782.208" y="245.355" width="180.36" height="90.36" fill="#c0ffc0"/>
<rect x="782.208" y="245.355" width="180.36" height="90.36" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_74">
<path d="M 782.208 315.4336 L 794.088 320.7736 L 782.208 326.1136 Z" fill="#ccc"/>
<path d="M 782.208 315.4336 L 794.088 320.7736 L 782.208 326.1136 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Graphic_73">
<text transform="translate(794.088 312.9975)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-weight="400" fill="black" x="2.1677246" y="12">clock</tspan>
</text>
</g>
<g id="Graphic_72">
<text transform="translate(904.968 253.184)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-weight="400" fill="black" x="0" y="12">raddr[7:0]</tspan>
</text>
</g>
<g id="Graphic_71">
<text transform="translate(784.368 251.835)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-weight="400" fill="black" x="0" y="12">waddr[7:0]</tspan>
</text>
</g>
<g id="Graphic_70">
<text transform="translate(784.368 269.835)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-weight="400" fill="black" x="5.414551" y="12">wen</tspan>
</text>
</g>
<g id="Graphic_69">
<text transform="translate(932.8855 268.73624)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-weight="400" fill="black" x="5.414551" y="12">ren</tspan>
</text>
</g>
<g id="Graphic_68">
<text transform="translate(784.368 287.835)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-weight="400" fill="black" x=".17456055" y="12">data_in[3:0]</tspan>
</text>
</g>
<g id="Graphic_67">
<text transform="translate(888.6737 285.6375)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-weight="400" fill="black" x=".803154" y="12">data_out[3:0]</tspan>
</text>
</g>
<g id="Line_66">
<line x1="735.768" y1="259.755" x2="772.668" y2="259.81183" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_65">
<line x1="735.768" y1="276.01237" x2="770.868" y2="276.06642" marker-end="url(#FilledArrow_Marker_2)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Line_64">
<line x1="735.768" y1="295.11113" x2="772.668" y2="295.16795" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_63">
<line x1="735.768" y1="320.2736" x2="770.868" y2="320.32766" marker-end="url(#FilledArrow_Marker_2)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Line_62">
<line x1="964.008" y1="293.5575" x2="1000.908" y2="293.6143" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_61">
<line x1="1009.008" y1="276.72554" x2="973.908" y2="276.6715" marker-end="url(#FilledArrow_Marker_2)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Line_60">
<line x1="1009.008" y1="259.8243" x2="972.108" y2="259.76748" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_59">
<line x1="757.178" y1="255.335" x2="750.7405" y2="264.90812" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_58">
<line x1="757.178" y1="289.27093" x2="750.7405" y2="298.84404" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_57">
<line x1="996.3655" y1="254.82457" x2="989.928" y2="264.39768" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_56">
<line x1="987.3655" y1="288.62705" x2="980.928" y2="298.20016" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_55">
<text transform="translate(922.7355 309.435)" fill="black">
<tspan font-family="Times New Roman" font-size="12" font-weight="400" fill="black" x="5.4590435" y="11">mode</tspan>
</text>
</g>
<g id="Line_54">
<line x1="1007.568" y1="316.2592" x2="972.468" y2="316.20513" marker-end="url(#FilledArrow_Marker_2)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Graphic_76">
<text transform="translate(1010.048 306.95783)" fill="black">
<tspan font-family="Helvetica Neue" font-size="16" font-weight="700" fill="black" x="6394885e-19" y="16">0</tspan>
</text>
</g>
<g id="Graphic_77">
<text transform="translate(727.128 219.7961)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-weight="400" fill="black" x="0" y="14">Operating mode 2: Dual port 256</tspan>
<tspan font-family="STIXGeneral" font-size="13" font-weight="400" fill="black" y="14">x</tspan>
<tspan font-family="Times New Roman" font-size="13" font-weight="400" fill="black" y="14">4 RAM</tspan>
</text>
</g>
<g id="Graphic_78">
<text transform="translate(727.128 95.31501)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-weight="400" fill="black" x="0" y="12">Operating mode 1: Dual port 128x8 RAM</tspan>
</text>
</g>
<g id="Graphic_81">
<text transform="translate(376.2 153.9355)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-weight="400" fill="black" x="0" y="12">Schematic: Multi-mode dual port 128x8/256x4 RAM</tspan>
</text>
</g>
<g id="Graphic_82">
<path d="M 689.5061 176.1904 L 696.6112 183.2955 L 708.2277 171.679 L 711.78025 175.23154 L 712.4533 160.34827 L 697.57005 161.02135 L 701.1226 164.5739 Z" fill="#ff4040"/>
<path d="M 689.5061 176.1904 L 696.6112 183.2955 L 708.2277 171.679 L 711.78025 175.23154 L 712.4533 160.34827 L 697.57005 161.02135 L 701.1226 164.5739 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Graphic_83">
<path d="M 698.3752 233.85175 L 691.2701 240.95684 L 702.8866 252.57335 L 699.33405 256.1259 L 714.2173 256.79898 L 713.54425 241.9157 L 709.9917 245.46825 Z" fill="#ff4040"/>
<path d="M 698.3752 233.85175 L 691.2701 240.95684 L 702.8866 252.57335 L 699.33405 256.1259 L 714.2173 256.79898 L 713.54425 241.9157 L 709.9917 245.46825 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 21 KiB

View File

@ -0,0 +1,152 @@
<?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 xmlns:dc="http://purl.org/dc/elements/1.1/" version="1.1" xmlns:xl="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" viewBox="249.96086 276.12 209.06514 170.76" width="209.06514" height="170.76">
<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="12" 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>
</defs>
<metadata> Produced by OmniGraffle 7.18.5\n2021-05-24 18:52:28 +0000</metadata>
<g id="multi_mode_ff" stroke-opacity="1" fill="none" stroke-dasharray="none" fill-opacity="1" stroke="none">
<title>multi_mode_ff</title>
<g id="multi_mode_ff_Layer_1">
<title>Layer 1</title>
<g id="Graphic_34">
<rect x="295.92" y="279.72" width="151.39959" height="140.4" fill="#ffffc0"/>
<rect x="295.92" y="279.72" width="151.39959" height="140.4" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_12">
<rect x="367.0598" y="298.8" width="67.44001" height="58.68" fill="white"/>
<rect x="367.0598" y="298.8" width="67.44001" height="58.68" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
<text transform="translate(372.0598 320.34263)" fill="black">
<tspan font-family="Times New Roman" font-size="14" font-weight="400" fill="black" x="20.933872" y="12">FF</tspan>
</text>
</g>
<g id="Graphic_11">
<text transform="translate(368.12027 314.24883)" 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_10">
<text transform="translate(375.2564 338.94)" 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_9">
<line x1="365.9288" y1="319.13116" x2="295.5" y2="319.13116" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_8">
<line x1="365.9288" y1="343.63115" x2="295.92" y2="343.75" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_7">
<line x1="447.3196" y1="314.44" x2="435.6308" y2="314.45366" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_6">
<path d="M 367.0598 340.05115 L 374.6198 344.13115 L 367.0598 348.21115 Z" fill="#ccc"/>
<path d="M 367.0598 340.05115 L 374.6198 344.13115 L 367.0598 348.21115 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Graphic_5">
<text transform="translate(424.8 309.74883)" 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_13">
<text transform="translate(393.893 347.09767)" fill="black">
<tspan font-family="Times New Roman" font-size="9" font-weight="400" fill="black" x="0" y="8">RST</tspan>
</text>
</g>
<g id="Line_16">
<line x1="401.64593" y1="367.8623" x2="401.64593" y2="357.48" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Group_21">
<g id="Graphic_17">
<path d="M 325.0602 378 L 340.04 385.68 L 325.0602 393.36 Z" fill="white"/>
<path d="M 325.0602 378 L 340.04 385.68 L 325.0602 393.36 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_18">
<circle cx="342.74" cy="385.3" r="2.70000442162365" fill="white"/>
<circle cx="342.74" cy="385.3" r="2.70000442162365" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
</g>
<g id="Graphic_20">
<path d="M 357.84 413.64 L 357.84 375.48 L 368.2223 383.112 L 368.2223 406.008 Z" fill="white"/>
<path d="M 357.84 413.64 L 357.84 375.48 L 368.2223 383.112 L 368.2223 406.008 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_22">
<line x1="310.1" y1="385.39" x2="324.06028" y2="385.57033" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_23">
<line x1="346.43835" y1="385.4102" x2="357.84" y2="385.75" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_24">
<line x1="310" y1="402.25" x2="357.84" y2="402.25" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_25">
<line x1="310.1" y1="385.39" x2="310" y2="402.25" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_26">
<line x1="295.92" y1="394.06" x2="309.88028" y2="394.2403" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_27">
<path d="M 369.2223 394.59046 L 401.64593 394.75 L 401.87445 368.25" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Group_33">
<g id="Graphic_28">
<rect x="357.84" y="435.18766" width="10.382324" height="10.382324" fill="#ccc"/>
<rect x="357.84" y="435.18766" width="10.382324" height="10.382324" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_29">
<line x1="368.2223" y1="446.38" x2="357.84" y2="435.3175" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Line_30">
<line x1="357.18676" y1="445.525" x2="368.2223" y2="434.88" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
</g>
<g id="Line_32">
<line x1="363.03115" y1="410.824" x2="363.03115" y2="434.18766" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_35">
<text transform="translate(300.92 281.12)" fill="black">
<tspan font-family="Times New Roman" font-size="14" font-weight="400" fill="black" x="0" y="12">Multi-mode FF</tspan>
</text>
</g>
<g id="Graphic_36">
<text transform="translate(450.36 305.6214)" fill="black">
<tspan font-family="Times New Roman" font-size="12" font-weight="400" fill="black" x="0" y="11">Q</tspan>
</text>
</g>
<g id="Graphic_37">
<text transform="translate(284.6425 310.1214)" fill="black">
<tspan font-family="Times New Roman" font-size="12" font-weight="400" fill="black" x="0" y="11">D</tspan>
</text>
</g>
<g id="Graphic_38">
<text transform="translate(366.59038 420.3702)" fill="black">
<tspan font-family="Times New Roman" font-size="12" font-weight="400" fill="black" x="0" y="11">MODE</tspan>
</text>
</g>
<g id="Graphic_39">
<text transform="translate(269.30852 336.87627)" fill="black">
<tspan font-family="Times New Roman" font-size="12" font-weight="400" fill="black" x="0" y="11">CLK</tspan>
</text>
</g>
<g id="Graphic_40">
<text transform="translate(249.96086 387.3051)" fill="black">
<tspan font-family="Times New Roman" font-size="12" font-weight="400" fill="black" x="0" y="11">RST_OP</tspan>
</text>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 8.7 KiB

View File

@ -0,0 +1,249 @@
<?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 xmlns:dc="http://purl.org/dc/elements/1.1/" version="1.1" xmlns:xl="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" viewBox="264.73112 332.86 459.72887 267.47224" width="459.72887" height="267.47224">
<defs>
<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="13" 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="-1256.384" 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>
<marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="FilledArrow_Marker" stroke-linejoin="miter" stroke-miterlimit="10" viewBox="-1 -2 5 4" markerWidth="5" markerHeight="4" color="black">
<g>
<path d="M 2.4 0 L 0 -.9 L 0 .9 Z" fill="currentColor" stroke="currentColor" stroke-width="1"/>
</g>
</marker>
<font-face font-family="Times New Roman" font-size="13" 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>
</defs>
<metadata> Produced by OmniGraffle 7.18.5\n2021-05-24 21:09:05 +0000</metadata>
<g id="multi_mode_mult_8x8" stroke-opacity="1" fill="none" stroke-dasharray="none" fill-opacity="1" stroke="none">
<title>multi_mode_mult_8x8</title>
<g id="multi_mode_mult_8x8_Layer_1">
<title>Layer 1</title>
<g id="Graphic_38">
<rect x="265.23112" y="415.98" width="211.68" height="116.08224" fill="white"/>
<rect x="265.23112" y="415.98" width="211.68" height="116.08224" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Graphic_35">
<rect x="512.28" y="333.36" width="211.68" height="149.04" fill="white"/>
<rect x="512.28" y="333.36" width="211.68" height="149.04" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Graphic_13">
<rect x="336.2311" y="441.36" width="57.6" height="58.68" fill="#ffffc0"/>
<rect x="336.2311" y="441.36" width="57.6" height="58.68" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
<text transform="translate(341.2311 455.10526)" fill="black">
<tspan font-family="Times New Roman" font-size="14" font-style="italic" font-weight="400" fill="black" x="5.2677727" y="12">MULT</tspan>
<tspan font-family="Times New Roman" font-size="14" font-style="italic" font-weight="400" fill="black" x="13.693066" y="27.594727">8x8</tspan>
</text>
</g>
<g id="Graphic_10">
<text transform="translate(265.23112 449.24)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-style="italic" font-weight="400" fill="black" x="5.632742" y="12">a[7:0]</tspan>
</text>
</g>
<g id="Graphic_9">
<text transform="translate(268.29112 472.1)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-style="italic" font-weight="400" fill="black" x="2.5727406" y="12">b[7:0]</tspan>
</text>
</g>
<g id="Line_8">
<line x1="310.44387" y1="456.93384" x2="328.13117" y2="456.8695" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_7">
<line x1="307.38387" y1="479.6596" x2="328.1316" y2="479.4297" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_6">
<line x1="394.8311" y1="470.7" x2="411.51837" y2="470.7" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_5">
<text transform="translate(419.61837 462.92387)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-style="italic" font-weight="400" fill="black" x="0" y="12">out[15:0]</tspan>
</text>
</g>
<g id="Line_14">
<line x1="322.39087" y1="451.17" x2="316.7111" y2="461.86224" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Line_15">
<line x1="322.39087" y1="474.53" x2="316.7111" y2="485.22224" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Graphic_24">
<rect x="583.28" y="354.6" width="57.6" height="58.68" fill="#c0ffff"/>
<rect x="583.28" y="354.6" width="57.6" height="58.68" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
<text transform="translate(588.28 360.5479)" fill="black">
<tspan font-family="Times New Roman" font-size="14" font-style="italic" font-weight="400" fill="black" x="5.2677727" y="12">MULT</tspan>
<tspan font-family="Times New Roman" font-size="14" font-style="italic" font-weight="400" fill="black" x="13.693066" y="27.594727">4x4</tspan>
<tspan font-family="Times New Roman" font-size="14" font-style="italic" font-weight="400" fill="black" x="14.851757" y="43.189453">[0]</tspan>
</text>
</g>
<g id="Graphic_23">
<text transform="translate(512.28 362.48)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-style="italic" font-weight="400" fill="black" x="5.632742" y="12">a[7:4]</tspan>
</text>
</g>
<g id="Graphic_22">
<text transform="translate(515.34 385.34)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-style="italic" font-weight="400" fill="black" x="2.5727406" y="12">b[7:4]</tspan>
</text>
</g>
<g id="Line_21">
<line x1="557.49274" y1="370.17385" x2="575.18004" y2="370.10948" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_20">
<line x1="554.43274" y1="392.89958" x2="575.1805" y2="392.66973" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_19">
<line x1="641.88" y1="383.94" x2="658.5672" y2="383.94" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_18">
<text transform="translate(666.6672 376.16387)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-style="italic" font-weight="400" fill="black" x="0" y="12">out[15:8]</tspan>
</text>
</g>
<g id="Line_17">
<line x1="569.43975" y1="364.41" x2="563.76" y2="375.10224" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Line_16">
<line x1="569.43975" y1="387.77" x2="563.76" y2="398.46224" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Graphic_33">
<rect x="583.28" y="418.96774" width="57.6" height="58.68" fill="#c0ffff"/>
<rect x="583.28" y="418.96774" width="57.6" height="58.68" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
<text transform="translate(588.28 424.91565)" fill="black">
<tspan font-family="Times New Roman" font-size="14" font-style="italic" font-weight="400" fill="black" x="5.2677727" y="12">MULT</tspan>
<tspan font-family="Times New Roman" font-size="14" font-style="italic" font-weight="400" fill="black" x="13.693066" y="27.594727">4x4</tspan>
<tspan font-family="Times New Roman" font-size="14" font-style="italic" font-weight="400" fill="black" x="14.851757" y="43.189453">[1]</tspan>
</text>
</g>
<g id="Graphic_32">
<text transform="translate(512.28 426.84774)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-style="italic" font-weight="400" fill="black" x="5.632742" y="12">a[3:0]</tspan>
</text>
</g>
<g id="Graphic_31">
<text transform="translate(515.34 449.70774)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-style="italic" font-weight="400" fill="black" x="2.5727406" y="12">b[3:0]</tspan>
</text>
</g>
<g id="Line_30">
<line x1="557.49274" y1="434.5416" x2="575.18004" y2="434.47723" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_29">
<line x1="554.43274" y1="457.26733" x2="575.1805" y2="457.0375" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_28">
<line x1="641.88" y1="448.30774" x2="661.8172" y2="448.30774" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_27">
<text transform="translate(669.9172 440.5316)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-style="italic" font-weight="400" fill="black" x="0" y="12">out[7:0]</tspan>
</text>
</g>
<g id="Line_26">
<line x1="569.43975" y1="428.77774" x2="563.76" y2="439.47" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Line_25">
<line x1="569.43975" y1="452.13774" x2="563.76" y2="462.83" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Graphic_34">
<text transform="translate(515.34 335.52)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-weight="400" fill="black" x="0" y="12">Operating mode 1: Dual 4x4 multiplier</tspan>
</text>
</g>
<g id="Line_36">
<line x1="365.0311" y1="516.51" x2="365.0311" y2="509.14" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_37">
<text transform="translate(342.42474 516.51)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-style="italic" font-weight="400" fill="black" x="8.527273" y="12">mode</tspan>
</text>
</g>
<g id="Graphic_39">
<text transform="translate(268.29112 415.98)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-weight="400" fill="black" x="0" y="12">Schematic: multi-mode 8x8 multiplier</tspan>
</text>
</g>
<g id="Graphic_59">
<rect x="512.28" y="490.32" width="211.68" height="109.51224" fill="white"/>
<rect x="512.28" y="490.32" width="211.68" height="109.51224" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Graphic_58">
<rect x="583.28" y="511.56" width="57.6" height="58.68" fill="#c0ffc0"/>
<rect x="583.28" y="511.56" width="57.6" height="58.68" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
<text transform="translate(588.28 525.30526)" fill="black">
<tspan font-family="Times New Roman" font-size="14" font-style="italic" font-weight="400" fill="black" x="5.2677727" y="12">MULT</tspan>
<tspan font-family="Times New Roman" font-size="14" font-style="italic" font-weight="400" fill="black" x="13.693066" y="27.594727">8x8</tspan>
</text>
</g>
<g id="Graphic_57">
<text transform="translate(512.28 519.44)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-style="italic" font-weight="400" fill="black" x="5.632742" y="12">a[7:0]</tspan>
</text>
</g>
<g id="Graphic_56">
<text transform="translate(515.34 542.3)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-style="italic" font-weight="400" fill="black" x="2.5727406" y="12">b[7:0]</tspan>
</text>
</g>
<g id="Line_55">
<line x1="557.49274" y1="527.13384" x2="575.18004" y2="527.0695" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_54">
<line x1="554.43274" y1="549.8596" x2="575.1805" y2="549.6297" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_53">
<line x1="641.88" y1="540.9" x2="658.5672" y2="540.9" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_52">
<text transform="translate(666.6672 533.12386)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-style="italic" font-weight="400" fill="black" x="0" y="12">out[15:0]</tspan>
</text>
</g>
<g id="Line_51">
<line x1="569.43975" y1="521.37" x2="563.76" y2="532.06223" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Line_50">
<line x1="569.43975" y1="544.73" x2="563.76" y2="555.42223" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Graphic_40">
<text transform="translate(529.6 492.48)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-weight="400" fill="black" x="0" y="12">Operating mode 2: 8x8 multiplier</tspan>
</text>
</g>
<g id="Line_61">
<line x1="614.85374" y1="584.28" x2="614.8337" y2="578.33994" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_60">
<text transform="translate(586.08 584.28)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-style="italic" font-weight="400" fill="black" x="2.7555656" y="12">mode=0</tspan>
</text>
</g>
<g id="Graphic_63">
<path d="M 480.46366 439.4672 L 487.56876 446.5723 L 499.18527 434.9558 L 502.7378 438.50836 L 503.4109 423.6251 L 488.5276 424.29817 L 492.08017 427.8507 Z" fill="#ff4040"/>
<path d="M 480.46366 439.4672 L 487.56876 446.5723 L 499.18527 434.9558 L 502.7378 438.50836 L 503.4109 423.6251 L 488.5276 424.29817 L 492.08017 427.8507 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Graphic_62">
<path d="M 489.33276 497.12856 L 482.22766 504.23366 L 493.84417 515.85017 L 490.2916 519.4027 L 505.1749 520.0758 L 504.5018 505.1925 L 500.94927 508.7451 Z" fill="#ff4040"/>
<path d="M 489.33276 497.12856 L 482.22766 504.23366 L 493.84417 515.85017 L 490.2916 519.4027 L 505.1749 520.0758 L 504.5018 505.1925 L 500.94927 508.7451 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Line_65">
<line x1="656.3763" y1="406.80216" x2="648.9099" y2="405.8134" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_64">
<text transform="translate(656.3763 402.84)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-style="italic" font-weight="400" fill="black" x="2.7555656" y="12">mode=1</tspan>
</text>
</g>
<g id="Line_66">
<line x1="663.1438" y1="418.39224" x2="648.5182" y2="423.55417" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -0,0 +1,104 @@
<?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 xmlns:dc="http://purl.org/dc/elements/1.1/" version="1.1" xmlns:xl="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" viewBox="383.84 177.56 275.24 92.36" width="275.24" height="92.36">
<defs>
<font-face font-family="Times New Roman" font-size="13" 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>
<marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="FilledArrow_Marker" stroke-linejoin="miter" stroke-miterlimit="10" viewBox="-1 -2 5 4" markerWidth="5" markerHeight="4" color="black">
<g>
<path d="M 2.4 0 L 0 -.9 L 0 .9 Z" fill="currentColor" stroke="currentColor" stroke-width="1"/>
</g>
</marker>
<marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="FilledArrow_Marker_2" stroke-linejoin="miter" stroke-miterlimit="10" viewBox="-1 -4 10 8" markerWidth="10" markerHeight="8" color="black">
<g>
<path d="M 8 0 L 0 -3 L 0 3 Z" fill="currentColor" stroke="currentColor" stroke-width="1"/>
</g>
</marker>
</defs>
<metadata> Produced by OmniGraffle 7.18.5\n2021-05-24 19:57:04 +0000</metadata>
<g id="single_mode_dual_port_bram" stroke-opacity="1" fill="none" stroke-dasharray="none" fill-opacity="1" stroke="none">
<title>single_mode_dual_port_bram</title>
<g id="single_mode_dual_port_bram_Layer_1">
<title>Layer 1</title>
<g id="Graphic_2">
<rect x="431.28" y="178.56" width="180.36" height="90.36" fill="#ffffc0"/>
<rect x="431.28" y="178.56" width="180.36" height="90.36" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_3">
<path d="M 431.28 248.6386 L 443.16 253.9786 L 431.28 259.3186 Z" fill="#ccc"/>
<path d="M 431.28 248.6386 L 443.16 253.9786 L 431.28 259.3186 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Graphic_4">
<text transform="translate(443.16 246.20248)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-weight="400" fill="black" x="2.1677246" y="12">clock</tspan>
</text>
</g>
<g id="Graphic_6">
<text transform="translate(554.04 186.389)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-weight="400" fill="black" x="0" y="12">raddr[6:0]</tspan>
</text>
</g>
<g id="Graphic_7">
<text transform="translate(433.44 185.04)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-weight="400" fill="black" x="0" y="12">waddr[6:0]</tspan>
</text>
</g>
<g id="Graphic_8">
<text transform="translate(433.44 203.04)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-weight="400" fill="black" x="5.414551" y="12">wen</tspan>
</text>
</g>
<g id="Graphic_9">
<text transform="translate(581.9575 201.94124)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-weight="400" fill="black" x="5.414551" y="12">ren</tspan>
</text>
</g>
<g id="Graphic_10">
<text transform="translate(433.44 221.04)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-weight="400" fill="black" x=".17456055" y="12">data_in[7:0]</tspan>
</text>
</g>
<g id="Graphic_11">
<text transform="translate(537.7457 218.84248)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-weight="400" fill="black" x=".803154" y="12">data_out[7:0]</tspan>
</text>
</g>
<g id="Line_12">
<line x1="384.84" y1="192.96" x2="421.74" y2="193.01682" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_13">
<line x1="384.84" y1="209.21736" x2="419.94" y2="209.27141" marker-end="url(#FilledArrow_Marker_2)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Line_14">
<line x1="384.84" y1="228.31612" x2="421.74" y2="228.37295" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_15">
<line x1="384.84" y1="253.4786" x2="419.94" y2="253.53265" marker-end="url(#FilledArrow_Marker_2)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Line_16">
<line x1="613.08" y1="226.76248" x2="649.98" y2="226.8193" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_17">
<line x1="658.08" y1="209.93054" x2="622.98" y2="209.87648" marker-end="url(#FilledArrow_Marker_2)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Line_18">
<line x1="658.08" y1="193.0293" x2="621.18" y2="192.97247" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_19">
<line x1="406.25" y1="188.54" x2="399.8125" y2="198.1131" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_24">
<line x1="406.25" y1="222.47592" x2="399.8125" y2="232.04903" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_25">
<line x1="645.4375" y1="188.02956" x2="639" y2="197.60268" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_26">
<line x1="636.4375" y1="221.83204" x2="630" y2="231.40516" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

@ -0,0 +1,66 @@
<?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 xmlns:dc="http://purl.org/dc/elements/1.1/" version="1.1" xmlns:xl="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" viewBox="263.52 371.31224 204.94633 60.68" width="204.94633" height="60.68">
<defs>
<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="13" 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="-1256.384" 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>
<marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="FilledArrow_Marker" stroke-linejoin="miter" stroke-miterlimit="10" viewBox="-1 -2 5 4" markerWidth="5" markerHeight="4" color="black">
<g>
<path d="M 2.4 0 L 0 -.9 L 0 .9 Z" fill="currentColor" stroke="currentColor" stroke-width="1"/>
</g>
</marker>
</defs>
<metadata> Produced by OmniGraffle 7.18.5\n2021-05-24 21:09:05 +0000</metadata>
<g id="single_mode_mult_8x8" stroke-opacity="1" fill="none" stroke-dasharray="none" fill-opacity="1" stroke="none">
<title>single_mode_mult_8x8</title>
<g id="single_mode_mult_8x8_Layer_1">
<title>Layer 1</title>
<g id="Graphic_13">
<rect x="334.52" y="372.31224" width="57.6" height="58.68" fill="#ffffc0"/>
<rect x="334.52" y="372.31224" width="57.6" height="58.68" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
<text transform="translate(339.52 386.0575)" fill="black">
<tspan font-family="Times New Roman" font-size="14" font-style="italic" font-weight="400" fill="black" x="5.2677727" y="12">MULT</tspan>
<tspan font-family="Times New Roman" font-size="14" font-style="italic" font-weight="400" fill="black" x="13.693066" y="27.594727">8x8</tspan>
</text>
</g>
<g id="Graphic_10">
<text transform="translate(263.52 380.19224)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-style="italic" font-weight="400" fill="black" x="5.632742" y="12">a[7:0]</tspan>
</text>
</g>
<g id="Graphic_9">
<text transform="translate(266.58 403.05224)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-style="italic" font-weight="400" fill="black" x="2.5727406" y="12">b[7:0]</tspan>
</text>
</g>
<g id="Line_8">
<line x1="308.73274" y1="387.8861" x2="326.42005" y2="387.82172" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_7">
<line x1="305.67274" y1="410.6118" x2="326.4205" y2="410.38197" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_6">
<line x1="393.12" y1="401.65224" x2="409.80724" y2="401.65224" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_5">
<text transform="translate(417.90724 393.8761)" fill="black">
<tspan font-family="Times New Roman" font-size="13" font-style="italic" font-weight="400" fill="black" x="0" y="12">out[15:0]</tspan>
</text>
</g>
<g id="Line_14">
<line x1="320.67975" y1="382.12224" x2="315" y2="392.8145" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
<g id="Line_15">
<line x1="320.67975" y1="405.48224" x2="315" y2="416.1745" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@ -0,0 +1,50 @@
.. _file_format_bitstream_distribution_file:
Bitstream Distribution File (.xml)
----------------------------------
The bitstream distribution file aims to show
- The total number of configuration bits under each block
- The number of configuration bits per block
An example of design constraints is shown as follows.
.. code-block:: xml
<block name="fpga_top" number_of_bits="527">
<block name="grid_clb_1__1_" number_of_bits="136">
</block>
<block name="grid_io_top_1__2_" number_of_bits="8">
</block>
<block name="grid_io_right_2__1_" number_of_bits="8">
</block>
<block name="grid_io_bottom_1__0_" number_of_bits="8">
</block>
<block name="grid_io_left_0__1_" number_of_bits="8">
</block>
<block name="sb_0__0_" number_of_bits="58">
</block>
<block name="sb_0__1_" number_of_bits="57">
</block>
<block name="sb_1__0_" number_of_bits="59">
</block>
<block name="sb_1__1_" number_of_bits="56">
</block>
<block name="cbx_1__0_" number_of_bits="33">
</block>
<block name="cbx_1__1_" number_of_bits="33">
</block>
<block name="cby_0__1_" number_of_bits="30">
</block>
<block name="cby_1__1_" number_of_bits="33">
</block>
</block>
.. option:: name="<string>"
The block name represents the instance name which you can find in the fabric netlists
.. option:: number_of_bits="<string>"
The total number of configuration bits in this block

View File

@ -6,19 +6,35 @@ Bitstream Setting (.xml)
An example of bitstream settings is shown as follows.
This can define a hard-coded bitstream for a reconfigurable resource in FPGA fabrics.
.. warning:: Bitstream setting is a feature for power-users. It may cause wrong bitstream to be generated. For example, the hard-coded bitstream is not compatible with LUTs whose nets may be swapped during routing stage (cause a change on the truth table as well as bitstream). It is users's responsibility to ensure correct bitstream.
.. code-block:: xml
<openfpga_bitstream_setting>
<pb_type name="<string>" source="eblif" content=".param LUT" is_mode_select_bistream="true" bitstream_offset="1"/>
<interconnect name="<string>" default_path="<string>"/>
</openfpga_bitstream_setting>
.. option:: pb_type="<string>"
pb_type-related Settings
^^^^^^^^^^^^^^^^^^^^^^^^
The ``pb_type`` name to be constrained, which should be the full path of a ``pb_type`` consistent with VPR's architecture description. For example, ``pb_type="clb.fle[arithmetic].soft_adder.adder_lut4"``
The following syntax are applicable to the XML definition tagged by ``pb_type`` in bitstream setting files.
.. option:: name="<string>"
The ``pb_type`` name to be constrained, which should be the full path of a ``pb_type`` consistent with VPR's architecture description. For example,
.. code-block:: xml
pb_type="clb.fle[arithmetic].soft_adder.adder_lut4"
.. option:: source="<string>"
The source of the ``pb_type`` bitstream, which could be from a ``.eblif`` file. For example, ``source="eblif"``.
The source of the ``pb_type`` bitstream, which could be from a ``.eblif`` file. For example,
.. code-block:: xml
source="eblif"
.. option:: content="<string>"
@ -33,5 +49,25 @@ This can define a hard-coded bitstream for a reconfigurable resource in FPGA fab
Specify the offset to be applied when overloading the bitstream to a target. For example, a LUT may have a 16-bit bitstream. When ``offset=1``, bitstream overloading will skip the first bit and start from the second bit of the 16-bit bitstream.
.. warning:: Bitstream setting is a feature for power-users. It may cause wrong bitstream to be generated. For example, the hard-coded bitstream is not compatible with LUTs whose nets may be swapped during routing stage (cause a change on the truth table as well as bitstream). It is users's responsibility to ensure correct bitstream.
Interconnection-related Settings
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The following syntax are applicable to the XML definition tagged by ``interconnect`` in bitstream setting files.
.. option:: name="<string>"
The ``interconnect`` name to be constrained, which should be the full path of a ``pb_type`` consistent with VPR's architecture description. For example,
.. code-block:: xml
pb_type="clb.fle[arithmetic].mux1"
.. option:: default_path="<string>"
The default path denotes an input name that is consistent with VPR's architecture description. For example, in VPR architecture, there is a mux defined as
.. code-block:: xml
<mux name="mux1" input="iopad.inpad ff.Q" output="io.inpad"/>
The default path can be either ``iopad.inpad`` or ``ff.Q`` which corresponds to the first input and the second input respectively.

View File

@ -5,7 +5,7 @@ Fabric-dependent Bitstream
.. _file_formats_fabric_bitstream_plain_text:
Plain text (.txt)
Plain text (.bit)
~~~~~~~~~~~~~~~~~
This file format is designed to be directly loaded to an FPGA fabric.
@ -43,27 +43,38 @@ The information depends on the type of configuration procotol.
.. option:: memory_bank
Multiple lines will be included, each of which is organized as <address><space><bits>.
Note that due to the use of Bit-Line and Word-Line decoders, every two lines are paired.
The first line represents the Bit-Line address and configuration bit.
The second line represents the Word-Line address and configuration bit.
Multiple lines will be included, each of which is organized as <bl_address><wl_address><bits>.
The size of address line and data input bits are shown as a comment in the bitstream file, which eases the development of bitstream downloader.
For example
.. code-block:: verilog
// Bitstream width (LSB -> MSB): <bl_address 5 bits><wl_address 5 bits><data input 1 bits>
The first part represents the Bit-Line address.
The second part represents the Word-Line address.
The third part represents the configuration bit.
For example
.. code-block:: xml
<bitline_address> <bit_value>
<wordline_address> <bit_value>
<bitline_address> <bit_value>
<wordline_address> <bit_value>
<bitline_address><wordline_address><bit_value>
<bitline_address><wordline_address><bit_value>
...
<bitline_address> <bit_value>
<wordline_address> <bit_value>
<bitline_address><wordline_address><bit_value>
.. note:: When there are multiple configuration regions, each ``<bit_value>`` may consist of multiple bits. For example, ``0110`` represents the bits for 4 configuration regions, where the 4 digits correspond to the bits from region ``0, 1, 2, 3`` respectively.
.. option:: frame_based
Multiple lines will be included, each of which is organized as <address><space><bits>.
Multiple lines will be included, each of which is organized as ``<address><data_input_bits>``.
The size of address line and data input bits are shown as a comment in the bitstream file, which eases the development of bitstream downloader.
For example
.. code-block:: verilog
// Bitstream width (LSB -> MSB): <address 14 bits><data input 1 bits>
Note that the address may include don't care bit which is denoted as ``x``.
.. note:: OpenFPGA automatically convert don't care bit to logic ``0`` when generating testbenches.
@ -72,10 +83,10 @@ The information depends on the type of configuration procotol.
.. code-block:: xml
<frame_address> <bit_value>
<frame_address> <bit_value>
<frame_address><bit_value>
<frame_address><bit_value>
...
<frame_address> <bit_value>
<frame_address><bit_value>
.. note:: When there are multiple configuration regions, each ``<bit_value>`` may consist of multiple bits. For example, ``0110`` represents the bits for 4 configuration regions, where the 4 digits correspond to the bits from region ``0, 1, 2, 3`` respectively.

View File

@ -21,3 +21,7 @@ OpenFPGA widely uses XML format for interchangable files
bitstream_setting
fabric_key
io_mapping_file
bitstream_distribution_file

View File

@ -0,0 +1,33 @@
.. _file_format_io_mapping_file:
I/O Mapping File (.xml)
-----------------------
The I/O mapping file aims to show
- What nets have been mapped to each I/O
- What is the directionality of each mapped I/O
An example of design constraints is shown as follows.
.. code-block:: xml
<io_mapping>
<io name="gfpga_pad_GPIO_PAD[6:6]" net="a" dir="input"/>
<io name="gfpga_pad_GPIO_PAD[1:1]" net="b" dir="input"/>
<io name="gfpga_pad_GPIO_PAD[9:9]" net="out_c" dir="output"/>
</io_mapping>
.. option:: name="<string>"
The pin name of the FPGA fabric which has been mapped, which should be a valid pin defined in OpenFPGA architecture description.
.. note:: You should be find the exact pin in the top-level module of FPGA fabric if you output the Verilog netlists.
.. option:: net="<string>"
The net name which is actually mapped to a pin, which should be consistent with net definition in your ``.blif`` file.
.. option:: dir="<string>"
The direction of an I/O, which can be either ``input`` or ``output``.

View File

@ -3,6 +3,11 @@
Repack Design Constraints (.xml)
--------------------------------
.. warning:: For the best practice, current repack design constraints only support the net remapping between pins in the same port. Pin constraints are **NOT** allowed for two separated ports.
- A legal pin constraint example: when there are two clock nets, ``clk0`` and ``clk1``, pin constraints are forced on two pins in a clock port ``clk[0:2]`` (e.g., ``clk[0] = clk0`` and ``clk[1] == clk1``).
- An **illegal** pin constraint example: when there are two clock nets, ``clk0`` and ``clk1``, pin constraints are forced on two clock ports ``clkA[0]`` and ``clkB[0]`` (e.g., ``clkA[0] = clk0`` and ``clkB[0] == clk1``).
An example of design constraints is shown as follows.
.. code-block:: xml
@ -25,5 +30,5 @@ An example of design constraints is shown as follows.
.. option:: net="<string>"
The net name of the pin to be mapped, which should be consistent with net definition in your ``.blif`` file. The reserved word ``OPEN`` means that no net should be mapped to a given pin. Please ensure that it is not conflicted with any net names in your ``.blif`` file.
.. warning:: Design constraints is a feature for power-users. It may cause repack to fail. It is users's responsibility to ensure proper design constraints

View File

@ -0,0 +1,102 @@
<?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 xmlns:dc="http://purl.org/dc/elements/1.1/" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xl="http://www.w3.org/1999/xlink" viewBox="501 16 702 175" width="702" height="175">
<defs>
<font-face font-family="Helvetica Neue" font-size="20" panose-1="2 0 5 3 0 0 0 2 0 4" units-per-em="1000" underline-position="-100" underline-thickness="50" slope="0" x-height="517" cap-height="714" ascent="951.9958" descent="-212.99744" font-weight="400">
<font-face-src>
<font-face-name name="HelveticaNeue"/>
</font-face-src>
</font-face>
<marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="FilledArrow_Marker" stroke-linejoin="miter" stroke-miterlimit="10" viewBox="-1 -3 7 6" markerWidth="7" markerHeight="6" color="black">
<g>
<path d="M 4.8 0 L 0 -1.8 L 0 1.8 Z" fill="currentColor" stroke="currentColor" stroke-width="1"/>
</g>
</marker>
<font-face font-family="Helvetica Neue" font-size="18" panose-1="2 0 5 3 0 0 0 2 0 4" units-per-em="1000" underline-position="-100" underline-thickness="50" slope="0" x-height="517" cap-height="714" ascent="951.9958" descent="-212.99744" font-weight="400">
<font-face-src>
<font-face-name name="HelveticaNeue"/>
</font-face-src>
</font-face>
</defs>
<metadata> Produced by OmniGraffle 7.18.5\n2021-06-03 22:42:19 +0000</metadata>
<g id="block_diagram" fill-opacity="1" stroke="none" stroke-opacity="1" stroke-dasharray="none" fill="none">
<title>block_diagram</title>
<rect fill="white" x="501" y="16" width="702" height="175"/>
<g id="block_diagram_Layer_1">
<title>Layer 1</title>
<g id="Graphic_91">
<rect x="502.5" y="25.252" width="128.5" height="49" fill="#666"/>
<rect x="502.5" y="25.252" width="128.5" height="49" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
<text transform="translate(507.5 37.972)" fill="white">
<tspan font-family="Helvetica Neue" font-size="20" font-weight="400" fill="white" x=".91" y="19">Bitstream file</tspan>
</text>
</g>
<g id="Line_92">
<line x1="632" y1="49.752" x2="726.244" y2="49.752" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
</g>
<g id="block_diagram_block_diagram">
<title>block_diagram</title>
<g id="Graphic_89">
<rect x="740.144" y="34" width="92.332" height="68" fill="#4040ff"/>
<rect x="740.144" y="34" width="92.332" height="68" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
<text transform="translate(745.144 44.44)" fill="white">
<tspan font-family="Helvetica Neue" font-size="20" font-weight="400" fill="white" x="14.876" y="19">FPGA </tspan>
<tspan font-family="Helvetica Neue" font-size="20" font-weight="400" fill="white" x="13.206" y="42.56">Fabric</tspan>
</text>
</g>
<g id="Graphic_88">
<rect x="740.144" y="122" width="92.332" height="68" fill="#4040ff"/>
<rect x="740.144" y="122" width="92.332" height="68" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
<text transform="translate(745.144 132.44)" fill="white">
<tspan font-family="Helvetica Neue" font-size="20" font-weight="400" fill="white" x="13.206" y="19">Users </tspan>
<tspan font-family="Helvetica Neue" font-size="20" font-weight="400" fill="white" x="10.236" y="42.56">Design</tspan>
</text>
</g>
<g id="Graphic_87">
<rect x="969.072" y="61" width="92.332" height="98.5" fill="#ff4040"/>
<rect x="969.072" y="61" width="92.332" height="98.5" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
<text transform="translate(974.072 86.69)" fill="white">
<tspan font-family="Helvetica Neue" font-size="20" font-weight="400" fill="white" x="10.216" y="19">Output </tspan>
<tspan font-family="Helvetica Neue" font-size="20" font-weight="400" fill="white" x="3.7560004" y="42.56">Checker</tspan>
</text>
</g>
<g id="Graphic_86">
<text transform="translate(598.566 99.248)" fill="black">
<tspan font-family="Helvetica Neue" font-size="18" font-weight="400" fill="black" x="45474735e-20" y="17">Input stimulus</tspan>
</text>
</g>
<g id="Line_85">
<line x1="833.476" y1="68" x2="955.172" y2="68" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_84">
<line x1="833.476" y1="156" x2="955.172" y2="156" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_83">
<line x1="1062.404" y1="110.84803" x2="1091.601" y2="111.21822" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Graphic_82">
<text transform="translate(1109.5 90.496)" fill="black">
<tspan font-family="Helvetica Neue" font-size="18" font-weight="400" fill="black" x="1.0814986" y="17">Number of </tspan>
<tspan font-family="Helvetica Neue" font-size="18" font-weight="400" fill="black" x="20.431499" y="38.504">errors</tspan>
</text>
</g>
<g id="Graphic_81">
<text transform="translate(842 39)" fill="black">
<tspan font-family="Helvetica Neue" font-size="18" font-weight="400" fill="black" x="22737368e-20" y="17">FPGA output vectors</tspan>
</text>
</g>
<g id="Graphic_80">
<text transform="translate(842 163.496)" fill="black">
<tspan font-family="Helvetica Neue" font-size="18" font-weight="400" fill="black" x="42632564e-21" y="17">Expected output vectors</tspan>
</text>
</g>
<g id="Line_79">
<path d="M 655.095 94.248 L 655.095 68 L 726.244 68" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
<g id="Line_78">
<path d="M 655.095 125.752 L 655.095 156 L 726.244 156" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.5 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 284 KiB

View File

@ -16,24 +16,32 @@ In this part, we will introduce the hierarchy, dependency and functionality of e
+-----------------+---------+----------------+---------------+
OpenFPGA can auto-generate two types of Verilog testbenches to validate the correctness of the fabric: full and formal-oriented.
Both testbenches share the same organization, as depicted in :numref:`fig_verilog_testbench_organization` (a).
Both testbenches share the same organization, as depicted in :numref:`fig_verilog_testbench_organization`.
To enable self-testing, the FPGA and user's RTL design (simulate using an HDL simulator) are driven by the same input stimuli, and any mismatch on their outputs will raise an error flag.
.. _fig_verilog_testbench_organization:
.. figure:: figures/verilog_testbench_organization.png
.. figure:: figures/full_testbench_block_diagram.svg
:scale: 50%
:alt: Functional Verification using ModelSim
:alt: Verilog testbench principles
Principles of Verilog testbenches organization: (a) block diagram and (b) waveforms.
Principles of Verilog testbenches: (1) using common input stimuli; (2) applying bitstream; (3) checking output vectors.
.. _fig_verilog_full_testbench_waveform:
.. figure:: figures/full_testbench_waveform.svg
:scale: 50%
:alt: Full testbench waveform
Illustration on the waveforms in full testbench
Full Testbench
~~~~~~~~~~~~~~
Full testbench aims at simulating an entire FPGA operating period, consisting of two phases:
- the **Configuration Phase**, where the synthesized design bitstream is loaded to the programmable fabric, as highlighted by the green rectangle of :numref:`fig_verilog_testbench_organization` (b);
- the **Configuration Phase**, where the synthesized design bitstream is loaded to the programmable fabric, as highlighted by the green rectangle of :numref:`fig_verilog_full_testbench_waveform`;
- the **Operating Phase**, where random input vectors are auto-generated to drive both Devices Under Test (DUTs), as highlighted by the red rectangle of :numref:`fig_verilog_testbench_organization` (b). Using the full testbench, users can validate both the configuration circuits and programming fabric of an FPGA.
- the **Operating Phase**, where random input vectors are auto-generated to drive both Devices Under Test (DUTs), as highlighted by the red rectangle of :numref:`fig_verilog_full_testbench_waveform`. Using the full testbench, users can validate both the configuration circuits and programming fabric of an FPGA.
Formal-oriented Testbench
~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -69,6 +69,49 @@ write_fabric_bitstream
Specify the file format [``plain_text`` | ``xml``]. By default is ``plain_text``.
See file formats in :ref:`file_formats_fabric_bitstream_xml` and :ref:`file_formats_fabric_bitstream_plain_text`.
.. option:: --fast_configuration
Reduce the bitstream size when outputing by skipping dummy configuration bits. 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.
.. warning:: Fast configuration is only applicable to plain text file format!
.. 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.
.. option:: --verbose
Show verbose log
write_io_mapping
~~~~~~~~~~~~~~~~
Output the I/O mapping information to a file
.. option:: --file <string> or -f <string>
Specify the file name where the I/O mapping will be outputted to.
See file formats in :ref:`file_format_io_mapping_file`.
.. option:: --verbose
Show verbose log
report_bitstream_distribution
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Output the bitstream distribution to a file
.. option:: --file <string> or -f <string>
Specify the file name where the bitstream distribution will be outputted to.
See file formats in :ref:`file_format_bitstream_distribution_file`.
.. option:: --depth <int> or -d <int>
Specify the maximum depth of the block which should appear in the block
.. option:: --verbose
Show verbose log

View File

@ -6,7 +6,7 @@ FPGA-Verilog
write_fabric_verilog
~~~~~~~~~~~~~~~~~~~~
Write the Verilog netlist for FPGA fabric based on module graph
Write the Verilog netlist for FPGA fabric based on module graph. See details in :ref:`fabric_netlists`.
.. option:: --file <string> or -f <string>
@ -40,15 +40,19 @@ write_fabric_verilog
Show verbose log
write_verilog_testbench
write_full_testbench
~~~~~~~~~~~~~~~~~~~~~~~
Write the Verilog testbench for FPGA fabric
Write the full testbench for FPGA fabric in Verilog format. See details in :ref:`fpga_verilog_testbench`.
.. option:: --file <string> or -f <string>
The output directory for all the testbench netlists. We suggest the use of same output directory as fabric Verilog netlists. For example, ``--file /temp/testbench``
.. option:: --bitstream <string>
The bitstream file to be loaded to the full testbench, which should be in the same file format that OpenFPGA can outputs (See detailes in :ref:`file_formats_fabric_bitstream_plain_text`). For example, ``--bitstream and2.bit``
.. option:: --fabric_netlist_file_path <string>
Specify the fabric Verilog file if they are not in the same directory as the testbenches to be generated. If not specified, OpenFPGA will assume that the fabric netlists are the in the same directory as testbenches and assign default names. For example, ``--file /temp/fabric/fabric_netlists.v``
@ -68,22 +72,113 @@ write_verilog_testbench
.. 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.
.. option:: --print_top_testbench
.. option:: --explicit_port_mapping
Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA
Use explicit port mapping when writing the Verilog netlists
.. option:: --print_formal_verification_top_netlist
.. option:: --default_net_type <string>
Generate a top-level module which can be used in formal verification
Specify the default net type for the Verilog netlists. Currently, supported types are ``none`` and ``wire``. Default value: ``none``.
.. option:: --print_preconfig_top_testbench
.. option:: --include_signal_init
Enable pre-configured top-level testbench which is a fast verification skipping programming phase
Output signal initialization to Verilog testbench to smooth convergence in HDL simulation
.. option:: --print_simulation_ini <string>
.. option:: --verbose
Output an exchangeable simulation ini file, which is needed only when you need to interface different HDL simulators using openfpga flow-run scripts. For example, ``--print_simulation_ini /temp/testbench/sim.ini``
Show verbose log
write_preconfigured_fabric_wrapper
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Write the Verilog wrapper for a preconfigured FPGA fabric. See details in :ref:`fpga_verilog_testbench`.
.. option:: --file <string> or -f <string>
The output directory for the netlists. We suggest the use of same output directory as fabric Verilog netlists. For example, ``--file /temp/testbench``
.. option:: --fabric_netlist_file_path <string>
Specify the fabric Verilog file if they are not in the same directory as the testbenches to be generated. If not specified, OpenFPGA will assume that the fabric netlists are the in the same directory as testbenches and assign default names. For example, ``--file /temp/fabric/fabric_netlists.v``
.. option:: --pin_constraints_file <string> or -pcf <string>
Specify the *Pin Constraints File* (PCF) if you want to custom stimulus in testbenches. For example, ``-pin_constraints_file pin_constraints.xml``
Strongly recommend for multi-clock simulations. See detailed file format about :ref:`file_format_pin_constraints_file`.
.. option:: --explicit_port_mapping
Use explicit port mapping when writing the Verilog netlists
.. option:: --default_net_type <string>
Specify the default net type for the Verilog netlists. Currently, supported types are ``none`` and ``wire``. Default value: ``none``.
.. option:: --support_icarus_simulator
Output Verilog netlists with syntax that iVerilog simulator can accept
.. option:: --verbose
Show verbose log
write_preconfigured_testbench
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Write the Verilog testbench for a preconfigured FPGA fabric. See details in :ref:`fpga_verilog_testbench`.
.. option:: --file <string> or -f <string>
The output directory for all the testbench netlists. We suggest the use of same output directory as fabric Verilog netlists. For example, ``--file /temp/testbench``
.. option:: --fabric_netlist_file_path <string>
Specify the fabric Verilog file if they are not in the same directory as the testbenches to be generated. If not specified, OpenFPGA will assume that the fabric netlists are the in the same directory as testbenches and assign default names. For example, ``--file /temp/fabric/fabric_netlists.v``
.. option:: --reference_benchmark_file_path <string>
Must specify the reference benchmark Verilog file if you want to output any testbenches. For example, ``--reference_benchmark_file_path /temp/benchmark/counter_post_synthesis.v``
.. option:: --pin_constraints_file <string> or -pcf <string>
Specify the *Pin Constraints File* (PCF) if you want to custom stimulus in testbenches. For example, ``-pin_constraints_file pin_constraints.xml``
Strongly recommend for multi-clock simulations. See detailed file format about :ref:`file_format_pin_constraints_file`.
.. option:: --explicit_port_mapping
Use explicit port mapping when writing the Verilog netlists
.. option:: --default_net_type <string>
Specify the default net type for the Verilog netlists. Currently, supported types are ``none`` and ``wire``. Default value: ``none``.
.. option:: --support_icarus_simulator
Output Verilog netlists with syntax that iVerilog simulator can accept
.. option:: --verbose
Show verbose log
write_simulation_task_info
~~~~~~~~~~~~~~~~~~~~~~~~~~
Write an interchangeable file in ``.ini`` format to interface HDL simulators, such as iVerilog and Modelsim.
.. option:: --file <string> or -f <string>
Specify the file path to output simulation-related information. For example, ``--file simulation.ini``
.. option:: --hdl_dir <string>
Specify the directory path where HDL netlists are created. For example, ``--hdl_dir ./SRC``
.. option:: --reference_benchmark_file_path <string>
Must specify the reference benchmark Verilog file if you want to output any testbenches. For example, ``--reference_benchmark_file_path /temp/benchmark/counter_post_synthesis.v``
.. option:: --verbose
Show verbose log

View File

@ -42,19 +42,21 @@ Supported Circuit Designs
+-----------------+--------------+-----------+-----------------------------------------------------+
| | Configurable | No | Yes | - :ref:`circuit_model_config_latch_example` |
| | Memory | | | - :ref:`circuit_model_sram_blwl_example` |
| | | | - :ref:`circuit_model_dff_example` |
| | | | - :ref:`circuit_model_ccff_example` |
| | | | - :ref:`circuit_model_ccff_enable_example` |
| | | | - :ref:`circuit_model_ccff_scanable_example` |
+-----------------+--------------+-----------+-----------------------------------------------------+
| Block RAM | No | Yes | - **Any size** |
| | | | - Single-port |
| | | | - Dual-port |
| | | | - Fracturable |
| Data Memory | No | Yes | - **Any size** |
| | | | - :ref:`circuit_model_dff_example` |
| | | | - :ref:`circuit_model_multi_mode_ff_example` |
| | | | - Single-port Block RAM |
| | | | - :ref:`circuit_model_single_mode_dpram_example` |
| | | | - :ref:`circuit_model_multi_mode_dpram_example` |
+-----------------+--------------+-----------+-----------------------------------------------------+
| | Arithmetic | No | Yes | - **Any size** |
| | Units | | | - Multiplier |
| | | | - :ref:`circuit_model_full_adder_example` |
| | Units | | | - :ref:`circuit_model_full_adder_example` |
| | | | - :ref:`circuit_model_single_mode_mult8x8_example` |
| | | | - :ref:`circuit_model_multi_mode_mult8x8_example` |
+-----------------+--------------+-----------+-----------------------------------------------------+
| I/O | No | Yes | - :ref:`circuit_model_gpio_example` |
| | | | - Bi-directional buffer |

View File

@ -11,7 +11,7 @@ How to Compile
General Guidelines
~~~~~~~~~~~~~~~~~~
OpenFPGA uses CMake to generate the Makefile scripts
OpenFPGA uses CMake to generate the Makefile scripts.
In general, please follow the steps to compile
.. code-block:: shell
@ -24,7 +24,7 @@ In general, please follow the steps to compile
.. note:: cmake3.12+ is recommended to compile OpenFPGA with GUI
.. note:: recommend using ``make -j`` to accelerate the compilation
.. note:: Recommend using ``make -j<int>`` to accelerate the compilation, where ``<int>`` denotes the number of cores to be used in compilation.
.. note:: VPR's GUI requires gtk-3, and can be enabled with ``cmake .. -DVPR_USE_EZGL=on``

View File

@ -16,6 +16,10 @@ BitstreamSetting::bitstream_pb_type_setting_range BitstreamSetting::pb_type_sett
return vtr::make_range(pb_type_setting_ids_.begin(), pb_type_setting_ids_.end());
}
BitstreamSetting::bitstream_interconnect_setting_range BitstreamSetting::interconnect_settings() const {
return vtr::make_range(interconnect_setting_ids_.begin(), interconnect_setting_ids_.end());
}
/************************************************************************
* Constructors
***********************************************************************/
@ -61,6 +65,25 @@ size_t BitstreamSetting::bitstream_offset(const BitstreamPbTypeSettingId& pb_typ
return bitstream_offsets_[pb_type_setting_id];
}
std::string BitstreamSetting::interconnect_name(const BitstreamInterconnectSettingId& interconnect_setting_id) const {
VTR_ASSERT(true == valid_bitstream_interconnect_setting_id(interconnect_setting_id));
return interconnect_names_[interconnect_setting_id];
}
std::vector<std::string> BitstreamSetting::parent_pb_type_names(const BitstreamInterconnectSettingId& interconnect_setting_id) const {
VTR_ASSERT(true == valid_bitstream_interconnect_setting_id(interconnect_setting_id));
return interconnect_parent_pb_type_names_[interconnect_setting_id];
}
std::vector<std::string> BitstreamSetting::parent_mode_names(const BitstreamInterconnectSettingId& interconnect_setting_id) const {
VTR_ASSERT(true == valid_bitstream_interconnect_setting_id(interconnect_setting_id));
return interconnect_parent_mode_names_[interconnect_setting_id];
}
std::string BitstreamSetting::default_path(const BitstreamInterconnectSettingId& interconnect_setting_id) const {
VTR_ASSERT(true == valid_bitstream_interconnect_setting_id(interconnect_setting_id));
return interconnect_default_paths_[interconnect_setting_id];
}
/************************************************************************
* Public Mutators
@ -95,6 +118,20 @@ void BitstreamSetting::set_bitstream_offset(const BitstreamPbTypeSettingId& pb_t
bitstream_offsets_[pb_type_setting_id] = offset;
}
BitstreamInterconnectSettingId BitstreamSetting::add_bitstream_interconnect_setting(const std::string& interconnect_name,
const std::vector<std::string>& parent_pb_type_names,
const std::vector<std::string>& parent_mode_names,
const std::string& default_path) {
BitstreamInterconnectSettingId interc_setting_id = BitstreamInterconnectSettingId(interconnect_setting_ids_.size());
interconnect_setting_ids_.push_back(interc_setting_id);
interconnect_names_.push_back(interconnect_name);
interconnect_parent_pb_type_names_.push_back(parent_pb_type_names);
interconnect_parent_mode_names_.push_back(parent_mode_names);
interconnect_default_paths_.push_back(default_path);
return interc_setting_id;
}
/************************************************************************
* Public Validators
***********************************************************************/
@ -102,4 +139,8 @@ bool BitstreamSetting::valid_bitstream_pb_type_setting_id(const BitstreamPbTypeS
return ( size_t(pb_type_setting_id) < pb_type_setting_ids_.size() ) && ( pb_type_setting_id == pb_type_setting_ids_[pb_type_setting_id] );
}
bool BitstreamSetting::valid_bitstream_interconnect_setting_id(const BitstreamInterconnectSettingId& interconnect_setting_id) const {
return ( size_t(interconnect_setting_id) < interconnect_setting_ids_.size() ) && ( interconnect_setting_id == interconnect_setting_ids_[interconnect_setting_id] );
}
} /* namespace openfpga ends */

View File

@ -16,6 +16,10 @@ namespace openfpga {
/********************************************************************
* A data structure to describe bitstream settings
*
* This data structure includes following types of settings:
* - Pb type: include definiting hard coded bitstream for pb_types (LUT or configurable pb_type for mode selection)
* - Interconnect: include defining default paths for routing multiplexers in pb_types
*
* Typical usage:
* --------------
@ -27,12 +31,15 @@ namespace openfpga {
class BitstreamSetting {
public: /* Types */
typedef vtr::vector<BitstreamPbTypeSettingId, BitstreamPbTypeSettingId>::const_iterator bitstream_pb_type_setting_iterator;
typedef vtr::vector<BitstreamInterconnectSettingId, BitstreamInterconnectSettingId>::const_iterator bitstream_interconnect_setting_iterator;
/* Create range */
typedef vtr::Range<bitstream_pb_type_setting_iterator> bitstream_pb_type_setting_range;
typedef vtr::Range<bitstream_interconnect_setting_iterator> bitstream_interconnect_setting_range;
public: /* Constructors */
BitstreamSetting();
public: /* Accessors: aggregates */
bitstream_pb_type_setting_range pb_type_settings() const;
bitstream_interconnect_setting_range interconnect_settings() const;
public: /* Public Accessors */
std::string pb_type_name(const BitstreamPbTypeSettingId& pb_type_setting_id) const;
std::vector<std::string> parent_pb_type_names(const BitstreamPbTypeSettingId& pb_type_setting_id) const;
@ -41,6 +48,10 @@ class BitstreamSetting {
std::string pb_type_bitstream_content(const BitstreamPbTypeSettingId& pb_type_setting_id) const;
bool is_mode_select_bitstream(const BitstreamPbTypeSettingId& pb_type_setting_id) const;
size_t bitstream_offset(const BitstreamPbTypeSettingId& pb_type_setting_id) const;
std::string interconnect_name(const BitstreamInterconnectSettingId& interconnect_setting_id) const;
std::vector<std::string> parent_pb_type_names(const BitstreamInterconnectSettingId& interconnect_setting_id) const;
std::vector<std::string> parent_mode_names(const BitstreamInterconnectSettingId& interconnect_setting_id) const;
std::string default_path(const BitstreamInterconnectSettingId& interconnect_setting_id) const;
public: /* Public Mutators */
BitstreamPbTypeSettingId add_bitstream_pb_type_setting(const std::string& pb_type_name,
const std::vector<std::string>& parent_pb_type_names,
@ -51,9 +62,19 @@ class BitstreamSetting {
const bool& is_mode_select_bitstream);
void set_bitstream_offset(const BitstreamPbTypeSettingId& pb_type_setting_id,
const size_t& offset);
BitstreamInterconnectSettingId add_bitstream_interconnect_setting(const std::string& interconnect_name,
const std::vector<std::string>& parent_pb_type_names,
const std::vector<std::string>& parent_mode_names,
const std::string& default_path);
public: /* Public Validators */
bool valid_bitstream_pb_type_setting_id(const BitstreamPbTypeSettingId& pb_type_setting_id) const;
bool valid_bitstream_interconnect_setting_id(const BitstreamInterconnectSettingId& interconnect_setting_id) const;
private: /* Internal data */
/* Pb type -related settings
* - Paths to a pb_type in the pb_graph
* - Bitstream source, data_type, offsets etc.
*/
vtr::vector<BitstreamPbTypeSettingId, BitstreamPbTypeSettingId> pb_type_setting_ids_;
vtr::vector<BitstreamPbTypeSettingId, std::string> pb_type_names_;
vtr::vector<BitstreamPbTypeSettingId, std::vector<std::string>> parent_pb_type_names_;
@ -64,6 +85,16 @@ class BitstreamSetting {
vtr::vector<BitstreamPbTypeSettingId, bool> is_mode_select_bitstreams_;
/* The offset that the bitstream is applied to the original bitstream of a pb_type */
vtr::vector<BitstreamPbTypeSettingId, size_t> bitstream_offsets_;
/* Interconnect-related settings:
* - Name of interconnect under a given pb_type
* - The default path to be considered for a given interconnect during bitstream generation
*/
vtr::vector<BitstreamInterconnectSettingId, BitstreamInterconnectSettingId> interconnect_setting_ids_;
vtr::vector<BitstreamInterconnectSettingId, std::string> interconnect_names_;
vtr::vector<BitstreamInterconnectSettingId, std::vector<std::string>> interconnect_parent_pb_type_names_;
vtr::vector<BitstreamInterconnectSettingId, std::vector<std::string>> interconnect_parent_mode_names_;
vtr::vector<BitstreamInterconnectSettingId, std::string> interconnect_default_paths_;
};
} /* namespace openfpga ends */

View File

@ -13,8 +13,10 @@
#include "vtr_strong_id.h"
struct bitstream_pb_type_setting_id_tag;
struct bitstream_interconnect_setting_id_tag;
typedef vtr::StrongId<bitstream_pb_type_setting_id_tag> BitstreamPbTypeSettingId;
typedef vtr::StrongId<bitstream_interconnect_setting_id_tag> BitstreamInterconnectSettingId;
/* Short declaration of class */
class BitstreamSetting;

View File

@ -86,11 +86,11 @@ std::vector<std::string> PbTypeAnnotation::port_names() const {
return keys;
}
std::map<BasicPort, std::array<int, 2>> PbTypeAnnotation::physical_pb_type_port(const std::string& port_name) const {
std::map<std::string, std::map<BasicPort, std::array<int, 2>>>::const_iterator it = operating_pb_type_ports_.find(port_name);
std::map<BasicPort, std::array<int, 3>> PbTypeAnnotation::physical_pb_type_port(const std::string& port_name) const {
std::map<std::string, std::map<BasicPort, std::array<int, 3>>>::const_iterator it = operating_pb_type_ports_.find(port_name);
if (it == operating_pb_type_ports_.end()) {
/* Return an empty port */
return std::map<BasicPort, std::array<int, 2>>();
return std::map<BasicPort, std::array<int, 3>>();
}
return operating_pb_type_ports_.at(port_name);
}
@ -169,25 +169,25 @@ void PbTypeAnnotation::set_physical_pb_type_index_offset(const int& value) {
void PbTypeAnnotation::add_pb_type_port_pair(const std::string& operating_pb_port_name,
const BasicPort& physical_pb_port) {
/* Give a warning if the operating_pb_port_name already exist */
std::map<std::string, std::map<BasicPort, std::array<int, 2>>>::const_iterator it = operating_pb_type_ports_.find(operating_pb_port_name);
std::map<std::string, std::map<BasicPort, std::array<int, 3>>>::const_iterator it = operating_pb_type_ports_.find(operating_pb_port_name);
/* If not exist, initialize and set a default value */
if (it == operating_pb_type_ports_.end()) {
operating_pb_type_ports_[operating_pb_port_name][physical_pb_port] = {0, 0};
operating_pb_type_ports_[operating_pb_port_name][physical_pb_port] = {0, 0, 0};
/* We can return early */
return;
}
/* If the physical port is not in the list, we create one and set a default value */
if (0 == operating_pb_type_ports_[operating_pb_port_name].count(physical_pb_port)) {
operating_pb_type_ports_[operating_pb_port_name][physical_pb_port] = {0, 0};
operating_pb_type_ports_[operating_pb_port_name][physical_pb_port] = {0, 0, 0};
}
}
void PbTypeAnnotation::set_physical_pin_initial_offset(const std::string& operating_pb_port_name,
const BasicPort& physical_pb_port,
const int& physical_pin_initial_offset) {
std::map<std::string, std::map<BasicPort, std::array<int, 2>>>::const_iterator it = operating_pb_type_ports_.find(operating_pb_port_name);
std::map<std::string, std::map<BasicPort, std::array<int, 3>>>::const_iterator it = operating_pb_type_ports_.find(operating_pb_port_name);
if (it == operating_pb_type_ports_.end()) {
VTR_LOG_ERROR("The operating pb_type port '%s' is not valid!\n",
@ -210,7 +210,7 @@ void PbTypeAnnotation::set_physical_pin_initial_offset(const std::string& operat
void PbTypeAnnotation::set_physical_pin_rotate_offset(const std::string& operating_pb_port_name,
const BasicPort& physical_pb_port,
const int& physical_pin_rotate_offset) {
std::map<std::string, std::map<BasicPort, std::array<int, 2>>>::const_iterator it = operating_pb_type_ports_.find(operating_pb_port_name);
std::map<std::string, std::map<BasicPort, std::array<int, 3>>>::const_iterator it = operating_pb_type_ports_.find(operating_pb_port_name);
if (it == operating_pb_type_ports_.end()) {
VTR_LOG_ERROR("The operating pb_type port '%s' is not valid!\n",
@ -230,6 +230,30 @@ void PbTypeAnnotation::set_physical_pin_rotate_offset(const std::string& operati
operating_pb_type_ports_[operating_pb_port_name][physical_pb_port][1] = physical_pin_rotate_offset;
}
void PbTypeAnnotation::set_physical_port_rotate_offset(const std::string& operating_pb_port_name,
const BasicPort& physical_pb_port,
const int& physical_port_rotate_offset) {
std::map<std::string, std::map<BasicPort, std::array<int, 3>>>::const_iterator it = operating_pb_type_ports_.find(operating_pb_port_name);
if (it == operating_pb_type_ports_.end()) {
VTR_LOG_ERROR("The operating pb_type port '%s' is not valid!\n",
operating_pb_port_name.c_str());
exit(1);
}
if (operating_pb_type_ports_[operating_pb_port_name].end() == operating_pb_type_ports_[operating_pb_port_name].find(physical_pb_port)) {
VTR_LOG_ERROR("The physical pb_type port '%s[%lu:%lu]' definition for operating pb_type port '%s' is not valid!\n",
physical_pb_port.get_name().c_str(),
physical_pb_port.get_lsb(),
physical_pb_port.get_msb(),
operating_pb_port_name.c_str());
exit(1);
}
operating_pb_type_ports_[operating_pb_port_name][physical_pb_port][2] = physical_port_rotate_offset;
}
void PbTypeAnnotation::add_interconnect_circuit_model_pair(const std::string& interc_name,
const std::string& circuit_model_name) {
std::map<std::string, std::string>::const_iterator it = interconnect_circuit_model_names_.find(interc_name);

View File

@ -49,7 +49,7 @@ class PbTypeAnnotation {
float physical_pb_type_index_factor() const;
int physical_pb_type_index_offset() const;
std::vector<std::string> port_names() const;
std::map<BasicPort, std::array<int, 2>> physical_pb_type_port(const std::string& port_name) const;
std::map<BasicPort, std::array<int, 3>> physical_pb_type_port(const std::string& port_name) const;
std::vector<std::string> interconnect_names() const;
std::string interconnect_circuit_model_name(const std::string& interc_name) const;
public: /* Public mutators */
@ -73,6 +73,9 @@ class PbTypeAnnotation {
void set_physical_pin_rotate_offset(const std::string& operating_pb_port_name,
const BasicPort& physical_pb_port,
const int& physical_pin_rotate_offset);
void set_physical_port_rotate_offset(const std::string& operating_pb_port_name,
const BasicPort& physical_pb_port,
const int& physical_port_rotate_offset);
void add_interconnect_circuit_model_pair(const std::string& interc_name,
const std::string& circuit_model_name);
private: /* Internal data */
@ -138,10 +141,10 @@ class PbTypeAnnotation {
int physical_pb_type_index_offset_;
/* Link from the pins under an operating pb_type to pairs of
* its physical pb_type and its pin initial & rotating offset
*
* Note that initial offset is the first element of the std::array
* Note that rotating offset is the second element of the std::array
* its physical pb_type and
* - its pin initial offset: the first element of the std::array
* - pin-level rotating offset: the second element of the std::array
* - port-level rotating offset: the third element of the std::array
*
* The offsets aim to align the pin indices for port of pb_type
* between operating and physical modes, especially when an operating
@ -158,14 +161,21 @@ class PbTypeAnnotation {
* physical pb_type bram[0].dout_a[0] with a full path memory[physical].bram[0]
* physical pb_type bram[0].dout_a[1] with a full path memory[physical].bram[0]
*
* For example, a rotating offset of 9 is used to map
* For example, a pin-level rotating offset of 9 is used to map
* operating pb_type mult_9x9[0].a[0] with a full path mult[frac].mult_9x9[0]
* operating pb_type mult_9x9[0].a[1] with a full path mult[frac].mult_9x9[1]
* to
* physical pb_type mult_36x36.a[0] with a full path mult[physical].mult_36x36[0]
* physical pb_type mult_36x36.a[9] with a full path mult[physical].mult_36x36[0]
*
* For example, a port-level rotating offset of 9 is used to map
* operating pb_type mult_9x9[0].a[0:8] with a full path mult[frac].mult_9x9[0]
* operating pb_type mult_9x9[1].a[0:8] with a full path mult[frac].mult_9x9[1]
* to
* physical pb_type mult_36x36.a[0:8] with a full path mult[physical].mult_36x36[0]
* physical pb_type mult_36x36.a[9:17] with a full path mult[physical].mult_36x36[0]
*/
std::map<std::string, std::map<BasicPort, std::array<int, 2>>> operating_pb_type_ports_;
std::map<std::string, std::map<BasicPort, std::array<int, 3>>> operating_pb_type_ports_;
/* Link between the interconnects under this pb_type and circuit model names */
std::map<std::string, std::string> interconnect_circuit_model_names_;

View File

@ -50,6 +50,26 @@ void read_xml_bitstream_pb_type_setting(pugi::xml_node& xml_pb_type,
bitstream_setting.set_bitstream_offset(bitstream_pb_type_id, offset);
}
/********************************************************************
* Parse XML description for a pb_type annotation under a <interconect> XML node
*******************************************************************/
static
void read_xml_bitstream_interconnect_setting(pugi::xml_node& xml_pb_type,
const pugiutil::loc_data& loc_data,
openfpga::BitstreamSetting& bitstream_setting) {
const std::string& name_attr = get_attribute(xml_pb_type, "name", loc_data).as_string();
const std::string& default_path_attr = get_attribute(xml_pb_type, "default_path", loc_data).as_string();
/* Parse the attributes for operating pb_type */
openfpga::PbParser operating_pb_parser(name_attr);
/* Add to bitstream setting */
bitstream_setting.add_bitstream_interconnect_setting(operating_pb_parser.leaf(),
operating_pb_parser.parents(),
operating_pb_parser.modes(),
default_path_attr);
}
/********************************************************************
* Parse XML codes about <openfpga_bitstream_setting> to an object
*******************************************************************/
@ -60,12 +80,19 @@ openfpga::BitstreamSetting read_xml_bitstream_setting(pugi::xml_node& Node,
/* Iterate over the children under this node,
* each child should be named after <pb_type>
*/
for (pugi::xml_node xml_pb_type : Node.children()) {
for (pugi::xml_node xml_child : Node.children()) {
/* Error out if the XML child has an invalid name! */
if (xml_pb_type.name() != std::string("pb_type")) {
bad_tag(xml_pb_type, loc_data, Node, {"pb_type"});
if ( (xml_child.name() != std::string("pb_type"))
&& (xml_child.name() != std::string("interconnect")) ) {
bad_tag(xml_child, loc_data, Node, {"pb_type | interconnect"});
}
if (xml_child.name() == std::string("pb_type")) {
read_xml_bitstream_pb_type_setting(xml_child, loc_data, bitstream_setting);
} else {
VTR_ASSERT_SAFE(xml_child.name() == std::string("interconnect"));
read_xml_bitstream_interconnect_setting(xml_child, loc_data, bitstream_setting);
}
read_xml_bitstream_pb_type_setting(xml_pb_type, loc_data, bitstream_setting);
}
return bitstream_setting;

View File

@ -114,6 +114,31 @@ void read_xml_pb_port_annotation(pugi::xml_node& xml_port,
std::stoi(rotate_offsets[iport]));
}
}
/* We have an optional attribute: physical_mode_port_rotate_offset
* Split based on the number of physical pb_type ports that have been defined
*/
const std::string& physical_port_rotate_offset_attr = get_attribute(xml_port, "physical_mode_port_rotate_offset", loc_data, pugiutil::ReqOpt::OPTIONAL).as_string();
if (false == physical_port_rotate_offset_attr.empty()) {
/* Split the physical mode port attributes with space */
openfpga::StringToken offset_tokenizer(physical_port_rotate_offset_attr);
const std::vector<std::string> rotate_offsets = offset_tokenizer.split();
/* Error out if the offset does not match the port definition */
if (physical_mode_ports.size() != rotate_offsets.size()) {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_port),
"Defined %lu physical mode ports but only %lu physical port rotate offset are defined! Expect size matching.\n",
physical_mode_ports.size(), rotate_offsets.size());
}
for (size_t iport = 0; iport < physical_mode_ports.size(); ++iport) {
openfpga::PortParser port_parser(physical_mode_ports[iport]);
pb_type_annotation.set_physical_port_rotate_offset(name_attr,
port_parser.port(),
std::stoi(rotate_offsets[iport]));
}
}
}
/********************************************************************

View File

@ -39,6 +39,31 @@ std::string generate_bitstream_setting_pb_type_hierarchy_name(const openfpga::Bi
return hie_name;
}
/********************************************************************
* Generate the full hierarchy name for an interconnect in bitstream setting
*******************************************************************/
static
std::string generate_bitstream_setting_interconnect_hierarchy_name(const openfpga::BitstreamSetting& bitstream_setting,
const BitstreamInterconnectSettingId& bitstream_interc_setting_id) {
/* Iterate over the parent_pb_type and modes names, they should well match */
VTR_ASSERT_SAFE(bitstream_setting.parent_pb_type_names(bitstream_interc_setting_id).size() == bitstream_setting.parent_mode_names(bitstream_interc_setting_id).size());
std::string hie_name;
for (size_t i = 0 ; i < bitstream_setting.parent_pb_type_names(bitstream_interc_setting_id).size(); ++i) {
hie_name += bitstream_setting.parent_pb_type_names(bitstream_interc_setting_id)[i];
hie_name += std::string("[");
hie_name += bitstream_setting.parent_mode_names(bitstream_interc_setting_id)[i];
hie_name += std::string("]");
hie_name += std::string(".");
}
/* Add the leaf pb_type */
hie_name += bitstream_setting.interconnect_name(bitstream_interc_setting_id);
return hie_name;
}
/********************************************************************
* A writer to output a bitstream pb_type setting to XML format
*******************************************************************/
@ -63,6 +88,27 @@ void write_xml_bitstream_pb_type_setting(std::fstream& fp,
fp << "/>" << "\n";
}
/********************************************************************
* A writer to output a bitstream interconnect setting to XML format
*******************************************************************/
static
void write_xml_bitstream_interconnect_setting(std::fstream& fp,
const char* fname,
const openfpga::BitstreamSetting& bitstream_setting,
const BitstreamInterconnectSettingId& bitstream_interc_setting_id) {
/* Validate the file stream */
openfpga::check_file_stream(fname, fp);
fp << "\t" << "<pb_type";
/* Generate the full hierarchy name of the pb_type */
write_xml_attribute(fp, "name", generate_bitstream_setting_interconnect_hierarchy_name(bitstream_setting, bitstream_interc_setting_id).c_str());
write_xml_attribute(fp, "default_path", bitstream_setting.default_path(bitstream_interc_setting_id).c_str());
fp << "/>" << "\n";
}
/********************************************************************
* A writer to output a bitstream setting to XML format
*******************************************************************/
@ -76,11 +122,16 @@ void write_xml_bitstream_setting(std::fstream& fp,
*/
fp << "<openfpga_bitstream_setting>" << "\n";
/* Write clock settings */
/* Write pb_type -related settings */
for (const auto& bitstream_pb_type_setting_id : bitstream_setting.pb_type_settings()) {
write_xml_bitstream_pb_type_setting(fp, fname, bitstream_setting, bitstream_pb_type_setting_id);
}
/* Write interconnect -related settings */
for (const auto& bitstream_interc_setting_id : bitstream_setting.interconnect_settings()) {
write_xml_bitstream_interconnect_setting(fp, fname, bitstream_setting, bitstream_interc_setting_id);
}
/* Write the root node <openfpga_bitstream_setting> */
fp << "</openfpga_bitstream_setting>" << "\n";
}

View File

@ -144,7 +144,14 @@ void write_xml_pb_port_annotation(std::fstream& fp,
physical_mode_pin_rotate_offset_attr += std::to_string(physical_pb_port_pair.second[1]);
}
write_xml_attribute(fp, "physical_mode_pin_rotate_offset", physical_mode_pin_rotate_offset_attr.c_str());
std::string physical_mode_port_rotate_offset_attr;
for (const auto& physical_pb_port_pair : pb_type_annotation.physical_pb_type_port(port_name)) {
if (false == physical_mode_port_rotate_offset_attr.empty()) {
physical_mode_port_rotate_offset_attr += " ";
}
physical_mode_port_rotate_offset_attr += std::to_string(physical_pb_port_pair.second[2]);
}
write_xml_attribute(fp, "physical_mode_port_rotate_offset", physical_mode_port_rotate_offset_attr.c_str());
fp << "/>" << "\n";
}

View File

@ -71,5 +71,27 @@ size_t find_bitstream_manager_config_bit_index_in_parent_block(const BitstreamMa
return curr_index;
}
/********************************************************************
* Find the total number of configuration bits under a block
* As configuration bits are stored only under the leaf blocks,
* this function will recursively visit all the child blocks
* until reaching a leaf block, where we collect the number of bits
*******************************************************************/
size_t rec_find_bitstream_manager_block_sum_of_bits(const BitstreamManager& bitstream_manager,
const ConfigBlockId& block) {
/* For leaf block, return directly with the number of bits, because it has not child block */
if (0 < bitstream_manager.block_bits(block).size()) {
VTR_ASSERT_SAFE(bitstream_manager.block_children(block).empty());
return bitstream_manager.block_bits(block).size();
}
size_t sum_of_bits = 0;
/* Dive to child blocks if this block has any */
for (const ConfigBlockId& child_block : bitstream_manager.block_children(block)) {
sum_of_bits += rec_find_bitstream_manager_block_sum_of_bits(bitstream_manager, child_block);
}
return sum_of_bits;
}
} /* end namespace openfpga */

View File

@ -22,6 +22,9 @@ std::vector<ConfigBlockId> find_bitstream_manager_top_blocks(const BitstreamMana
size_t find_bitstream_manager_config_bit_index_in_parent_block(const BitstreamManager& bitstream_manager,
const ConfigBitId& bit_id);
size_t rec_find_bitstream_manager_block_sum_of_bits(const BitstreamManager& bitstream_manager,
const ConfigBlockId& block);
} /* end namespace openfpga */
#endif

View File

@ -0,0 +1,124 @@
/********************************************************************
* This file includes functions that report distribution of bitstream by blocks
*******************************************************************/
#include <chrono>
#include <ctime>
#include <fstream>
/* Headers from vtrutil library */
#include "vtr_assert.h"
#include "vtr_log.h"
#include "vtr_time.h"
/* Headers from openfpgautil library */
#include "openfpga_digest.h"
#include "openfpga_tokenizer.h"
#include "openfpga_version.h"
#include "openfpga_reserved_words.h"
#include "bitstream_manager_utils.h"
#include "report_arch_bitstream_distribution.h"
/* begin namespace openfpga */
namespace openfpga {
/********************************************************************
* This function write header information for an XML file of bitstream distribution
*******************************************************************/
static
void report_architecture_bitstream_distribution_xml_file_head(std::fstream& fp) {
valid_file_stream(fp);
auto end = std::chrono::system_clock::now();
std::time_t end_time = std::chrono::system_clock::to_time_t(end);
fp << "<!-- " << std::endl;
fp << "\t- Report Architecture Bitstream Distribution" << std::endl;
fp << "\t- Version: " << openfpga::VERSION << std::endl;
fp << "\t- Date: " << std::ctime(&end_time) ;
fp << "--> " << std::endl;
fp << std::endl;
}
/********************************************************************
* Recursively report the bitstream distribution of a block to a file
* This function will use a Depth-First Search in outputting bitstream
* for each block
* For block with child blocks, we visit each child recursively
* The reporting can be stopped at a given maximum hierarchy level
* which is used to limit the length of the report
*******************************************************************/
static
void rec_report_block_bitstream_distribution_to_xml_file(std::fstream& fp,
const BitstreamManager& bitstream_manager,
const ConfigBlockId& block,
const size_t& max_hierarchy_level,
const size_t& hierarchy_level) {
valid_file_stream(fp);
if (hierarchy_level > max_hierarchy_level) {
return;
}
/* Write the bitstream distribution of this block */
write_tab_to_file(fp, hierarchy_level);
fp << "<block";
fp << " name=\"" << bitstream_manager.block_name(block)<< "\"";
fp << " number_of_bits=\"" << rec_find_bitstream_manager_block_sum_of_bits(bitstream_manager, block) << "\"";
fp << ">" << std::endl;
/* Dive to child blocks if this block has any */
for (const ConfigBlockId& child_block : bitstream_manager.block_children(block)) {
rec_report_block_bitstream_distribution_to_xml_file(fp, bitstream_manager, child_block,
max_hierarchy_level, hierarchy_level + 1);
}
write_tab_to_file(fp, hierarchy_level);
fp << "</block>" <<std::endl;
}
/********************************************************************
* Report the distribution of bitstream by blocks, e.g., the number of
* configuration bits per SB/CB/CLB
* This function can generate a report to a file
*
* Notes:
* - The output format is a table whose format is compatible with RST files
*******************************************************************/
int report_architecture_bitstream_distribution(const BitstreamManager& bitstream_manager,
const std::string& fname,
const size_t& max_hierarchy_level) {
/* Ensure that we have a valid file name */
if (true == fname.empty()) {
VTR_LOG_ERROR("Received empty file name to report bitstream!\n\tPlease specify a valid file name.\n");
return 1;
}
std::string timer_message = std::string("Report architecture bitstream distribution into XML file '") + fname + std::string("'");
vtr::ScopedStartFinishTimer timer(timer_message);
/* Create the file stream */
std::fstream fp;
fp.open(fname, std::fstream::out | std::fstream::trunc);
check_file_stream(fname.c_str(), fp);
/* Put down a brief introduction */
report_architecture_bitstream_distribution_xml_file_head(fp);
/* Find the top block, which has not parents */
std::vector<ConfigBlockId> top_block = find_bitstream_manager_top_blocks(bitstream_manager);
/* Make sure we have only 1 top block */
VTR_ASSERT(1 == top_block.size());
/* Write bitstream, block by block, in a recursive way */
rec_report_block_bitstream_distribution_to_xml_file(fp, bitstream_manager, top_block[0], max_hierarchy_level, 0);
/* Close file handler */
fp.close();
return 0;
}
} /* end namespace openfpga */

View File

@ -0,0 +1,23 @@
#ifndef REPORT_ARCH_BITSTREAM_DISTRIBUTION_H
#define REPORT_ARCH_BITSTREAM_DISTRIBUTION_H
/********************************************************************
* Include header files that are required by function declaration
*******************************************************************/
#include <string>
#include "bitstream_manager.h"
/********************************************************************
* Function declaration
*******************************************************************/
/* begin namespace openfpga */
namespace openfpga {
int report_architecture_bitstream_distribution(const BitstreamManager& bitstream_manager,
const std::string& fname,
const size_t& max_hierarchy_level = 1);
} /* end namespace openfpga */
#endif

View File

@ -10,17 +10,18 @@
/* Headers from fabric key */
#include "read_xml_arch_bitstream.h"
#include "write_xml_arch_bitstream.h"
#include "report_arch_bitstream_distribution.h"
int main(int argc, const char** argv) {
/* Ensure we have only one or two argument */
VTR_ASSERT((2 == argc) || (3 == argc));
/* Ensure we have only one or two or 3 argument */
VTR_ASSERT((2 == argc) || (3 == argc) || (4 == argc));
/* Parse the bitstream from an XML file */
openfpga::BitstreamManager test_bitstream = openfpga::read_xml_architecture_bitstream(argv[1]);
VTR_LOG("Read the bitstream from an XML file: %s.\n",
argv[1]);
/* Output the circuit library to an XML file
/* Output the bitstream database to an XML file
* This is optional only used when there is a second argument
*/
if (3 <= argc) {
@ -28,6 +29,15 @@ int main(int argc, const char** argv) {
VTR_LOG("Echo the bitstream to an XML file: %s.\n",
argv[2]);
}
/* Output the bitstream distribution to an XML file
* This is optional only used when there is a third argument
*/
if (4 <= argc) {
openfpga::report_architecture_bitstream_distribution(test_bitstream, argv[3]);
VTR_LOG("Echo the bitstream distribution to an XML file: %s.\n",
argv[3]);
}
}

View File

@ -50,6 +50,20 @@ std::string RepackDesignConstraints::net(const RepackDesignConstraintId& repack_
return repack_design_constraint_nets_[repack_design_constraint_id];
}
std::string RepackDesignConstraints::find_constrained_pin_net(const std::string& pb_type,
const openfpga::BasicPort& pin) const {
std::string constrained_net_name;
for (const RepackDesignConstraintId& design_constraint : design_constraints()) {
/* If found a constraint, record the net name */
if ( (pb_type == repack_design_constraint_pb_types_[design_constraint])
&& (pin == repack_design_constraint_pins_[design_constraint])) {
constrained_net_name = repack_design_constraint_nets_[design_constraint];
break;
}
}
return constrained_net_name;
}
bool RepackDesignConstraints::empty() const {
return 0 == repack_design_constraint_ids_.size();
}
@ -106,3 +120,11 @@ void RepackDesignConstraints::set_net(const RepackDesignConstraintId& repack_des
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] );
}
bool RepackDesignConstraints::unconstrained_net(const std::string& net) const {
return net.empty();
}
bool RepackDesignConstraints::unmapped_net(const std::string& net) const {
return std::string(REPACK_DESIGN_CONSTRAINT_OPEN_NET) == net;
}

View File

@ -61,6 +61,10 @@ class RepackDesignConstraints {
/* Get the net to be constrained */
std::string net(const RepackDesignConstraintId& repack_design_constraint_id) const;
/* Find a constrained net */
std::string find_constrained_pin_net(const std::string& pb_type,
const openfpga::BasicPort& pin) const;
/* Check if there are any design constraints */
bool empty() const;
@ -86,6 +90,20 @@ class RepackDesignConstraints {
public: /* Public invalidators/validators */
bool valid_design_constraint_id(const RepackDesignConstraintId& repack_design_constraint_id) const;
/* Show if the net has no constraints (free to map to any pin)
* This function is used to identify the net name returned by APIs:
* - find_constrained_pin_net()
* - net()
*/
bool unconstrained_net(const std::string& net) const;
/* Show if the net is defined specifically not to map to any pin
* This function is used to identify the net name returned by APIs:
* - find_constrained_pin_net()
* - net()
*/
bool unmapped_net(const std::string& net) const;
private: /* Internal data */
/* Unique ids for each design constraint */
vtr::vector<RepackDesignConstraintId, RepackDesignConstraintId> repack_design_constraint_ids_;

View File

@ -12,6 +12,9 @@
#include "vtr_assert.h"
#include "vtr_log.h"
/* Headers from openfpgautil library */
#include "openfpga_tokenizer.h"
#include "pb_type_utils.h"
#include "annotate_bitstream_setting.h"
@ -23,9 +26,10 @@ namespace openfpga {
* - Find the pb_type and link to the bitstream source
* - Find the pb_type and link to the bitstream content
*******************************************************************/
int annotate_bitstream_setting(const BitstreamSetting& bitstream_setting,
const DeviceContext& vpr_device_ctx,
VprBitstreamAnnotation& vpr_bitstream_annotation) {
static
int annotate_bitstream_pb_type_setting(const BitstreamSetting& bitstream_setting,
const DeviceContext& vpr_device_ctx,
VprBitstreamAnnotation& vpr_bitstream_annotation) {
for (const auto& bitstream_pb_type_setting_id : bitstream_setting.pb_type_settings()) {
/* Get the full name of pb_type */
@ -95,4 +99,135 @@ int annotate_bitstream_setting(const BitstreamSetting& bitstream_setting,
return CMD_EXEC_SUCCESS;
}
/********************************************************************
* Annotate bitstream setting based on VPR device information
* - Find the interconnect and link to the default path id
*******************************************************************/
static
int annotate_bitstream_interconnect_setting(const BitstreamSetting& bitstream_setting,
const DeviceContext& vpr_device_ctx,
const VprDeviceAnnotation& vpr_device_annotation,
VprBitstreamAnnotation& vpr_bitstream_annotation) {
for (const auto& bitstream_interc_setting_id : bitstream_setting.interconnect_settings()) {
/* Get the full name of pb_type */
std::vector<std::string> target_pb_type_names;
std::vector<std::string> target_pb_mode_names;
target_pb_type_names = bitstream_setting.parent_pb_type_names(bitstream_interc_setting_id);
target_pb_mode_names = bitstream_setting.parent_mode_names(bitstream_interc_setting_id);
/* Kick out the last mode so that we can use an existing function search the pb_type in graph */
std::string expected_physical_mode_name = target_pb_mode_names.back();
target_pb_mode_names.pop_back();
std::string interconnect_name = bitstream_setting.interconnect_name(bitstream_interc_setting_id);
std::string expected_input_path = bitstream_setting.default_path(bitstream_interc_setting_id);
/* Pb type information are located at the logic_block_types in the device context of VPR
* We iterate over the vectors and find the pb_type matches the parent_pb_type_name
*/
bool link_success = false;
for (const t_logical_block_type& lb_type : vpr_device_ctx.logical_block_types) {
/* By pass nullptr for pb_type head */
if (nullptr == lb_type.pb_type) {
continue;
}
/* Check the name of the top-level pb_type, if it does not match, we can bypass */
if (target_pb_type_names[0] != std::string(lb_type.pb_type->name)) {
continue;
}
/* Match the name in the top-level, we go further to search the pb_type in the graph */
t_pb_type* target_pb_type = try_find_pb_type_with_given_path(lb_type.pb_type, target_pb_type_names,
target_pb_mode_names);
if (nullptr == target_pb_type) {
continue;
}
/* Found one, build annotation */
t_mode* physical_mode = vpr_device_annotation.physical_mode(target_pb_type);
VTR_ASSERT(nullptr != physical_mode);
/* Ensure that the annotation is only applicable to physical mode */
if (std::string(physical_mode->name) != expected_physical_mode_name) {
VTR_LOG_ERROR("The physical mode '%s' under pb_type '%s' does not match in the bitstream setting '%s'!\n",
physical_mode->name,
target_pb_type->name,
expected_physical_mode_name.c_str());
return CMD_EXEC_FATAL_ERROR;
}
/* Find the interconnect name under the physical mode of a physical pb_type */
t_interconnect* pb_interc = find_pb_mode_interconnect(physical_mode, interconnect_name.c_str());
if (nullptr == pb_interc) {
VTR_LOG_ERROR("Unable to find interconnect '%s' under physical mode '%s' of pb_type '%s'!\n",
interconnect_name.c_str(),
physical_mode->name,
target_pb_type->name);
return CMD_EXEC_FATAL_ERROR;
}
/* Find the default path and spot the path id from the input string recorded */
StringToken input_string_tokenizer(std::string(pb_interc->input_string));
std::vector<std::string> input_paths = input_string_tokenizer.split(' ');
size_t input_path_id = input_paths.size();
for (size_t ipath = 0; ipath < input_paths.size(); ++ipath) {
if (expected_input_path == input_paths[ipath]) {
input_path_id = ipath;
break;
}
}
/* If the input_path id is invalid, error out! */
if (input_path_id == input_paths.size()) {
VTR_LOG_ERROR("Invalid default path '%s' for interconnect '%s' which inputs are '%s'\n",
expected_input_path.c_str(),
interconnect_name.c_str(),
pb_interc->input_string);
return CMD_EXEC_FATAL_ERROR;
}
vpr_bitstream_annotation.set_interconnect_default_path_id(pb_interc, input_path_id);
link_success = true;
}
/* If fail to link bitstream setting to architecture, error out immediately */
if (false == link_success) {
VTR_LOG_ERROR("Fail to find an interconnect '%s' with default path '%s', which is defined in bitstream setting from VPR architecture description\n",
interconnect_name.c_str(),
expected_input_path.c_str());
return CMD_EXEC_FATAL_ERROR;
}
}
return CMD_EXEC_SUCCESS;
}
/********************************************************************
* Annotate bitstream setting based on VPR device information
* - Fill pb_type -related mapping
* - Fill interconnect -related mapping
*******************************************************************/
int annotate_bitstream_setting(const BitstreamSetting& bitstream_setting,
const DeviceContext& vpr_device_ctx,
const VprDeviceAnnotation& vpr_device_annotation,
VprBitstreamAnnotation& vpr_bitstream_annotation) {
int status = CMD_EXEC_SUCCESS;
status = annotate_bitstream_pb_type_setting(bitstream_setting,
vpr_device_ctx,
vpr_bitstream_annotation);
if (status == CMD_EXEC_FATAL_ERROR) {
return status;
}
status = annotate_bitstream_interconnect_setting(bitstream_setting,
vpr_device_ctx, vpr_device_annotation,
vpr_bitstream_annotation);
return status;
}
} /* end namespace openfpga */

View File

@ -16,6 +16,7 @@ namespace openfpga {
int annotate_bitstream_setting(const BitstreamSetting& bitstream_setting,
const DeviceContext& vpr_device_ctx,
const VprDeviceAnnotation& vpr_device_annotation,
VprBitstreamAnnotation& vpr_bitstream_annotation);
} /* end namespace openfpga */

View File

@ -333,7 +333,7 @@ bool try_match_pb_graph_pin(t_pb_graph_pin* operating_pb_graph_pin,
* by the pin rotate offset value
* The accumulated offset will be reset to 0 when it exceeds the msb() of the physical port
*/
int acc_offset = vpr_device_annotation.physical_pb_pin_offset(operating_pb_graph_pin->port, candidate_port);
int acc_offset = vpr_device_annotation.physical_pb_pin_offset(operating_pb_graph_pin->port, candidate_port) + vpr_device_annotation.physical_pb_port_offset(operating_pb_graph_pin->port, candidate_port);
int init_offset = vpr_device_annotation.physical_pb_pin_initial_offset(operating_pb_graph_pin->port, candidate_port);
const BasicPort& physical_port_range = vpr_device_annotation.physical_pb_port_range(operating_pb_graph_pin->port, candidate_port);
if (physical_pb_graph_pin->pin_number != operating_pb_graph_pin->pin_number
@ -463,6 +463,14 @@ void annotate_physical_pb_graph_node_pins(t_pb_graph_node* operating_pb_graph_no
physical_pb_graph_node, vpr_device_annotation,
verbose_output);
}
/* Finish a port, accumulate the port-level offset affiliated to the port */
if (0 == operating_pb_graph_node->num_input_pins[iport]) {
continue;
}
t_pb_graph_pin* operating_pb_graph_pin = &(operating_pb_graph_node->input_pins[iport][0]);
for (t_port* candidate_port : vpr_device_annotation.physical_pb_port(operating_pb_graph_pin->port)) {
vpr_device_annotation.accumulate_physical_pb_port_rotate_offset(operating_pb_graph_pin->port, candidate_port);
}
}
for (int iport = 0; iport < operating_pb_graph_node->num_output_ports; ++iport) {
@ -471,6 +479,14 @@ void annotate_physical_pb_graph_node_pins(t_pb_graph_node* operating_pb_graph_no
physical_pb_graph_node, vpr_device_annotation,
verbose_output);
}
/* Finish a port, accumulate the port-level offset affiliated to the port */
if (0 == operating_pb_graph_node->num_output_pins[iport]) {
continue;
}
t_pb_graph_pin* operating_pb_graph_pin = &(operating_pb_graph_node->output_pins[iport][0]);
for (t_port* candidate_port : vpr_device_annotation.physical_pb_port(operating_pb_graph_pin->port)) {
vpr_device_annotation.accumulate_physical_pb_port_rotate_offset(operating_pb_graph_pin->port, candidate_port);
}
}
for (int iport = 0; iport < operating_pb_graph_node->num_clock_ports; ++iport) {
@ -479,6 +495,14 @@ void annotate_physical_pb_graph_node_pins(t_pb_graph_node* operating_pb_graph_no
physical_pb_graph_node, vpr_device_annotation,
verbose_output);
}
/* Finish a port, accumulate the port-level offset affiliated to the port */
if (0 == operating_pb_graph_node->num_clock_pins[iport]) {
continue;
}
t_pb_graph_pin* operating_pb_graph_pin = &(operating_pb_graph_node->clock_pins[iport][0]);
for (t_port* candidate_port : vpr_device_annotation.physical_pb_port(operating_pb_graph_pin->port)) {
vpr_device_annotation.accumulate_physical_pb_port_rotate_offset(operating_pb_graph_pin->port, candidate_port);
}
}
}

View File

@ -211,7 +211,7 @@ bool pair_operating_and_physical_pb_types(t_pb_type* operating_pb_type,
* if not found, we assume that the physical port is the same as the operating pb_port
*/
for (t_port* operating_pb_port : pb_type_ports(operating_pb_type)) {
std::map<BasicPort, std::array<int, 2>> expected_physical_pb_ports = pb_type_annotation.physical_pb_type_port(std::string(operating_pb_port->name));
std::map<BasicPort, std::array<int, 3>> expected_physical_pb_ports = pb_type_annotation.physical_pb_type_port(std::string(operating_pb_port->name));
/* If not defined in the annotation, set the default pair:
* rotate_offset is 0 by default!
@ -243,6 +243,7 @@ bool pair_operating_and_physical_pb_types(t_pb_type* operating_pb_type,
vpr_device_annotation.add_physical_pb_port_range(operating_pb_port, physical_pb_port, expected_physical_pb_port.first);
vpr_device_annotation.add_physical_pb_pin_initial_offset(operating_pb_port, physical_pb_port, expected_physical_pb_port.second[0]);
vpr_device_annotation.add_physical_pb_pin_rotate_offset(operating_pb_port, physical_pb_port, expected_physical_pb_port.second[1]);
vpr_device_annotation.add_physical_pb_port_rotate_offset(operating_pb_port, physical_pb_port, expected_physical_pb_port.second[2]);
}
}

View File

@ -4,6 +4,7 @@
#include "vtr_log.h"
#include "vtr_assert.h"
#include "vpr_bitstream_annotation.h"
#include "mux_bitstream_constants.h"
/* namespace openfpga begins */
namespace openfpga {
@ -78,6 +79,16 @@ size_t VprBitstreamAnnotation::pb_type_mode_select_bitstream_offset(t_pb_type* p
return 0;
}
size_t VprBitstreamAnnotation::interconnect_default_path_id(t_interconnect* interconnect) const {
auto result = interconnect_default_path_ids_.find(interconnect);
if (result != interconnect_default_path_ids_.end()) {
return result->second;
}
/* Not found, return an invalid input id */
return DEFAULT_PATH_ID;
}
/************************************************************************
* Public mutators
***********************************************************************/
@ -111,4 +122,9 @@ void VprBitstreamAnnotation::set_pb_type_mode_select_bitstream_offset(t_pb_type*
mode_select_bitstream_offsets_[pb_type] = offset;
}
void VprBitstreamAnnotation::set_interconnect_default_path_id(t_interconnect* interconnect,
const size_t& default_path_id) {
interconnect_default_path_ids_[interconnect] = default_path_id;
}
} /* End namespace openfpga*/

View File

@ -38,6 +38,7 @@ class VprBitstreamAnnotation {
e_bitstream_source_type pb_type_mode_select_bitstream_source(t_pb_type* pb_type) const;
std::string pb_type_mode_select_bitstream_content(t_pb_type* pb_type) const;
size_t pb_type_mode_select_bitstream_offset(t_pb_type* pb_type) const;
size_t interconnect_default_path_id(t_interconnect* interconnect) const;
public: /* Public mutators */
void set_pb_type_bitstream_source(t_pb_type* pb_type,
const e_bitstream_source_type& bitstream_source);
@ -52,6 +53,8 @@ class VprBitstreamAnnotation {
const std::string& bitstream_content);
void set_pb_type_mode_select_bitstream_offset(t_pb_type* pb_type,
const size_t& offset);
void set_interconnect_default_path_id(t_interconnect* interconnect,
const size_t& default_path_id);
private: /* Internal data */
/* For regular bitstreams */
/* A look up for pb type to find bitstream source type */
@ -68,6 +71,12 @@ class VprBitstreamAnnotation {
std::map<t_pb_type*, std::string> mode_select_bitstream_contents_;
/* Offset to be applied to mode-select bitstream */
std::map<t_pb_type*, size_t> mode_select_bitstream_offsets_;
/* A look up for interconnect to find default path indices
* Note: this is different from the default path in bitstream setting which is the index
* of inputs in the context of the interconnect input string
*/
std::map<t_interconnect*, size_t> interconnect_default_path_ids_;
};
} /* End namespace openfpga*/

View File

@ -220,6 +220,21 @@ int VprDeviceAnnotation::physical_pb_pin_rotate_offset(t_port* operating_pb_port
return physical_pb_pin_rotate_offsets_.at(operating_pb_port).at(physical_pb_port);
}
int VprDeviceAnnotation::physical_pb_port_rotate_offset(t_port* operating_pb_port,
t_port* physical_pb_port) const {
/* Ensure that the pb_type is in the list */
std::map<t_port*, std::map<t_port*, int>>::const_iterator it = physical_pb_port_rotate_offsets_.find(operating_pb_port);
if (it == physical_pb_port_rotate_offsets_.end()) {
/* Default value is 0 */
return 0;
}
if (0 == physical_pb_port_rotate_offsets_.at(operating_pb_port).count(physical_pb_port)) {
/* Default value is 0 */
return 0;
}
return physical_pb_port_rotate_offsets_.at(operating_pb_port).at(physical_pb_port);
}
int VprDeviceAnnotation::physical_pb_pin_offset(t_port* operating_pb_port,
t_port* physical_pb_port) const {
/* Ensure that the pb_type is in the list */
@ -235,6 +250,21 @@ int VprDeviceAnnotation::physical_pb_pin_offset(t_port* operating_pb_port,
return physical_pb_pin_offsets_.at(operating_pb_port).at(physical_pb_port);
}
int VprDeviceAnnotation::physical_pb_port_offset(t_port* operating_pb_port,
t_port* physical_pb_port) const {
/* Ensure that the pb_type is in the list */
std::map<t_port*, std::map<t_port*, int>>::const_iterator it = physical_pb_port_offsets_.find(operating_pb_port);
if (it == physical_pb_port_offsets_.end()) {
/* Default value is 0 */
return 0;
}
if (0 == physical_pb_port_offsets_.at(operating_pb_port).count(physical_pb_port)) {
/* Default value is 0 */
return 0;
}
return physical_pb_port_offsets_.at(operating_pb_port).at(physical_pb_port);
}
t_pb_graph_pin* VprDeviceAnnotation::physical_pb_graph_pin(const t_pb_graph_pin* pb_graph_pin) const {
/* Ensure that the pb_type is in the list */
std::map<const t_pb_graph_pin*, t_pb_graph_pin*>::const_iterator it = physical_pb_graph_pins_.find(pb_graph_pin);
@ -478,6 +508,28 @@ void VprDeviceAnnotation::add_physical_pb_pin_initial_offset(t_port* operating_p
physical_pb_pin_initial_offsets_[operating_pb_port][physical_pb_port] = offset;
}
void VprDeviceAnnotation::add_physical_pb_port_rotate_offset(t_port* operating_pb_port,
t_port* physical_pb_port,
const int& offset) {
/* Warn any override attempt */
std::map<t_port*, std::map<t_port*, int>>::const_iterator it = physical_pb_port_rotate_offsets_.find(operating_pb_port);
if ( (it != physical_pb_port_rotate_offsets_.end())
&& (0 < physical_pb_port_rotate_offsets_[operating_pb_port].count(physical_pb_port)) ) {
VTR_LOG_WARN("Override the annotation between operating pb_port '%s' and it physical pb_port '%s' port rotate offset '%d'!\n",
operating_pb_port->name, offset);
}
physical_pb_port_rotate_offsets_[operating_pb_port][physical_pb_port] = offset;
/* We initialize the accumulated offset to 0 */
physical_pb_port_offsets_[operating_pb_port][physical_pb_port] = 0;
}
void VprDeviceAnnotation::accumulate_physical_pb_port_rotate_offset(t_port* operating_pb_port,
t_port* physical_pb_port) {
physical_pb_port_offsets_[operating_pb_port][physical_pb_port] += physical_pb_port_rotate_offsets_[operating_pb_port][physical_pb_port];
}
void VprDeviceAnnotation::add_physical_pb_pin_rotate_offset(t_port* operating_pb_port,
t_port* physical_pb_port,
const int& offset) {

View File

@ -67,6 +67,9 @@ class VprDeviceAnnotation {
int physical_pb_pin_rotate_offset(t_port* operating_pb_port,
t_port* physical_pb_port) const;
int physical_pb_port_rotate_offset(t_port* operating_pb_port,
t_port* physical_pb_port) const;
/**This function returns an accumulated offset. Note that the
* accumulated offset is NOT the pin rotate offset specified by users
* It is an aggregation of the offset during pin pairing
@ -76,6 +79,8 @@ class VprDeviceAnnotation {
*/
int physical_pb_pin_offset(t_port* operating_pb_port,
t_port* physical_pb_port) const;
int physical_pb_port_offset(t_port* operating_pb_port,
t_port* physical_pb_port) const;
t_pb_graph_pin* physical_pb_graph_pin(const t_pb_graph_pin* pb_graph_pin) const;
CircuitModelId rr_switch_circuit_model(const RRSwitchId& rr_switch) const;
CircuitModelId rr_segment_circuit_model(const RRSegmentId& rr_segment) const;
@ -106,6 +111,11 @@ class VprDeviceAnnotation {
void add_physical_pb_pin_initial_offset(t_port* operating_pb_port,
t_port* physical_pb_port,
const int& offset);
void add_physical_pb_port_rotate_offset(t_port* operating_pb_port,
t_port* physical_pb_port,
const int& offset);
void accumulate_physical_pb_port_rotate_offset(t_port* operating_pb_port,
t_port* physical_pb_port);
void add_physical_pb_pin_rotate_offset(t_port* operating_pb_port,
t_port* physical_pb_port,
const int& offset);
@ -166,8 +176,11 @@ class VprDeviceAnnotation {
std::map<t_port*, std::vector<t_port*>> physical_pb_ports_;
std::map<t_port*, std::map<t_port*, int>> physical_pb_pin_initial_offsets_;
std::map<t_port*, std::map<t_port*, int>> physical_pb_pin_rotate_offsets_;
std::map<t_port*, std::map<t_port*, int>> physical_pb_port_rotate_offsets_;
/* Accumulated offsets for a physical pb_type port, just for internal usage */
/* Accumulated offsets for a physical pb port, just for internal usage */
std::map<t_port*, std::map<t_port*, int>> physical_pb_port_offsets_;
/* Accumulated offsets for a physical pb_graph_pin, just for internal usage */
std::map<t_port*, std::map<t_port*, int>> physical_pb_pin_offsets_;
/* Pair a pb_port to its LSB and MSB of a physical pb_port

View File

@ -0,0 +1,54 @@
/******************************************************************************
* Memember functions for data structure IoMap
******************************************************************************/
#include "vtr_assert.h"
#include "io_map.h"
/* begin namespace openfpga */
namespace openfpga {
IoMap::io_map_range IoMap::io_map() const {
return vtr::make_range(io_map_ids_.begin(), io_map_ids_.end());
}
BasicPort IoMap::io_port(IoMapId io_map_id) const {
VTR_ASSERT(valid_io_map_id(io_map_id));
return io_ports_[io_map_id];
}
BasicPort IoMap::io_net(IoMapId io_map_id) const {
VTR_ASSERT(valid_io_map_id(io_map_id));
return mapped_nets_[io_map_id];
}
bool IoMap::is_io_output(IoMapId io_map_id) const {
VTR_ASSERT(valid_io_map_id(io_map_id));
return IoMap::IO_MAP_DIR_OUTPUT == io_directionality_[io_map_id];
}
bool IoMap::is_io_input(IoMapId io_map_id) const {
VTR_ASSERT(valid_io_map_id(io_map_id));
return IoMap::IO_MAP_DIR_INPUT == io_directionality_[io_map_id];
}
IoMapId IoMap::create_io_mapping(const BasicPort& port,
const BasicPort& net,
IoMap::e_direction dir) {
/* Create a new id */
IoMapId io_map_id = IoMapId(io_map_ids_.size());
io_map_ids_.push_back(io_map_id);
/* Allocate related attributes */
io_ports_.push_back(port);
mapped_nets_.push_back(net);
io_directionality_.push_back(dir);
return io_map_id;
}
bool IoMap::valid_io_map_id(IoMapId io_map_id) const {
return (size_t(io_map_id) < io_map_ids_.size()) && (io_map_id == io_map_ids_[io_map_id]);
}
} /* end namespace openfpga */

View File

@ -0,0 +1,59 @@
#ifndef IO_MAP_H
#define IO_MAP_H
/********************************************************************
* Include header files required by the data structure definition
*******************************************************************/
#include "vtr_vector.h"
#include "openfpga_port.h"
#include "io_map_fwd.h"
/* Begin namespace openfpga */
namespace openfpga {
/********************************************************************
* This is a data structure storing io mapping information
* - the net-to-I/O mapping
* - each I/O directionality
*******************************************************************/
class IoMap {
public: /* Types and ranges */
enum e_direction {
IO_MAP_DIR_INPUT,
IO_MAP_DIR_OUTPUT,
NUM_IO_MAP_DIR_TYPES
};
typedef vtr::vector<IoMapId, IoMapId>::const_iterator io_map_iterator;
typedef vtr::Range<io_map_iterator> io_map_range;
public: /* Public aggregators */
/* Find all io mapping */
io_map_range io_map() const;
/* Get the port of the io that is mapped */
BasicPort io_port(IoMapId io_map_id) const;
/* Get the net of the io that is mapped to */
BasicPort io_net(IoMapId io_map_id) const;
/* Query on if an io is configured as an input */
bool is_io_input(IoMapId io_map_id) const;
/* Query on if an io is configured as an output */
bool is_io_output(IoMapId io_map_id) const;
public: /* Public mutators */
/* Create a new I/O mapping */
IoMapId create_io_mapping(const BasicPort& port,
const BasicPort& net,
e_direction dir);
public: /* Public validators/invalidators */
bool valid_io_map_id(IoMapId io_map_id) const;
private: /* Internal Data */
vtr::vector<IoMapId, IoMapId> io_map_ids_;
vtr::vector<IoMapId, BasicPort> io_ports_;
vtr::vector<IoMapId, BasicPort> mapped_nets_;
vtr::vector<IoMapId, e_direction> io_directionality_;
};
} /* End namespace openfpga*/
#endif

View File

@ -0,0 +1,23 @@
/**************************************************
* This file includes only declarations for
* the data structures for IoMap
* Please refer to io_map.h for more details
*************************************************/
#ifndef IO_MAP_FWD_H
#define IO_MAP_FWD_H
#include "vtr_strong_id.h"
/* begin namespace openfpga */
namespace openfpga {
/* Strong Ids */
struct io_map_id_tag;
typedef vtr::StrongId<io_map_id_tag> IoMapId;
class IoMap;
} /* end namespace openfpga */
#endif

View File

@ -14,11 +14,16 @@
/* Headers from fpgabitstream library */
#include "read_xml_arch_bitstream.h"
#include "write_xml_arch_bitstream.h"
#include "report_arch_bitstream_distribution.h"
#include "openfpga_naming.h"
#include "build_device_bitstream.h"
#include "write_text_fabric_bitstream.h"
#include "write_xml_fabric_bitstream.h"
#include "build_fabric_bitstream.h"
#include "build_io_mapping_info.h"
#include "write_xml_io_mapping.h"
#include "openfpga_bitstream.h"
/* Include global variables of VPR */
@ -86,6 +91,7 @@ int write_fabric_bitstream(const OpenfpgaContext& openfpga_ctx,
CommandOptionId opt_verbose = cmd.option("verbose");
CommandOptionId opt_file = cmd.option("file");
CommandOptionId opt_file_format = cmd.option("format");
CommandOptionId opt_fast_config = cmd.option("fast_configuration");
/* Write fabric bitstream if required */
int status = CMD_EXEC_SUCCESS;
@ -114,11 +120,90 @@ int write_fabric_bitstream(const OpenfpgaContext& openfpga_ctx,
status = write_fabric_bitstream_to_text_file(openfpga_ctx.bitstream_manager(),
openfpga_ctx.fabric_bitstream(),
openfpga_ctx.arch().config_protocol,
openfpga_ctx.fabric_global_port_info(),
cmd_context.option_value(cmd, opt_file),
cmd_context.option_enable(cmd, opt_fast_config),
cmd_context.option_enable(cmd, opt_verbose));
}
return status;
}
/********************************************************************
* A wrapper function to call the write_io_mapping() in FPGA bitstream
*******************************************************************/
int write_io_mapping(const OpenfpgaContext& openfpga_ctx,
const Command& cmd, const CommandContext& cmd_context) {
CommandOptionId opt_verbose = cmd.option("verbose");
CommandOptionId opt_file = cmd.option("file");
/* Write fabric bitstream if required */
int status = CMD_EXEC_SUCCESS;
VTR_ASSERT(true == cmd_context.option_enable(cmd, opt_file));
std::string src_dir_path = find_path_dir_name(cmd_context.option_value(cmd, opt_file));
/* Create directories */
create_directory(src_dir_path);
/* Create a module as the top-level fabric, and add it to the module manager */
std::string top_module_name = generate_fpga_top_module_name();
ModuleId top_module = openfpga_ctx.module_graph().find_module(top_module_name);
VTR_ASSERT(true == openfpga_ctx.module_graph().valid_module_id(top_module));
IoMap io_map = build_fpga_io_mapping_info(openfpga_ctx.module_graph(),
top_module,
g_vpr_ctx.atom(),
g_vpr_ctx.placement(),
openfpga_ctx.io_location_map(),
openfpga_ctx.vpr_netlist_annotation(),
std::string(),
std::string());
status = write_io_mapping_to_xml_file(io_map,
cmd_context.option_value(cmd, opt_file),
cmd_context.option_enable(cmd, opt_verbose));
return status;
}
/********************************************************************
* A wrapper function to call the report_arch_bitstream_distribution() in FPGA bitstream
*******************************************************************/
int report_bitstream_distribution(const OpenfpgaContext& openfpga_ctx,
const Command& cmd, const CommandContext& cmd_context) {
CommandOptionId opt_file = cmd.option("file");
int status = CMD_EXEC_SUCCESS;
VTR_ASSERT(true == cmd_context.option_enable(cmd, opt_file));
std::string src_dir_path = find_path_dir_name(cmd_context.option_value(cmd, opt_file));
/* Create directories */
create_directory(src_dir_path);
/* Default depth requirement, this is to limit the report size by default */
int depth = 1;
CommandOptionId opt_depth = cmd.option("depth");
if (true == cmd_context.option_enable(cmd, opt_depth)) {
depth = std::atoi(cmd_context.option_value(cmd, opt_depth).c_str());
/* Error out if we have negative depth */
if (0 > depth) {
VTR_LOG_ERROR("Invalid depth '%d' which should be 0 or a positive number!\n",
depth);
return CMD_EXEC_FATAL_ERROR;
}
}
status = report_architecture_bitstream_distribution(openfpga_ctx.bitstream_manager(),
cmd_context.option_value(cmd, opt_file),
depth);
return status;
}
} /* end namespace openfpga */

View File

@ -24,6 +24,12 @@ int build_fabric_bitstream(OpenfpgaContext& openfpga_ctx,
int write_fabric_bitstream(const OpenfpgaContext& openfpga_ctx,
const Command& cmd, const CommandContext& cmd_context);
int write_io_mapping(const OpenfpgaContext& openfpga_ctx,
const Command& cmd, const CommandContext& cmd_context);
int report_bitstream_distribution(const OpenfpgaContext& openfpga_ctx,
const Command& cmd, const CommandContext& cmd_context);
} /* end namespace openfpga */
#endif

View File

@ -72,6 +72,40 @@ ShellCommandId add_openfpga_build_arch_bitstream_command(openfpga::Shell<Openfpg
return shell_cmd_id;
}
/********************************************************************
* - Add a command to Shell environment: report_bitstream_distribution
* - Add associated options
* - Add command dependency
*******************************************************************/
static
ShellCommandId add_openfpga_report_bitstream_distribution_command(openfpga::Shell<OpenfpgaContext>& shell,
const ShellCommandClassId& cmd_class_id,
const std::vector<ShellCommandId>& dependent_cmds) {
Command shell_cmd("report_bitstream_distribution");
/* Add an option '--file' */
CommandOptionId opt_file = shell_cmd.add_option("file", true, "file path to output the bitstream distribution");
shell_cmd.set_option_short_name(opt_file, "f");
shell_cmd.set_option_require_value(opt_file, openfpga::OPT_STRING);
/* Add an option '--depth' */
CommandOptionId opt_depth = shell_cmd.add_option("depth", false, "Specify the max. depth of blocks which will appear in report");
shell_cmd.set_option_require_value(opt_depth, openfpga::OPT_STRING);
/* Add an option '--verbose' */
shell_cmd.add_option("verbose", false, "Enable verbose output");
/* Add command 'report_bitstream_distribution' to the Shell */
ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "Report bitstream distribution");
shell.set_command_class(shell_cmd_id, cmd_class_id);
shell.set_command_execute_function(shell_cmd_id, report_bitstream_distribution);
/* Add command dependency to the Shell */
shell.set_command_dependency(shell_cmd_id, dependent_cmds);
return shell_cmd_id;
}
/********************************************************************
* - Add a command to Shell environment: build_fabric_bitstream
* - Add associated options
@ -117,6 +151,9 @@ ShellCommandId add_openfpga_write_fabric_bitstream_command(openfpga::Shell<Openf
CommandOptionId opt_file_format = shell_cmd.add_option("format", false, "file format of fabric bitstream [plain_text|xml]. Default: plain_text");
shell_cmd.set_option_require_value(opt_file_format, openfpga::OPT_STRING);
/* Add an option '--fast_configuration' */
shell_cmd.add_option("fast_configuration", false, "Reduce the size of bitstream to be downloaded");
/* Add an option '--verbose' */
shell_cmd.add_option("verbose", false, "Enable verbose output");
@ -131,6 +168,36 @@ ShellCommandId add_openfpga_write_fabric_bitstream_command(openfpga::Shell<Openf
return shell_cmd_id;
}
/********************************************************************
* - Add a command to Shell environment: write_io_mapping
* - Add associated options
* - Add command dependency
*******************************************************************/
static
ShellCommandId add_openfpga_write_io_mapping_command(openfpga::Shell<OpenfpgaContext>& shell,
const ShellCommandClassId& cmd_class_id,
const std::vector<ShellCommandId>& dependent_cmds) {
Command shell_cmd("write_io_mapping");
/* Add an option '--file' in short '-f'*/
CommandOptionId opt_file = shell_cmd.add_option("file", true, "file path to output the io mapping information");
shell_cmd.set_option_short_name(opt_file, "f");
shell_cmd.set_option_require_value(opt_file, openfpga::OPT_STRING);
/* Add an option '--verbose' */
shell_cmd.add_option("verbose", false, "Enable verbose output");
/* Add command 'fabric_bitstream' to the Shell */
ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "Write the I/O mapping information to a file");
shell.set_command_class(shell_cmd_id, cmd_class_id);
shell.set_command_execute_function(shell_cmd_id, write_io_mapping);
/* Add command dependency to the Shell */
shell.set_command_dependency(shell_cmd_id, dependent_cmds);
return shell_cmd_id;
}
/********************************************************************
* Top-level function to add all the commands related to FPGA-Bitstream
*******************************************************************/
@ -157,6 +224,14 @@ void add_openfpga_bitstream_commands(openfpga::Shell<OpenfpgaContext>& shell) {
cmd_dependency_build_arch_bitstream.push_back(shell_cmd_repack_id);
ShellCommandId shell_cmd_build_arch_bitstream_id = add_openfpga_build_arch_bitstream_command(shell, openfpga_bitstream_cmd_class, cmd_dependency_build_arch_bitstream);
/********************************
* Command 'report_bitstream_distribution'
*/
/* The 'report_bitstream_distribution' command should NOT be executed before 'build_architecture_bitstream' */
std::vector<ShellCommandId> cmd_dependency_report_bitstream_distribution;
cmd_dependency_build_arch_bitstream.push_back(shell_cmd_build_arch_bitstream_id);
add_openfpga_report_bitstream_distribution_command(shell, openfpga_bitstream_cmd_class, cmd_dependency_report_bitstream_distribution);
/********************************
* Command 'build_fabric_bitstream'
*/
@ -172,6 +247,14 @@ void add_openfpga_bitstream_commands(openfpga::Shell<OpenfpgaContext>& shell) {
std::vector<ShellCommandId> cmd_dependency_write_fabric_bitstream;
cmd_dependency_write_fabric_bitstream.push_back(shell_cmd_build_fabric_bitstream_id);
add_openfpga_write_fabric_bitstream_command(shell, openfpga_bitstream_cmd_class, cmd_dependency_write_fabric_bitstream);
/********************************
* Command 'write_io_mapping'
*/
/* The 'write_io_mapping' command should NOT be executed before 'build_fabric' */
std::vector<ShellCommandId> cmd_dependency_write_io_mapping;
cmd_dependency_write_io_mapping.push_back(shell_cmd_build_fabric_id);
add_openfpga_write_io_mapping_command(shell, openfpga_bitstream_cmd_class, cmd_dependency_write_io_mapping);
}
} /* end namespace openfpga */

View File

@ -177,7 +177,9 @@ int link_arch(OpenfpgaContext& openfpga_ctx,
/* Build bitstream annotation based on bitstream settings */
if (CMD_EXEC_FATAL_ERROR == annotate_bitstream_setting(openfpga_ctx.bitstream_setting(),
g_vpr_ctx.device(),
openfpga_ctx.vpr_device_annotation(),
openfpga_ctx.mutable_vpr_bitstream_annotation())) {
return CMD_EXEC_FATAL_ERROR;
}

View File

@ -96,20 +96,49 @@ void update_cluster_pin_with_post_routing_results(const DeviceContext& device_ct
/* Find the net mapped to this pin in clustering results*/
ClusterNetId cluster_net_id = clustering_ctx.clb_nlist.block_net(blk_id, j);
/* Ignore those net have never been routed */
/* Ignore those net have never been routed: this check is valid only
* when both packer has mapped a net to the pin and the router leaves the pin to be unmapped
* This is important because we cannot bypass when router forces a valid net to be mapped
* and the net remapping has to be considered
*/
if ( (ClusterNetId::INVALID() != cluster_net_id)
&& (ClusterNetId::INVALID() == routing_net_id)
&& (true == clustering_ctx.clb_nlist.net_is_ignored(cluster_net_id))) {
VTR_LOGV(verbose,
"Bypass net at clustered block '%s' pin 'grid[%ld][%ld].%s.%s[%d]' as it is not routed\n",
clustering_ctx.clb_nlist.block_pb(blk_id)->name,
grid_coord.x(), grid_coord.y(),
clustering_ctx.clb_nlist.block_pb(blk_id)->pb_graph_node->pb_type->name,
get_pb_graph_node_pin_from_block_pin(blk_id, physical_pin)->port->name,
get_pb_graph_node_pin_from_block_pin(blk_id, physical_pin)->pin_number
);
continue;
}
/* Ignore used in local cluster only, reserved one CLB pin */
if ( (ClusterNetId::INVALID() != cluster_net_id)
&& (0 == clustering_ctx.clb_nlist.net_sinks(cluster_net_id).size())) {
VTR_LOGV(verbose,
"Bypass net at clustered block '%s' pin 'grid[%ld][%ld].%s.%s[%d]' as it is a local net inside the cluster\n",
clustering_ctx.clb_nlist.block_pb(blk_id)->name,
grid_coord.x(), grid_coord.y(),
clustering_ctx.clb_nlist.block_pb(blk_id)->pb_graph_node->pb_type->name,
get_pb_graph_node_pin_from_block_pin(blk_id, physical_pin)->port->name,
get_pb_graph_node_pin_from_block_pin(blk_id, physical_pin)->pin_number
);
continue;
}
/* If matched, we finish here */
if (routing_net_id == cluster_net_id) {
VTR_LOGV(verbose,
"Bypass net at clustered block '%s' pin 'grid[%ld][%ld].%s.%s[%d]' as it matches cluster routing\n",
clustering_ctx.clb_nlist.block_pb(blk_id)->name,
grid_coord.x(), grid_coord.y(),
clustering_ctx.clb_nlist.block_pb(blk_id)->pb_graph_node->pb_type->name,
get_pb_graph_node_pin_from_block_pin(blk_id, physical_pin)->port->name,
get_pb_graph_node_pin_from_block_pin(blk_id, physical_pin)->pin_number
);
continue;
}

View File

@ -62,23 +62,20 @@ int write_fabric_verilog(OpenfpgaContext& openfpga_ctx,
}
/********************************************************************
* A wrapper function to call the Verilog testbench generator of FPGA-Verilog
* A wrapper function to call the full testbench generator of FPGA-Verilog
*******************************************************************/
int write_verilog_testbench(OpenfpgaContext& openfpga_ctx,
const Command& cmd, const CommandContext& cmd_context) {
int write_full_testbench(const OpenfpgaContext& openfpga_ctx,
const Command& cmd, const CommandContext& cmd_context) {
CommandOptionId opt_output_dir = cmd.option("file");
CommandOptionId opt_bitstream = cmd.option("bitstream");
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");
CommandOptionId opt_print_formal_verification_top_netlist = cmd.option("print_formal_verification_top_netlist");
CommandOptionId opt_print_preconfig_top_testbench = cmd.option("print_preconfig_top_testbench");
CommandOptionId opt_print_simulation_ini = cmd.option("print_simulation_ini");
CommandOptionId opt_explicit_port_mapping = cmd.option("explicit_port_mapping");
CommandOptionId opt_default_net_type = cmd.option("default_net_type");
CommandOptionId opt_include_signal_init = cmd.option("include_signal_init");
CommandOptionId opt_support_icarus_simulator = cmd.option("support_icarus_simulator");
CommandOptionId opt_verbose = cmd.option("verbose");
/* This is an intermediate data structure which is designed to modularize the FPGA-Verilog
@ -88,15 +85,14 @@ int write_verilog_testbench(OpenfpgaContext& openfpga_ctx,
options.set_output_directory(cmd_context.option_value(cmd, opt_output_dir));
options.set_fabric_netlist_file_path(cmd_context.option_value(cmd, opt_fabric_netlist));
options.set_reference_benchmark_file_path(cmd_context.option_value(cmd, opt_reference_benchmark));
options.set_print_formal_verification_top_netlist(cmd_context.option_enable(cmd, opt_print_formal_verification_top_netlist));
options.set_print_preconfig_top_testbench(cmd_context.option_enable(cmd, opt_print_preconfig_top_testbench));
options.set_fast_configuration(cmd_context.option_enable(cmd, opt_fast_configuration));
options.set_print_top_testbench(cmd_context.option_enable(cmd, opt_print_top_testbench));
options.set_print_simulation_ini(cmd_context.option_value(cmd, opt_print_simulation_ini));
options.set_explicit_port_mapping(cmd_context.option_enable(cmd, opt_explicit_port_mapping));
options.set_include_signal_init(cmd_context.option_enable(cmd, opt_include_signal_init));
options.set_support_icarus_simulator(cmd_context.option_enable(cmd, opt_support_icarus_simulator));
options.set_verbose_output(cmd_context.option_enable(cmd, opt_verbose));
options.set_print_top_testbench(true);
options.set_include_signal_init(cmd_context.option_enable(cmd, opt_include_signal_init));
if (true == cmd_context.option_enable(cmd, opt_default_net_type)) {
options.set_default_net_type(cmd_context.option_value(cmd, opt_default_net_type));
}
/* If pin constraints are enabled by command options, read the file */
PinConstraints pin_constraints;
@ -104,19 +100,142 @@ int write_verilog_testbench(OpenfpgaContext& openfpga_ctx,
pin_constraints = read_xml_pin_constraints(cmd_context.option_value(cmd, opt_pcf).c_str());
}
return fpga_verilog_testbench(openfpga_ctx.module_graph(),
openfpga_ctx.bitstream_manager(),
openfpga_ctx.fabric_bitstream(),
g_vpr_ctx.atom(),
g_vpr_ctx.placement(),
pin_constraints,
openfpga_ctx.io_location_map(),
openfpga_ctx.fabric_global_port_info(),
openfpga_ctx.vpr_netlist_annotation(),
openfpga_ctx.arch().circuit_lib,
openfpga_ctx.simulation_setting(),
openfpga_ctx.arch().config_protocol,
options);
return fpga_verilog_full_testbench(openfpga_ctx.module_graph(),
openfpga_ctx.bitstream_manager(),
openfpga_ctx.fabric_bitstream(),
g_vpr_ctx.atom(),
g_vpr_ctx.placement(),
pin_constraints,
cmd_context.option_value(cmd, opt_bitstream),
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);
}
/********************************************************************
* A wrapper function to call the preconfigured wrapper generator of FPGA-Verilog
*******************************************************************/
int write_preconfigured_fabric_wrapper(const OpenfpgaContext& openfpga_ctx,
const Command& cmd, const CommandContext& cmd_context) {
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_explicit_port_mapping = cmd.option("explicit_port_mapping");
CommandOptionId opt_default_net_type = cmd.option("default_net_type");
CommandOptionId opt_support_icarus_simulator = cmd.option("support_icarus_simulator");
CommandOptionId opt_verbose = cmd.option("verbose");
/* This is an intermediate data structure which is designed to modularize the FPGA-Verilog
* Keep it independent from any other outside data structures
*/
VerilogTestbenchOption options;
options.set_output_directory(cmd_context.option_value(cmd, opt_output_dir));
options.set_fabric_netlist_file_path(cmd_context.option_value(cmd, opt_fabric_netlist));
options.set_explicit_port_mapping(cmd_context.option_enable(cmd, opt_explicit_port_mapping));
options.set_verbose_output(cmd_context.option_enable(cmd, opt_verbose));
options.set_support_icarus_simulator(cmd_context.option_enable(cmd, opt_support_icarus_simulator));
options.set_print_formal_verification_top_netlist(true);
if (true == cmd_context.option_enable(cmd, opt_default_net_type)) {
options.set_default_net_type(cmd_context.option_value(cmd, opt_default_net_type));
}
/* If pin constraints are enabled by command options, read the file */
PinConstraints pin_constraints;
if (true == cmd_context.option_enable(cmd, opt_pcf)) {
pin_constraints = read_xml_pin_constraints(cmd_context.option_value(cmd, opt_pcf).c_str());
}
return fpga_verilog_preconfigured_fabric_wrapper(openfpga_ctx.module_graph(),
openfpga_ctx.bitstream_manager(),
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.arch().config_protocol,
options);
}
/********************************************************************
* A wrapper function to call the preconfigured testbench generator of FPGA-Verilog
*******************************************************************/
int write_preconfigured_testbench(const OpenfpgaContext& openfpga_ctx,
const Command& cmd, const CommandContext& cmd_context) {
CommandOptionId opt_output_dir = cmd.option("file");
CommandOptionId opt_pcf = cmd.option("pin_constraints_file");
CommandOptionId opt_fabric_netlist = cmd.option("fabric_netlist_file_path");
CommandOptionId opt_reference_benchmark = cmd.option("reference_benchmark_file_path");
CommandOptionId opt_support_icarus_simulator = cmd.option("support_icarus_simulator");
CommandOptionId opt_explicit_port_mapping = cmd.option("explicit_port_mapping");
CommandOptionId opt_default_net_type = cmd.option("default_net_type");
CommandOptionId opt_verbose = cmd.option("verbose");
/* This is an intermediate data structure which is designed to modularize the FPGA-Verilog
* Keep it independent from any other outside data structures
*/
VerilogTestbenchOption options;
options.set_output_directory(cmd_context.option_value(cmd, opt_output_dir));
options.set_fabric_netlist_file_path(cmd_context.option_value(cmd, opt_fabric_netlist));
options.set_reference_benchmark_file_path(cmd_context.option_value(cmd, opt_reference_benchmark));
options.set_support_icarus_simulator(cmd_context.option_enable(cmd, opt_support_icarus_simulator));
options.set_explicit_port_mapping(cmd_context.option_enable(cmd, opt_explicit_port_mapping));
options.set_verbose_output(cmd_context.option_enable(cmd, opt_verbose));
options.set_print_preconfig_top_testbench(true);
if (true == cmd_context.option_enable(cmd, opt_default_net_type)) {
options.set_default_net_type(cmd_context.option_value(cmd, opt_default_net_type));
}
/* If pin constraints are enabled by command options, read the file */
PinConstraints pin_constraints;
if (true == cmd_context.option_enable(cmd, opt_pcf)) {
pin_constraints = read_xml_pin_constraints(cmd_context.option_value(cmd, opt_pcf).c_str());
}
return fpga_verilog_preconfigured_testbench(openfpga_ctx.module_graph(),
g_vpr_ctx.atom(),
pin_constraints,
openfpga_ctx.fabric_global_port_info(),
openfpga_ctx.vpr_netlist_annotation(),
openfpga_ctx.simulation_setting(),
options);
}
/********************************************************************
* A wrapper function to call the simulation task information generator of FPGA-Verilog
*******************************************************************/
int write_simulation_task_info(const OpenfpgaContext& openfpga_ctx,
const Command& cmd, const CommandContext& cmd_context) {
CommandOptionId opt_file = cmd.option("file");
CommandOptionId opt_hdl_dir = cmd.option("hdl_dir");
CommandOptionId opt_reference_benchmark = cmd.option("reference_benchmark_file_path");
CommandOptionId opt_verbose = cmd.option("verbose");
/* This is an intermediate data structure which is designed to modularize the FPGA-Verilog
* Keep it independent from any other outside data structures
*/
VerilogTestbenchOption options;
options.set_output_directory(cmd_context.option_value(cmd, opt_hdl_dir));
options.set_reference_benchmark_file_path(cmd_context.option_value(cmd, opt_reference_benchmark));
options.set_verbose_output(cmd_context.option_enable(cmd, opt_verbose));
options.set_print_simulation_ini(cmd_context.option_value(cmd, opt_file));
return fpga_verilog_simulation_task_info(openfpga_ctx.module_graph(),
openfpga_ctx.bitstream_manager(),
g_vpr_ctx.atom(),
g_vpr_ctx.placement(),
openfpga_ctx.io_location_map(),
openfpga_ctx.simulation_setting(),
openfpga_ctx.arch().config_protocol,
options);
}
} /* end namespace openfpga */

View File

@ -18,8 +18,17 @@ namespace openfpga {
int write_fabric_verilog(OpenfpgaContext& openfpga_ctx,
const Command& cmd, const CommandContext& cmd_context);
int write_verilog_testbench(OpenfpgaContext& openfpga_ctx,
const Command& cmd, const CommandContext& cmd_context);
int write_full_testbench(const OpenfpgaContext& openfpga_ctx,
const Command& cmd, const CommandContext& cmd_context);
int write_preconfigured_fabric_wrapper(const OpenfpgaContext& openfpga_ctx,
const Command& cmd, const CommandContext& cmd_context);
int write_preconfigured_testbench(const OpenfpgaContext& openfpga_ctx,
const Command& cmd, const CommandContext& cmd_context);
int write_simulation_task_info(const OpenfpgaContext& openfpga_ctx,
const Command& cmd, const CommandContext& cmd_context);
} /* end namespace openfpga */

View File

@ -55,23 +55,132 @@ ShellCommandId add_openfpga_write_fabric_verilog_command(openfpga::Shell<Openfpg
}
/********************************************************************
* - Add a command to Shell environment: write Verilog testbench
* - add a command to shell environment: write full testbench
* - add associated options
* - add command dependency
*******************************************************************/
static
ShellCommandId add_openfpga_write_full_testbench_command(openfpga::Shell<OpenfpgaContext>& shell,
const ShellCommandClassId& cmd_class_id,
const std::vector<ShellCommandId>& dependent_cmds) {
Command shell_cmd("write_full_testbench");
/* add an option '--file' in short '-f'*/
CommandOptionId output_opt = shell_cmd.add_option("file", true, "specify the output directory for hdl netlists");
shell_cmd.set_option_short_name(output_opt, "f");
shell_cmd.set_option_require_value(output_opt, openfpga::OPT_STRING);
/* add an option '--bitstream'*/
CommandOptionId bitstream_opt = shell_cmd.add_option("bitstream", true, "specify the bitstream to be loaded in the testbench");
shell_cmd.set_option_require_value(bitstream_opt, openfpga::OPT_STRING);
/* add an option '--fabric_netlist_file_path'*/
CommandOptionId fabric_netlist_opt = shell_cmd.add_option("fabric_netlist_file_path", false, "specify the file path to the fabric hdl 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);
/* add an option '--fast_configuration' */
shell_cmd.add_option("fast_configuration", false, "reduce the period of configuration by skip certain data points");
/* add an option '--explicit_port_mapping' */
shell_cmd.add_option("explicit_port_mapping", false, "use explicit port mapping in verilog netlists");
/* Add an option '--default_net_type' */
CommandOptionId default_net_type_opt = shell_cmd.add_option("default_net_type", false, "Set the default net type for Verilog netlists. Default value is 'none'");
shell_cmd.set_option_require_value(default_net_type_opt, openfpga::OPT_STRING);
/* add an option '--include_signal_init' */
shell_cmd.add_option("include_signal_init", false, "initialize all the signals in verilog testbenches");
/* add an option '--verbose' */
shell_cmd.add_option("verbose", false, "enable verbose output");
/* add command to the shell */
ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "generate full testbenches for an fpga fabric");
shell.set_command_class(shell_cmd_id, cmd_class_id);
shell.set_command_execute_function(shell_cmd_id, write_full_testbench);
/* add command dependency to the shell */
shell.set_command_dependency(shell_cmd_id, dependent_cmds);
return shell_cmd_id;
}
/********************************************************************
* - add a command to shell environment: write preconfigured fabric wrapper
* - add associated options
* - add command dependency
*******************************************************************/
static
ShellCommandId add_openfpga_write_preconfigured_fabric_wrapper_command(openfpga::Shell<OpenfpgaContext>& shell,
const ShellCommandClassId& cmd_class_id,
const std::vector<ShellCommandId>& dependent_cmds) {
Command shell_cmd("write_preconfigured_fabric_wrapper");
/* add an option '--file' in short '-f'*/
CommandOptionId output_opt = shell_cmd.add_option("file", true, "specify the output directory for hdl netlists");
shell_cmd.set_option_short_name(output_opt, "f");
shell_cmd.set_option_require_value(output_opt, openfpga::OPT_STRING);
/* add an option '--fabric_netlist_file_path'*/
CommandOptionId fabric_netlist_opt = shell_cmd.add_option("fabric_netlist_file_path", false, "specify the file path to the fabric hdl 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 '--explicit_port_mapping' */
shell_cmd.add_option("explicit_port_mapping", false, "use explicit port mapping in verilog netlists");
/* Add an option '--default_net_type' */
CommandOptionId default_net_type_opt = shell_cmd.add_option("default_net_type", false, "Set the default net type for Verilog netlists. Default value is 'none'");
shell_cmd.set_option_require_value(default_net_type_opt, openfpga::OPT_STRING);
/* Add an option '--support_icarus_simulator' */
shell_cmd.add_option("support_icarus_simulator", false, "Fine-tune Verilog testbenches to support icarus simulator");
/* add an option '--verbose' */
shell_cmd.add_option("verbose", false, "enable verbose output");
/* add command to the shell */
ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "generate a wrapper for a pre-configured fpga fabric");
shell.set_command_class(shell_cmd_id, cmd_class_id);
shell.set_command_execute_function(shell_cmd_id, write_preconfigured_fabric_wrapper);
/* add command dependency to the shell */
shell.set_command_dependency(shell_cmd_id, dependent_cmds);
return shell_cmd_id;
}
/********************************************************************
* - Add a command to Shell environment: write preconfigured testbench
* - Add associated options
* - Add command dependency
*******************************************************************/
static
ShellCommandId add_openfpga_write_verilog_testbench_command(openfpga::Shell<OpenfpgaContext>& shell,
const ShellCommandClassId& cmd_class_id,
const std::vector<ShellCommandId>& dependent_cmds) {
Command shell_cmd("write_verilog_testbench");
ShellCommandId add_openfpga_write_preconfigured_testbench_command(openfpga::Shell<OpenfpgaContext>& shell,
const ShellCommandClassId& cmd_class_id,
const std::vector<ShellCommandId>& dependent_cmds) {
Command shell_cmd("write_preconfigured_testbench");
/* Add an option '--file' in short '-f'*/
CommandOptionId output_opt = shell_cmd.add_option("file", true, "Specify the output directory for Verilog netlists");
CommandOptionId output_opt = shell_cmd.add_option("file", true, "Specify the output directory for HDL netlists");
shell_cmd.set_option_short_name(output_opt, "f");
shell_cmd.set_option_require_value(output_opt, openfpga::OPT_STRING);
/* Add an option '--fabric_netlist_file_path'*/
CommandOptionId fabric_netlist_opt = shell_cmd.add_option("fabric_netlist_file_path", false, "Specify the file path to the fabric Verilog netlist");
/* add an option '--fabric_netlist_file_path'*/
CommandOptionId fabric_netlist_opt = shell_cmd.add_option("fabric_netlist_file_path", false, "specify the file path to the fabric hdl netlist");
shell_cmd.set_option_require_value(fabric_netlist_opt, openfpga::OPT_STRING);
/* Add an option '--pin_constraints_file in short '-pcf' */
@ -83,38 +192,61 @@ ShellCommandId add_openfpga_write_verilog_testbench_command(openfpga::Shell<Open
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);
/* Add an option '--print_top_testbench' */
shell_cmd.add_option("print_top_testbench", false, "Generate a full testbench for top-level fabric module with autocheck capability");
/* Add an option '--fast_configuration' */
shell_cmd.add_option("fast_configuration", false, "Reduce the period of configuration by skip zero data points");
/* Add an option '--print_formal_verification_top_netlist' */
shell_cmd.add_option("print_formal_verification_top_netlist", false, "Generate a top-level module which can be used in formal verification");
/* Add an option '--print_preconfig_top_testbench' */
shell_cmd.add_option("print_preconfig_top_testbench", false, "Generate a pre-configured testbench for top-level fabric module with autocheck capability");
/* Add an option '--print_simulation_ini' */
CommandOptionId sim_ini_opt = shell_cmd.add_option("print_simulation_ini", false, "Generate a .ini file as an exchangeable file to enable HDL simulations");
shell_cmd.set_option_require_value(sim_ini_opt, openfpga::OPT_STRING);
/* Add an option '--support_icarus_simulator' */
shell_cmd.add_option("support_icarus_simulator", false, "Fine-tune Verilog testbenches to support icarus simulator");
/* Add an option '--explicit_port_mapping' */
shell_cmd.add_option("explicit_port_mapping", false, "Use explicit port mapping in Verilog netlists");
/* Add an option '--include_signal_init' */
shell_cmd.add_option("include_signal_init", false, "Initialize all the signals in Verilog testbenches");
/* Add an option '--support_icarus_simulator' */
shell_cmd.add_option("support_icarus_simulator", false, "Fine-tune Verilog testbenches to support icarus simulator");
/* Add an option '--default_net_type' */
CommandOptionId default_net_type_opt = shell_cmd.add_option("default_net_type", false, "Set the default net type for Verilog netlists. Default value is 'none'");
shell_cmd.set_option_require_value(default_net_type_opt, openfpga::OPT_STRING);
/* Add an option '--verbose' */
shell_cmd.add_option("verbose", false, "Enable verbose output");
/* Add command to the Shell */
ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "generate Verilog testbenches for full FPGA fabric");
ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "generate testbenches for a preconfigured FPGA fabric");
shell.set_command_class(shell_cmd_id, cmd_class_id);
shell.set_command_execute_function(shell_cmd_id, write_verilog_testbench);
shell.set_command_execute_function(shell_cmd_id, write_preconfigured_testbench);
/* Add command dependency to the Shell */
shell.set_command_dependency(shell_cmd_id, dependent_cmds);
return shell_cmd_id;
}
/********************************************************************
* - Add a command to Shell environment: write simulation task info
* - Add associated options
* - Add command dependency
*******************************************************************/
static
ShellCommandId add_openfpga_write_simulation_task_info_command(openfpga::Shell<OpenfpgaContext>& shell,
const ShellCommandClassId& cmd_class_id,
const std::vector<ShellCommandId>& dependent_cmds) {
Command shell_cmd("write_simulation_task_info");
/* Add an option '--file' in short '-f'*/
CommandOptionId output_opt = shell_cmd.add_option("file", true, "Specify the file path to output simulation-related information");
shell_cmd.set_option_short_name(output_opt, "f");
shell_cmd.set_option_require_value(output_opt, openfpga::OPT_STRING);
/* Add an option '--hdl_dir'*/
CommandOptionId hdl_dir_opt = shell_cmd.add_option("hdl_dir", true, "Specify the directory path where HDL netlists are created");
shell_cmd.set_option_require_value(hdl_dir_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);
/* Add an option '--verbose' */
shell_cmd.add_option("verbose", false, "Enable verbose output");
/* Add command to the Shell */
ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "generate an interchangable simulation task configuration file");
shell.set_command_class(shell_cmd_id, cmd_class_id);
shell.set_command_execute_function(shell_cmd_id, write_simulation_task_info);
/* Add command dependency to the Shell */
shell.set_command_dependency(shell_cmd_id, dependent_cmds);
@ -140,14 +272,44 @@ void add_openfpga_verilog_commands(openfpga::Shell<OpenfpgaContext>& shell) {
fabric_verilog_dependent_cmds);
/********************************
* Command 'write_verilog_testbench'
* Command 'write_full_testbench'
*/
/* The command 'write_verilog_testbench' should NOT be executed before 'build_fabric' */
std::vector<ShellCommandId> verilog_testbench_dependent_cmds;
verilog_testbench_dependent_cmds.push_back(build_fabric_cmd_id);
add_openfpga_write_verilog_testbench_command(shell,
openfpga_verilog_cmd_class,
verilog_testbench_dependent_cmds);
/* The command 'write_full_testbench' should NOT be executed before 'build_fabric' */
std::vector<ShellCommandId> full_testbench_dependent_cmds;
full_testbench_dependent_cmds.push_back(build_fabric_cmd_id);
add_openfpga_write_full_testbench_command(shell,
openfpga_verilog_cmd_class,
full_testbench_dependent_cmds);
/********************************
* Command 'write_preconfigured_fabric_wrapper'
*/
/* The command 'write_preconfigured_fabric_wrapper' should NOT be executed before 'build_fabric' */
std::vector<ShellCommandId> preconfig_wrapper_dependent_cmds;
preconfig_wrapper_dependent_cmds.push_back(build_fabric_cmd_id);
add_openfpga_write_preconfigured_fabric_wrapper_command(shell,
openfpga_verilog_cmd_class,
preconfig_wrapper_dependent_cmds);
/********************************
* Command 'write_preconfigured_testbench'
*/
/* The command 'write_preconfigured_testbench' should NOT be executed before 'build_fabric' */
std::vector<ShellCommandId> preconfig_testbench_dependent_cmds;
preconfig_testbench_dependent_cmds.push_back(build_fabric_cmd_id);
add_openfpga_write_preconfigured_testbench_command(shell,
openfpga_verilog_cmd_class,
preconfig_testbench_dependent_cmds);
/********************************
* Command 'write_simulation_task_info'
*/
/* The command 'write_simulation_task_info' should NOT be executed before 'build_fabric' */
std::vector<ShellCommandId> sim_task_info_dependent_cmds;
sim_task_info_dependent_cmds.push_back(build_fabric_cmd_id);
add_openfpga_write_simulation_task_info_command(shell,
openfpga_verilog_cmd_class,
sim_task_info_dependent_cmds);
}
} /* end namespace openfpga */

View File

@ -189,6 +189,7 @@ BitstreamManager build_device_bitstream(const VprContext& vpr_ctx,
openfpga_ctx.vpr_device_annotation(),
openfpga_ctx.vpr_clustering_annotation(),
openfpga_ctx.vpr_placement_annotation(),
openfpga_ctx.vpr_bitstream_annotation(),
verbose);
VTR_LOGV(verbose, "Done\n");

View File

@ -129,6 +129,7 @@ void build_physical_block_pin_interc_bitstream(BitstreamManager& bitstream_manag
const MuxLibrary& mux_lib,
const AtomContext& atom_ctx,
const VprDeviceAnnotation& device_annotation,
const VprBitstreamAnnotation& bitstream_annotation,
const PhysicalPb& physical_pb,
t_pb_graph_pin* des_pb_graph_pin,
t_mode* physical_mode) {
@ -197,6 +198,12 @@ void build_physical_block_pin_interc_bitstream(BitstreamManager& bitstream_manag
}
}
/* Overwrite the default path if defined in bitstream annotation */
if ( (size_t(DEFAULT_PATH_ID) == mux_input_pin_id)
&& (mux_input_pin_id != bitstream_annotation.interconnect_default_path_id(cur_interc)) ) {
mux_input_pin_id = bitstream_annotation.interconnect_default_path_id(cur_interc);
}
/* Generate bitstream depend on both technology and structure of this MUX */
std::vector<bool> mux_bitstream = build_mux_bitstream(circuit_lib, mux_model, mux_lib, datapath_mux_size, mux_input_pin_id);
@ -266,6 +273,7 @@ void build_physical_block_interc_port_bitstream(BitstreamManager& bitstream_mana
const MuxLibrary& mux_lib,
const AtomContext& atom_ctx,
const VprDeviceAnnotation& device_annotation,
const VprBitstreamAnnotation& bitstream_annotation,
t_pb_graph_node* physical_pb_graph_node,
const PhysicalPb& physical_pb,
const e_circuit_pb_port_type& pb_port_type,
@ -276,7 +284,7 @@ void build_physical_block_interc_port_bitstream(BitstreamManager& bitstream_mana
for (int ipin = 0; ipin < physical_pb_graph_node->num_input_pins[iport]; ++ipin) {
build_physical_block_pin_interc_bitstream(bitstream_manager, parent_configurable_block,
module_manager, circuit_lib, mux_lib,
atom_ctx, device_annotation,
atom_ctx, device_annotation, bitstream_annotation,
physical_pb,
&(physical_pb_graph_node->input_pins[iport][ipin]),
physical_mode);
@ -288,7 +296,7 @@ void build_physical_block_interc_port_bitstream(BitstreamManager& bitstream_mana
for (int ipin = 0; ipin < physical_pb_graph_node->num_output_pins[iport]; ++ipin) {
build_physical_block_pin_interc_bitstream(bitstream_manager, parent_configurable_block,
module_manager, circuit_lib, mux_lib,
atom_ctx, device_annotation,
atom_ctx, device_annotation, bitstream_annotation,
physical_pb,
&(physical_pb_graph_node->output_pins[iport][ipin]),
physical_mode);
@ -300,7 +308,7 @@ void build_physical_block_interc_port_bitstream(BitstreamManager& bitstream_mana
for (int ipin = 0; ipin < physical_pb_graph_node->num_clock_pins[iport]; ++ipin) {
build_physical_block_pin_interc_bitstream(bitstream_manager, parent_configurable_block,
module_manager, circuit_lib, mux_lib,
atom_ctx, device_annotation,
atom_ctx, device_annotation, bitstream_annotation,
physical_pb,
&(physical_pb_graph_node->clock_pins[iport][ipin]),
physical_mode);
@ -327,6 +335,7 @@ void build_physical_block_interc_bitstream(BitstreamManager& bitstream_manager,
const MuxLibrary& mux_lib,
const AtomContext& atom_ctx,
const VprDeviceAnnotation& device_annotation,
const VprBitstreamAnnotation& bitstream_annotation,
t_pb_graph_node* physical_pb_graph_node,
const PhysicalPb& physical_pb,
t_mode* physical_mode) {
@ -348,7 +357,7 @@ void build_physical_block_interc_bitstream(BitstreamManager& bitstream_manager,
*/
build_physical_block_interc_port_bitstream(bitstream_manager, parent_configurable_block,
module_manager, circuit_lib, mux_lib,
atom_ctx, device_annotation,
atom_ctx, device_annotation, bitstream_annotation,
physical_pb_graph_node, physical_pb,
CIRCUIT_PB_PORT_OUTPUT, physical_mode);
@ -367,13 +376,13 @@ void build_physical_block_interc_bitstream(BitstreamManager& bitstream_manager,
/* For each child_pb_graph_node input pins*/
build_physical_block_interc_port_bitstream(bitstream_manager, parent_configurable_block,
module_manager, circuit_lib, mux_lib,
atom_ctx, device_annotation,
atom_ctx, device_annotation, bitstream_annotation,
child_pb_graph_node, physical_pb,
CIRCUIT_PB_PORT_INPUT, physical_mode);
/* For clock pins, we should do the same work */
build_physical_block_interc_port_bitstream(bitstream_manager, parent_configurable_block,
module_manager, circuit_lib, mux_lib,
atom_ctx, device_annotation,
atom_ctx, device_annotation, bitstream_annotation,
child_pb_graph_node, physical_pb,
CIRCUIT_PB_PORT_CLOCK, physical_mode);
}
@ -534,6 +543,7 @@ void rec_build_physical_block_bitstream(BitstreamManager& bitstream_manager,
const MuxLibrary& mux_lib,
const AtomContext& atom_ctx,
const VprDeviceAnnotation& device_annotation,
const VprBitstreamAnnotation& bitstream_annotation,
const e_side& border_side,
const PhysicalPb& physical_pb,
const PhysicalPbId& pb_id,
@ -578,7 +588,7 @@ void rec_build_physical_block_bitstream(BitstreamManager& bitstream_manager,
rec_build_physical_block_bitstream(bitstream_manager, pb_configurable_block,
module_manager, circuit_lib, mux_lib,
atom_ctx,
device_annotation,
device_annotation, bitstream_annotation,
border_side,
physical_pb, child_pb,
&(physical_pb_graph_node->child_pb_graph_nodes[physical_mode->index][ipb][jpb]),
@ -623,7 +633,7 @@ void rec_build_physical_block_bitstream(BitstreamManager& bitstream_manager,
build_physical_block_interc_bitstream(bitstream_manager, pb_configurable_block,
module_manager, circuit_lib, mux_lib,
atom_ctx,
device_annotation,
device_annotation, bitstream_annotation,
physical_pb_graph_node, physical_pb,
physical_mode);
}
@ -644,6 +654,7 @@ void build_physical_block_bitstream(BitstreamManager& bitstream_manager,
const VprDeviceAnnotation& device_annotation,
const VprClusteringAnnotation& cluster_annotation,
const VprPlacementAnnotation& place_annotation,
const VprBitstreamAnnotation& bitstream_annotation,
const DeviceGrid& grids,
const vtr::Point<size_t>& grid_coord,
const e_side& border_side) {
@ -692,7 +703,8 @@ void build_physical_block_bitstream(BitstreamManager& bitstream_manager,
rec_build_physical_block_bitstream(bitstream_manager, grid_configurable_block,
module_manager, circuit_lib, mux_lib,
atom_ctx,
device_annotation, border_side,
device_annotation, bitstream_annotation,
border_side,
PhysicalPb(), PhysicalPbId::INVALID(),
lb_type->pb_graph_head, z);
} else {
@ -707,7 +719,8 @@ void build_physical_block_bitstream(BitstreamManager& bitstream_manager,
rec_build_physical_block_bitstream(bitstream_manager, grid_configurable_block,
module_manager, circuit_lib, mux_lib,
atom_ctx,
device_annotation, border_side,
device_annotation, bitstream_annotation,
border_side,
phy_pb, top_pb_id, pb_graph_head, z);
}
}
@ -731,6 +744,7 @@ void build_grid_bitstream(BitstreamManager& bitstream_manager,
const VprDeviceAnnotation& device_annotation,
const VprClusteringAnnotation& cluster_annotation,
const VprPlacementAnnotation& place_annotation,
const VprBitstreamAnnotation& bitstream_annotation,
const bool& verbose) {
VTR_LOGV(verbose, "Generating bitstream for core grids...");
@ -753,7 +767,7 @@ void build_grid_bitstream(BitstreamManager& bitstream_manager,
circuit_lib, mux_lib,
atom_ctx,
device_annotation, cluster_annotation,
place_annotation,
place_annotation, bitstream_annotation,
grids, grid_coord, NUM_SIDES);
}
}
@ -780,7 +794,7 @@ void build_grid_bitstream(BitstreamManager& bitstream_manager,
circuit_lib, mux_lib,
atom_ctx,
device_annotation, cluster_annotation,
place_annotation,
place_annotation, bitstream_annotation,
grids, io_coordinate, io_side);
}
}

View File

@ -14,6 +14,7 @@
#include "vpr_device_annotation.h"
#include "vpr_clustering_annotation.h"
#include "vpr_placement_annotation.h"
#include "vpr_bitstream_annotation.h"
/********************************************************************
* Function declaration
@ -32,6 +33,7 @@ void build_grid_bitstream(BitstreamManager& bitstream_manager,
const VprDeviceAnnotation& device_annotation,
const VprClusteringAnnotation& cluster_annotation,
const VprPlacementAnnotation& place_annotation,
const VprBitstreamAnnotation& bitstream_annotation,
const bool& verbose);
} /* end namespace openfpga */

View File

@ -0,0 +1,144 @@
/********************************************************************
* This file includes functions that build io mapping information
*******************************************************************/
#include <chrono>
#include <ctime>
#include <fstream>
/* Headers from vtrutil library */
#include "vtr_assert.h"
#include "vtr_log.h"
#include "vtr_time.h"
/* Headers from archopenfpga library */
#include "openfpga_naming.h"
#include "module_manager_utils.h"
#include "build_io_mapping_info.h"
/* begin namespace openfpga */
namespace openfpga {
/********************************************************************
* This function
* - builds the net-to-I/O mapping
* - identifies each I/O directionality
* - return a database containing the above information
*
* TODO: This function duplicates codes from
* function: print_verilog_testbench_connect_fpga_ios() in
* source file: verilog_testbench_utils.cpp
* Should consider how to merge the codes and share same builder function
*******************************************************************/
IoMap build_fpga_io_mapping_info(const ModuleManager& module_manager,
const ModuleId& top_module,
const AtomContext& atom_ctx,
const PlacementContext& place_ctx,
const IoLocationMap& io_location_map,
const VprNetlistAnnotation& netlist_annotation,
const std::string& io_input_port_name_postfix,
const std::string& io_output_port_name_postfix) {
IoMap io_map;
/* Only mappable i/o ports can be considered */
std::vector<ModulePortId> module_io_ports;
for (const ModuleManager::e_module_port_type& module_io_port_type : MODULE_IO_PORT_TYPES) {
for (const ModulePortId& gpio_port_id : module_manager.module_port_ids_by_type(top_module, module_io_port_type)) {
/* Only care mappable I/O */
if (false == module_manager.port_is_mappable_io(top_module, gpio_port_id)) {
continue;
}
module_io_ports.push_back(gpio_port_id);
}
}
/* Type mapping between VPR block and Module port */
std::map<AtomBlockType, ModuleManager::e_module_port_type> atom_block_type_to_module_port_type;
atom_block_type_to_module_port_type[AtomBlockType::INPAD] = ModuleManager::MODULE_GPIN_PORT;
atom_block_type_to_module_port_type[AtomBlockType::OUTPAD] = ModuleManager::MODULE_GPOUT_PORT;
/* Type mapping between VPR block and io mapping direction */
std::map<AtomBlockType, IoMap::e_direction> atom_block_type_to_io_map_direction;
atom_block_type_to_io_map_direction[AtomBlockType::INPAD] = IoMap::IO_MAP_DIR_INPUT;
atom_block_type_to_io_map_direction[AtomBlockType::OUTPAD] = IoMap::IO_MAP_DIR_OUTPUT;
for (const AtomBlockId& atom_blk : atom_ctx.nlist.blocks()) {
/* Bypass non-I/O atom blocks ! */
if ( (AtomBlockType::INPAD != atom_ctx.nlist.block_type(atom_blk))
&& (AtomBlockType::OUTPAD != atom_ctx.nlist.block_type(atom_blk)) ) {
continue;
}
/* If there is a GPIO port, use it directly
* Otherwise, should find a GPIN for INPAD
* or should find a GPOUT for OUTPAD
*/
std::pair<ModulePortId, size_t> mapped_module_io_info = std::make_pair(ModulePortId::INVALID(), -1);
for (const ModulePortId& module_io_port_id : module_io_ports) {
const BasicPort& module_io_port = module_manager.module_port(top_module, module_io_port_id);
/* Find the index of the mapped GPIO in top-level FPGA fabric */
size_t temp_io_index = io_location_map.io_index(place_ctx.block_locs[atom_ctx.lookup.atom_clb(atom_blk)].loc.x,
place_ctx.block_locs[atom_ctx.lookup.atom_clb(atom_blk)].loc.y,
place_ctx.block_locs[atom_ctx.lookup.atom_clb(atom_blk)].loc.z,
module_io_port.get_name());
/* Bypass invalid index (not mapped to this GPIO port) */
if (size_t(-1) == temp_io_index) {
continue;
}
/* If the port is an GPIO port, just use it */
if (ModuleManager::MODULE_GPIO_PORT == module_manager.port_type(top_module, module_io_port_id)) {
mapped_module_io_info = std::make_pair(module_io_port_id, temp_io_index);
break;
}
/* If this is an INPAD, we can use an GPIN port (if available) */
if (atom_block_type_to_module_port_type[atom_ctx.nlist.block_type(atom_blk)] == module_manager.port_type(top_module, module_io_port_id)) {
mapped_module_io_info = std::make_pair(module_io_port_id, temp_io_index);
break;
}
}
/* We must find a valid one */
VTR_ASSERT(true == module_manager.valid_module_port_id(top_module, mapped_module_io_info.first));
VTR_ASSERT(size_t(-1) != mapped_module_io_info.second);
/* Ensure that IO index is in range */
BasicPort module_mapped_io_port = module_manager.module_port(top_module, mapped_module_io_info.first);
size_t io_index = mapped_module_io_info.second;
/* Set the port pin index */
VTR_ASSERT(io_index < module_mapped_io_port.get_width());
module_mapped_io_port.set_width(io_index, io_index);
/* 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);
}
/* Create the port for benchmark I/O, due to BLIF benchmark, each I/O always has a size of 1
* In addition, the input and output ports may have different postfix in naming
* due to verification context! Here, we give full customization on naming
*/
BasicPort benchmark_io_port;
if (AtomBlockType::INPAD == atom_ctx.nlist.block_type(atom_blk)) {
benchmark_io_port.set_name(std::string(block_name + io_input_port_name_postfix));
benchmark_io_port.set_width(1);
} else {
VTR_ASSERT(AtomBlockType::OUTPAD == atom_ctx.nlist.block_type(atom_blk));
benchmark_io_port.set_name(std::string(block_name + io_output_port_name_postfix));
benchmark_io_port.set_width(1);
}
io_map.create_io_mapping(module_mapped_io_port,
benchmark_io_port,
atom_block_type_to_io_map_direction[atom_ctx.nlist.block_type(atom_blk)]);
}
return io_map;
}
} /* end namespace openfpga */

View File

@ -0,0 +1,33 @@
#ifndef BUILD_IO_MAPPING_INFO_H
#define BUILD_IO_MAPPING_INFO_H
/********************************************************************
* Include header files that are required by function declaration
*******************************************************************/
#include <string>
#include <vector>
#include "module_manager.h"
#include "vpr_context.h"
#include "io_location_map.h"
#include "io_map.h"
#include "vpr_netlist_annotation.h"
/********************************************************************
* Function declaration
*******************************************************************/
/* begin namespace openfpga */
namespace openfpga {
IoMap build_fpga_io_mapping_info(const ModuleManager& module_manager,
const ModuleId& top_module,
const AtomContext& atom_ctx,
const PlacementContext& place_ctx,
const IoLocationMap& io_location_map,
const VprNetlistAnnotation& netlist_annotation,
const std::string& io_input_port_name_postfix,
const std::string& io_output_port_name_postfix);
} /* end namespace openfpga */
#endif

View File

@ -0,0 +1,128 @@
/********************************************************************
* This file includes functions that are used to create
* an auto-check top-level testbench for a FPGA fabric
*******************************************************************/
#include <vector>
/* Headers from vtrutil library */
#include "vtr_log.h"
#include "vtr_assert.h"
#include "fabric_global_port_info_utils.h"
#include "fast_configuration.h"
/* begin namespace openfpga */
namespace openfpga {
/********************************************************************
* Identify if fast configuration is applicable base on the availability
* of programming reset and programming set ports of the FPGA fabric
*******************************************************************/
bool is_fast_configuration_applicable(const FabricGlobalPortInfo& global_ports) {
/* Preparation: find all the reset/set ports for programming usage */
std::vector<FabricGlobalPortId> global_prog_reset_ports = find_fabric_global_programming_reset_ports(global_ports);
std::vector<FabricGlobalPortId> global_prog_set_ports = find_fabric_global_programming_set_ports(global_ports);
/* Identify if we can apply fast configuration */
if (global_prog_set_ports.empty() && global_prog_reset_ports.empty()) {
VTR_LOG_WARN("None of global reset and set ports are defined for programming purpose. Fast configuration is not applicable\n");
return false;
}
return true;
}
/********************************************************************
* Decide if we should use reset or set signal to acheive fast configuration
* - If only one type signal is specified, we use that type
* For example, only reset signal is defined, we will use reset
* - If both are defined, pick the one that will bring bigger reduction
* i.e., larger number of configuration bits can be skipped
*******************************************************************/
bool find_bit_value_to_skip_for_fast_configuration(const e_config_protocol_type& config_protocol_type,
const FabricGlobalPortInfo& global_ports,
const BitstreamManager& bitstream_manager,
const FabricBitstream& fabric_bitstream) {
/* Preparation: find all the reset/set ports for programming usage */
std::vector<FabricGlobalPortId> global_prog_reset_ports = find_fabric_global_programming_reset_ports(global_ports);
std::vector<FabricGlobalPortId> global_prog_set_ports = find_fabric_global_programming_set_ports(global_ports);
/* Early exit conditions */
if (!global_prog_reset_ports.empty() && global_prog_set_ports.empty()) {
return false;
} else if (!global_prog_set_ports.empty() && global_prog_reset_ports.empty()) {
return true;
}
/* If both types of ports are not defined, the fast configuration is not applicable */
VTR_ASSERT(!global_prog_set_ports.empty() && !global_prog_reset_ports.empty());
bool bit_value_to_skip = false;
VTR_LOG("Both reset and set ports are defined for programming controls, selecting the best-fit one...\n");
size_t num_ones_to_skip = 0;
size_t num_zeros_to_skip = 0;
/* Branch on the type of configuration protocol */
switch (config_protocol_type) {
case CONFIG_MEM_STANDALONE:
break;
case CONFIG_MEM_SCAN_CHAIN: {
/* We can only skip the ones/zeros at the beginning of the bitstream */
/* Count how many logic '1' bits we can skip */
for (const FabricBitId& bit_id : fabric_bitstream.bits()) {
if (false == bitstream_manager.bit_value(fabric_bitstream.config_bit(bit_id))) {
break;
}
VTR_ASSERT(true == bitstream_manager.bit_value(fabric_bitstream.config_bit(bit_id)));
num_ones_to_skip++;
}
/* Count how many logic '0' bits we can skip */
for (const FabricBitId& bit_id : fabric_bitstream.bits()) {
if (true == bitstream_manager.bit_value(fabric_bitstream.config_bit(bit_id))) {
break;
}
VTR_ASSERT(false == bitstream_manager.bit_value(fabric_bitstream.config_bit(bit_id)));
num_zeros_to_skip++;
}
break;
}
case CONFIG_MEM_MEMORY_BANK:
case CONFIG_MEM_FRAME_BASED: {
/* Count how many logic '1' and logic '0' bits we can skip */
for (const FabricBitId& bit_id : fabric_bitstream.bits()) {
if (false == bitstream_manager.bit_value(fabric_bitstream.config_bit(bit_id))) {
num_zeros_to_skip++;
} else {
VTR_ASSERT(true == bitstream_manager.bit_value(fabric_bitstream.config_bit(bit_id)));
num_ones_to_skip++;
}
}
break;
}
default:
VTR_LOGF_ERROR(__FILE__, __LINE__,
"Invalid configuration protocol type!\n");
exit(1);
}
VTR_LOG("Using reset will skip %g% (%lu/%lu) of configuration bitstream.\n",
100. * (float) num_zeros_to_skip / (float) fabric_bitstream.num_bits(),
num_zeros_to_skip, fabric_bitstream.num_bits());
VTR_LOG("Using set will skip %g% (%lu/%lu) of configuration bitstream.\n",
100. * (float) num_ones_to_skip / (float) fabric_bitstream.num_bits(),
num_ones_to_skip, fabric_bitstream.num_bits());
/* By default, we prefer to skip zeros (when the numbers are the same */
if (num_ones_to_skip > num_zeros_to_skip) {
VTR_LOG("Will use set signal in fast configuration\n");
bit_value_to_skip = true;
} else {
VTR_LOG("Will use reset signal in fast configuration\n");
}
return bit_value_to_skip;
}
} /* end namespace openfpga */

View File

@ -0,0 +1,30 @@
#ifndef FAST_CONFIGURATION_H
#define FAST_CONFIGURATION_H
/********************************************************************
* Include header files that are required by function declaration
*******************************************************************/
#include <string>
#include <vector>
#include "fabric_global_port_info.h"
#include "config_protocol.h"
#include "bitstream_manager.h"
#include "fabric_bitstream.h"
/********************************************************************
* Function declaration
*******************************************************************/
/* begin namespace openfpga */
namespace openfpga {
bool is_fast_configuration_applicable(const FabricGlobalPortInfo& global_ports);
bool find_bit_value_to_skip_for_fast_configuration(const e_config_protocol_type& config_protocol_type,
const FabricGlobalPortInfo& global_ports,
const BitstreamManager& bitstream_manager,
const FabricBitstream& fabric_bitstream);
} /* end namespace openfpga */
#endif

View File

@ -13,9 +13,11 @@
/* Headers from openfpgautil library */
#include "openfpga_digest.h"
#include "openfpga_version.h"
#include "openfpga_naming.h"
#include "fast_configuration.h"
#include "bitstream_manager_utils.h"
#include "fabric_bitstream_utils.h"
#include "write_text_fabric_bitstream.h"
@ -24,64 +26,20 @@
namespace openfpga {
/********************************************************************
* Write a configuration bit into a plain text file
* The format depends on the type of configuration protocol
* - Vanilla (standalone): just put down pure 0|1 bitstream
* - Configuration chain: just put down pure 0|1 bitstream
* - Memory bank : <BL address> <WL address> <bit>
* - Frame-based configuration protocol : <address> <bit>
*
* Return:
* - 0 if succeed
* - 1 if critical errors occured
* This function write header information to a bitstream file
*******************************************************************/
static
int write_fabric_config_bit_to_text_file(std::fstream& fp,
const BitstreamManager& bitstream_manager,
const FabricBitstream& fabric_bitstream,
const FabricBitId& fabric_bit,
const e_config_protocol_type& config_type) {
if (false == valid_file_stream(fp)) {
return 1;
}
void write_fabric_bitstream_text_file_head(std::fstream& fp) {
valid_file_stream(fp);
auto end = std::chrono::system_clock::now();
std::time_t end_time = std::chrono::system_clock::to_time_t(end);
switch (config_type) {
case CONFIG_MEM_STANDALONE:
case CONFIG_MEM_SCAN_CHAIN:
fp << bitstream_manager.bit_value(fabric_bitstream.config_bit(fabric_bit));
break;
case CONFIG_MEM_MEMORY_BANK: {
for (const char& addr_bit : fabric_bitstream.bit_bl_address(fabric_bit)) {
fp << addr_bit;
}
write_space_to_file(fp, 1);
for (const char& addr_bit : fabric_bitstream.bit_wl_address(fabric_bit)) {
fp << addr_bit;
}
write_space_to_file(fp, 1);
fp << bitstream_manager.bit_value(fabric_bitstream.config_bit(fabric_bit));
fp << "\n";
break;
}
case CONFIG_MEM_FRAME_BASED: {
for (const char& addr_bit : fabric_bitstream.bit_address(fabric_bit)) {
fp << addr_bit;
}
write_space_to_file(fp, 1);
fp << bitstream_manager.bit_value(fabric_bitstream.config_bit(fabric_bit));
fp << "\n";
break;
}
default:
VTR_LOGF_ERROR(__FILE__, __LINE__,
"Invalid configuration protocol type!\n");
return 1;
}
return 0;
fp << "// Fabric bitstream" << std::endl;
fp << "// Version: " << openfpga::VERSION << std::endl;
fp << "// Date: " << std::ctime(&end_time);
}
/********************************************************************
* Write the flatten fabric bitstream to a plain text file
*
@ -92,20 +50,20 @@ int write_fabric_config_bit_to_text_file(std::fstream& fp,
static
int write_flatten_fabric_bitstream_to_text_file(std::fstream& fp,
const BitstreamManager& bitstream_manager,
const FabricBitstream& fabric_bitstream,
const ConfigProtocol& config_protocol) {
int status = 0;
for (const FabricBitId& fabric_bit : fabric_bitstream.bits()) {
status = write_fabric_config_bit_to_text_file(fp, bitstream_manager,
fabric_bitstream,
fabric_bit,
config_protocol.type());
if (1 == status) {
return status;
}
const FabricBitstream& fabric_bitstream) {
if (false == valid_file_stream(fp)) {
return 1;
}
return status;
/* Output bitstream size information */
fp << "// Bitstream length: " << fabric_bitstream.num_bits() << std::endl;
/* Output bitstream data */
for (const FabricBitId& fabric_bit : fabric_bitstream.bits()) {
fp << bitstream_manager.bit_value(fabric_bitstream.config_bit(fabric_bit));
}
return 0;
}
/********************************************************************
@ -118,6 +76,8 @@ int write_flatten_fabric_bitstream_to_text_file(std::fstream& fp,
*******************************************************************/
static
int write_config_chain_fabric_bitstream_to_text_file(std::fstream& fp,
const bool& fast_configuration,
const bool& bit_value_to_skip,
const BitstreamManager& bitstream_manager,
const FabricBitstream& fabric_bitstream) {
int status = 0;
@ -125,11 +85,28 @@ int write_config_chain_fabric_bitstream_to_text_file(std::fstream& fp,
size_t regional_bitstream_max_size = find_fabric_regional_bitstream_max_size(fabric_bitstream);
ConfigChainFabricBitstream regional_bitstreams = build_config_chain_fabric_bitstream_by_region(bitstream_manager, fabric_bitstream);
for (size_t ibit = 0; ibit < regional_bitstream_max_size; ++ibit) {
/* For fast configuration, the bitstream size counts from the first bit '1' */
size_t num_bits_to_skip = 0;
if (true == fast_configuration) {
num_bits_to_skip = find_configuration_chain_fabric_bitstream_size_to_be_skipped(fabric_bitstream, bitstream_manager, bit_value_to_skip);
VTR_ASSERT(num_bits_to_skip < regional_bitstream_max_size);
VTR_LOG("Fast configuration will skip %g% (%lu/%lu) of configuration bitstream.\n",
100. * (float) num_bits_to_skip / (float) regional_bitstream_max_size,
num_bits_to_skip, regional_bitstream_max_size);
}
/* Output bitstream size information */
fp << "// Bitstream length: " << regional_bitstream_max_size - num_bits_to_skip << std::endl;
fp << "// Bitstream width (LSB -> MSB): " << fabric_bitstream.num_regions() << std::endl;
/* Output bitstream data */
for (size_t ibit = num_bits_to_skip; ibit < regional_bitstream_max_size; ++ibit) {
for (const auto& region_bitstream : regional_bitstreams) {
fp << region_bitstream[ibit];
}
fp << std::endl;
if (ibit < regional_bitstream_max_size - 1) {
fp << std::endl;
}
}
return status;
@ -145,20 +122,54 @@ int write_config_chain_fabric_bitstream_to_text_file(std::fstream& fp,
*******************************************************************/
static
int write_memory_bank_fabric_bitstream_to_text_file(std::fstream& fp,
const FabricBitstream& fabric_bitstream) {
const bool& fast_configuration,
const bool& bit_value_to_skip,
const FabricBitstream& fabric_bitstream) {
int status = 0;
MemoryBankFabricBitstream fabric_bits_by_addr = build_memory_bank_fabric_bitstream_by_address(fabric_bitstream);
/* The address sizes and data input sizes are the same across any element,
* just get it from the 1st element to save runtime
*/
size_t bl_addr_size = fabric_bits_by_addr.begin()->first.first.size();
size_t wl_addr_size = fabric_bits_by_addr.begin()->first.second.size();
size_t din_size = fabric_bits_by_addr.begin()->second.size();
/* Identify and output bitstream size information */
size_t num_bits_to_skip = 0;
if (true == fast_configuration) {
num_bits_to_skip = fabric_bits_by_addr.size() - find_memory_bank_fast_configuration_fabric_bitstream_size(fabric_bitstream, bit_value_to_skip);
VTR_ASSERT(num_bits_to_skip < fabric_bits_by_addr.size());
VTR_LOG("Fast configuration will skip %g% (%lu/%lu) of configuration bitstream.\n",
100. * (float) num_bits_to_skip / (float) fabric_bits_by_addr.size(),
num_bits_to_skip, fabric_bits_by_addr.size());
}
/* Output information about how to intepret the bitstream */
fp << "// Bitstream length: " << fabric_bits_by_addr.size() - num_bits_to_skip << std::endl;
fp << "// Bitstream width (LSB -> MSB): ";
fp << "<bl_address " << bl_addr_size << " bits>";
fp << "<wl_address " << wl_addr_size << " bits>";
fp << "<data input " << din_size << " bits>";
fp << std::endl;
for (const auto& addr_din_pair : fabric_bits_by_addr) {
/* When fast configuration is enabled,
* the rule to skip any configuration bit should consider the whole data input values.
* Only all the bits in the din port match the value to be skipped,
* the programming cycle can be skipped!
*/
if (true == fast_configuration) {
if (addr_din_pair.second == std::vector<bool>(addr_din_pair.second.size(), bit_value_to_skip)) {
continue;
}
}
/* Write BL address code */
fp << addr_din_pair.first.first;
fp << " ";
/* Write WL address code */
fp << addr_din_pair.first.second;
fp << " ";
/* Write data input */
for (const bool& din_value : addr_din_pair.second) {
fp << din_value;
@ -179,15 +190,47 @@ int write_memory_bank_fabric_bitstream_to_text_file(std::fstream& fp,
*******************************************************************/
static
int write_frame_based_fabric_bitstream_to_text_file(std::fstream& fp,
const bool& fast_configuration,
const bool& bit_value_to_skip,
const FabricBitstream& fabric_bitstream) {
int status = 0;
FrameFabricBitstream fabric_bits_by_addr = build_frame_based_fabric_bitstream_by_address(fabric_bitstream);
/* The address sizes and data input sizes are the same across any element,
* just get it from the 1st element to save runtime
*/
size_t addr_size = fabric_bits_by_addr.begin()->first.size();
size_t din_size = fabric_bits_by_addr.begin()->second.size();
/* Identify and output bitstream size information */
size_t num_bits_to_skip = 0;
if (true == fast_configuration) {
num_bits_to_skip = fabric_bits_by_addr.size() - find_frame_based_fast_configuration_fabric_bitstream_size(fabric_bitstream, bit_value_to_skip);
VTR_ASSERT(num_bits_to_skip < fabric_bits_by_addr.size());
VTR_LOG("Fast configuration will skip %g% (%lu/%lu) of configuration bitstream.\n",
100. * (float) num_bits_to_skip / (float) fabric_bits_by_addr.size(),
num_bits_to_skip, fabric_bits_by_addr.size());
}
/* Output information about how to intepret the bitstream */
fp << "// Bitstream length: " << fabric_bits_by_addr.size() - num_bits_to_skip << std::endl;
fp << "// Bitstream width (LSB -> MSB): <address " << addr_size << " bits><data input " << din_size << " bits>" << std::endl;
for (const auto& addr_din_pair : fabric_bits_by_addr) {
/* When fast configuration is enabled,
* the rule to skip any configuration bit should consider the whole data input values.
* Only all the bits in the din port match the value to be skipped,
* the programming cycle can be skipped!
*/
if (true == fast_configuration) {
if (addr_din_pair.second == std::vector<bool>(addr_din_pair.second.size(), bit_value_to_skip)) {
continue;
}
}
/* Write address code */
fp << addr_din_pair.first;
fp << " ";
/* Write data input */
for (const bool& din_value : addr_din_pair.second) {
@ -214,7 +257,9 @@ int write_frame_based_fabric_bitstream_to_text_file(std::fstream& fp,
int write_fabric_bitstream_to_text_file(const BitstreamManager& bitstream_manager,
const FabricBitstream& fabric_bitstream,
const ConfigProtocol& config_protocol,
const FabricGlobalPortInfo& global_ports,
const std::string& fname,
const bool& fast_configuration,
const bool& verbose) {
/* Ensure that we have a valid file name */
if (true == fname.empty()) {
@ -230,26 +275,47 @@ int write_fabric_bitstream_to_text_file(const BitstreamManager& bitstream_manage
check_file_stream(fname.c_str(), fp);
bool apply_fast_configuration = is_fast_configuration_applicable(global_ports) && fast_configuration;
if (fast_configuration && apply_fast_configuration != fast_configuration) {
VTR_LOG_WARN("Disable fast configuration even it is enabled by user\n");
}
bool bit_value_to_skip = false;
if (apply_fast_configuration) {
bit_value_to_skip = find_bit_value_to_skip_for_fast_configuration(config_protocol.type(),
global_ports,
bitstream_manager,
fabric_bitstream);
}
/* Write file head */
write_fabric_bitstream_text_file_head(fp);
/* Output fabric bitstream to the file */
int status = 0;
switch (config_protocol.type()) {
case CONFIG_MEM_STANDALONE:
status = write_flatten_fabric_bitstream_to_text_file(fp,
bitstream_manager,
fabric_bitstream,
config_protocol);
fabric_bitstream);
break;
case CONFIG_MEM_SCAN_CHAIN:
status = write_config_chain_fabric_bitstream_to_text_file(fp,
apply_fast_configuration,
bit_value_to_skip,
bitstream_manager,
fabric_bitstream);
break;
case CONFIG_MEM_MEMORY_BANK:
status = write_memory_bank_fabric_bitstream_to_text_file(fp,
apply_fast_configuration,
bit_value_to_skip,
fabric_bitstream);
break;
case CONFIG_MEM_FRAME_BASED:
status = write_frame_based_fabric_bitstream_to_text_file(fp,
apply_fast_configuration,
bit_value_to_skip,
fabric_bitstream);
break;
default:

View File

@ -9,6 +9,7 @@
#include "bitstream_manager.h"
#include "fabric_bitstream.h"
#include "config_protocol.h"
#include "fabric_global_port_info.h"
/********************************************************************
* Function declaration
@ -20,7 +21,9 @@ namespace openfpga {
int write_fabric_bitstream_to_text_file(const BitstreamManager& bitstream_manager,
const FabricBitstream& fabric_bitstream,
const ConfigProtocol& config_protocol,
const FabricGlobalPortInfo& global_ports,
const std::string& fname,
const bool& fast_configuration,
const bool& verbose);
} /* end namespace openfpga */

View File

@ -0,0 +1,145 @@
/********************************************************************
* This file includes functions that output io mapping information
* to files in XML format
*******************************************************************/
#include <chrono>
#include <ctime>
#include <fstream>
/* Headers from vtrutil library */
#include "vtr_assert.h"
#include "vtr_log.h"
#include "vtr_time.h"
/* Headers from openfpgautil library */
#include "openfpga_digest.h"
/* Headers from archopenfpga library */
#include "openfpga_naming.h"
#include "openfpga_version.h"
#include "build_io_mapping_info.h"
#include "write_xml_io_mapping.h"
/* begin namespace openfpga */
namespace openfpga {
/********************************************************************
* This function write header information to an I/O mapping file
*******************************************************************/
static
void write_io_mapping_xml_file_head(std::fstream& fp) {
valid_file_stream(fp);
auto end = std::chrono::system_clock::now();
std::time_t end_time = std::chrono::system_clock::to_time_t(end);
fp << "<!--" << std::endl;
fp << "\t- I/O mapping" << std::endl;
fp << "\t- Version: " << openfpga::VERSION << std::endl;
fp << "\t- Date: " << std::ctime(&end_time) ;
fp << "-->" << std::endl;
fp << std::endl;
}
/********************************************************************
* Write an io mapping pair to an XML file
*
* Return:
* - 0 if succeed
* - 1 if critical errors occured
*******************************************************************/
static
int write_io_mapping_pair_to_xml_file(std::fstream& fp,
const IoMap& io_map,
const IoMapId& io_map_id,
int xml_hierarchy_depth) {
if (false == valid_file_stream(fp)) {
return 1;
}
write_tab_to_file(fp, xml_hierarchy_depth);
BasicPort io_port = io_map.io_port(io_map_id);
fp << "<io ";
fp << "name=\"" << io_port.get_name().c_str() << "[" << io_port.get_lsb() << ":" << io_port.get_msb() << "]" << "\"";
VTR_ASSERT(1 == io_map.io_net(io_map_id).get_width());
fp << " net=\"" << io_map.io_net(io_map_id).get_name().c_str() << "\"";
if (io_map.is_io_input(io_map_id)) {
fp << " dir=\"" << "input" << "\"";
} else {
VTR_ASSERT_SAFE(io_map.is_io_output(io_map_id));
fp << " dir=\"" << "output" << "\"";
}
fp << "/>\n";
return 0;
}
/********************************************************************
* Write the io mapping information to an XML file
* Notes:
* - This file is designed for users to learn
* - what nets are mapped to each I/O is mapped, io[0] -> netA
* - what directionality is applied to each I/O, io[0] -> input
*
* Return:
* - 0 if succeed
* - 1 if critical errors occured
*******************************************************************/
int write_io_mapping_to_xml_file(const IoMap& io_map,
const std::string& fname,
const bool& verbose) {
/* Ensure that we have a valid file name */
if (true == fname.empty()) {
VTR_LOG_ERROR("Received empty file name to output io_mapping!\n\tPlease specify a valid file name.\n");
return 1;
}
std::string timer_message = std::string("Write I/O mapping into xml file '") + fname + std::string("'");
vtr::ScopedStartFinishTimer timer(timer_message);
/* Create the file stream */
std::fstream fp;
fp.open(fname, std::fstream::out | std::fstream::trunc);
check_file_stream(fname.c_str(), fp);
/* Write XML head */
write_io_mapping_xml_file_head(fp);
int xml_hierarchy_depth = 0;
fp << "<io_mapping>\n";
/* Output fabric bitstream to the file */
int status = 0;
int io_map_cnt = 0;
for (const auto& io_map_id : io_map.io_map()) {
status = write_io_mapping_pair_to_xml_file(fp,
io_map, io_map_id,
xml_hierarchy_depth + 1);
io_map_cnt++;
if (1 == status) {
break;
}
}
/* Print an end to the file here */
fp << "</io_mapping>\n";
VTR_LOGV(verbose,
"Outputted %d I/O mapping to file '%s'\n",
io_map_cnt,
fname.c_str());
/* Close file handler */
fp.close();
return status;
}
} /* end namespace openfpga */

View File

@ -0,0 +1,25 @@
#ifndef WRITE_XML_IO_MAPPING_H
#define WRITE_XML_IO_MAPPING_H
/********************************************************************
* Include header files that are required by function declaration
*******************************************************************/
#include <string>
#include <vector>
#include "vpr_context.h"
#include "io_map.h"
/********************************************************************
* Function declaration
*******************************************************************/
/* begin namespace openfpga */
namespace openfpga {
int write_io_mapping_to_xml_file(const IoMap& io_map,
const std::string& fname,
const bool& verbose);
} /* end namespace openfpga */
#endif

View File

@ -20,6 +20,7 @@
/* Headers from openfpgautil library */
#include "openfpga_port.h"
#include "openfpga_digest.h"
#include "openfpga_scale.h"
#include "sdc_writer_naming.h"
#include "sdc_writer_utils.h"
@ -59,6 +60,7 @@ void print_pnr_sdc_clock_port(std::fstream& fp,
*******************************************************************/
static
void print_pnr_sdc_global_clock_ports(std::fstream& fp,
const float& time_unit,
const ModuleManager& module_manager,
const ModuleId& top_module,
const FabricGlobalPortInfo& fabric_global_port_info,
@ -103,7 +105,7 @@ void print_pnr_sdc_global_clock_ports(std::fstream& fp,
print_pnr_sdc_clock_port(fp,
port_to_constrain,
clock_period);
clock_period / time_unit);
}
}
}
@ -118,6 +120,7 @@ void print_pnr_sdc_global_clock_ports(std::fstream& fp,
*******************************************************************/
static
void print_pnr_sdc_global_non_clock_ports(std::fstream& fp,
const float& time_unit,
const float& operating_critical_path_delay,
const ModuleManager& module_manager,
const ModuleId& top_module,
@ -144,7 +147,7 @@ void print_pnr_sdc_global_non_clock_ports(std::fstream& fp,
print_pnr_sdc_clock_port(fp,
port_to_constrain,
clock_period);
clock_period / time_unit);
}
}
}
@ -161,6 +164,7 @@ 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& time_unit,
const ModuleManager& module_manager,
const ModuleId& top_module,
const FabricGlobalPortInfo& global_ports,
@ -183,12 +187,15 @@ void print_pnr_sdc_global_ports(const std::string& sdc_dir,
/* Generate the descriptions*/
print_sdc_file_header(fp, std::string("Clock contraints for PnR"));
print_pnr_sdc_global_clock_ports(fp,
/* Print time unit for the SDC file */
print_sdc_timescale(fp, time_unit_to_string(time_unit));
print_pnr_sdc_global_clock_ports(fp, time_unit,
module_manager, top_module,
global_ports, sim_setting);
if (true == constrain_non_clock_port) {
print_pnr_sdc_global_non_clock_ports(fp,
print_pnr_sdc_global_non_clock_ports(fp, time_unit,
1./sim_setting.default_operating_clock_frequency(),
module_manager, top_module,
global_ports);

View File

@ -18,6 +18,7 @@
namespace openfpga {
void print_pnr_sdc_global_ports(const std::string& sdc_dir,
const float& time_unit,
const ModuleManager& module_manager,
const ModuleId& top_module,
const FabricGlobalPortInfo& global_ports,

View File

@ -336,6 +336,7 @@ 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(),
sdc_options.time_unit(),
module_manager, top_module, global_ports,
sim_setting,
sdc_options.constrain_non_clock_global_port());

View File

@ -32,8 +32,7 @@
#include "verilog_api.h"
/* begin namespace openfpga */
namespace openfpga
{
namespace openfpga {
/********************************************************************
* A top-level function of FPGA-Verilog which focuses on fabric Verilog generation
@ -141,29 +140,26 @@ void fpga_fabric_verilog(ModuleManager &module_manager,
}
/********************************************************************
* A top-level function of FPGA-Verilog which focuses on fabric Verilog generation
* A top-level function of FPGA-Verilog which focuses on full testbench generation
* This function will generate
* - A wrapper module, which encapsulate the FPGA module in a Verilog module which have the same port as the input benchmark
* - Testbench, where a FPGA module is configured with a bitstream and then driven by input vectors
* - Pre-configured testbench, which can skip the configuration phase and pre-configure the FPGA module.
* 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
********************************************************************/
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) {
int fpga_verilog_full_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 std::string& bitstream_file,
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");
vtr::ScopedStartFinishTimer timer("Write Verilog full testbenches for FPGA fabric\n");
std::string src_dir_path = format_dir_path(options.output_directory());
@ -178,71 +174,22 @@ int fpga_verilog_testbench(const ModuleManager &module_manager,
print_verilog_simulation_preprocessing_flags(std::string(src_dir_path),
options);
/* 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);
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()) {
/* Generate top-level testbench using random vectors */
std::string random_top_testbench_file_path = src_dir_path + netlist_name + std::string(RANDOM_TOP_TESTBENCH_VERILOG_FILE_POSTFIX);
print_verilog_random_top_testbench(netlist_name,
random_top_testbench_file_path,
atom_ctx,
netlist_annotation,
module_manager,
fabric_global_port_info,
pin_constraints,
simulation_setting,
options.explicit_port_mapping());
}
/* Generate full testbench for verification, including configuration phase and operating phase */
if (true == options.print_top_testbench()) {
std::string top_testbench_file_path = src_dir_path + netlist_name + std::string(AUTOCHECK_TOP_TESTBENCH_VERILOG_FILE_POSTFIX);
print_verilog_top_testbench(module_manager,
bitstream_manager, fabric_bitstream,
circuit_lib,
config_protocol,
fabric_global_port_info,
atom_ctx, place_ctx,
pin_constraints,
io_location_map,
netlist_annotation,
netlist_name,
top_testbench_file_path,
simulation_setting,
options);
}
/* Generate exchangeable files which contains simulation settings */
if (true == options.print_simulation_ini()) {
std::string simulation_ini_file_name = options.simulation_ini_path();
VTR_ASSERT(true != options.simulation_ini_path().empty());
print_verilog_simulation_info(simulation_ini_file_name,
netlist_name,
src_dir_path,
atom_ctx, place_ctx, io_location_map,
module_manager,
config_protocol.type(),
bitstream_manager.num_bits(),
simulation_setting.num_clock_cycles(),
simulation_setting.programming_clock_frequency(),
simulation_setting.default_operating_clock_frequency());
}
std::string top_testbench_file_path = src_dir_path + netlist_name + std::string(AUTOCHECK_TOP_TESTBENCH_VERILOG_FILE_POSTFIX);
print_verilog_full_testbench(module_manager,
bitstream_manager, fabric_bitstream,
circuit_lib,
config_protocol,
fabric_global_port_info,
atom_ctx, place_ctx,
pin_constraints,
bitstream_file,
io_location_map,
netlist_annotation,
netlist_name,
top_testbench_file_path,
simulation_setting,
options);
/* Generate a Verilog file including all the netlists that have been generated */
print_verilog_testbench_include_netlists(src_dir_path,
@ -253,4 +200,141 @@ int fpga_verilog_testbench(const ModuleManager &module_manager,
return status;
}
/********************************************************************
* A top-level function of FPGA-Verilog which focuses on full testbench generation
* This function will generate
* - A wrapper module, which encapsulate the FPGA module in a Verilog module which have the same port as the input benchmark
********************************************************************/
int fpga_verilog_preconfigured_fabric_wrapper(const ModuleManager &module_manager,
const BitstreamManager &bitstream_manager,
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 ConfigProtocol &config_protocol,
const VerilogTestbenchOption &options) {
vtr::ScopedStartFinishTimer timer("Write a wrapper module for a preconfigured FPGA fabric\n");
std::string src_dir_path = format_dir_path(options.output_directory());
std::string netlist_name = atom_ctx.nlist.netlist_name();
int status = CMD_EXEC_SUCCESS;
/* Create directories */
create_directory(src_dir_path);
/* Generate wrapper module for FPGA fabric (mapped by the input benchmark and pre-configured testbench for verification */
std::string formal_verification_top_netlist_file_path = src_dir_path + netlist_name + std::string(FORMAL_VERIFICATION_VERILOG_FILE_POSTFIX);
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);
return status;
}
/********************************************************************
* A top-level function of FPGA-Verilog which focuses on fabric Verilog generation
* This function will generate
* - Pre-configured testbench, which can skip the configuration phase and pre-configure the FPGA module.
* This testbench is created for quick verification and formal verification purpose.
********************************************************************/
int fpga_verilog_preconfigured_testbench(const ModuleManager &module_manager,
const AtomContext &atom_ctx,
const PinConstraints& pin_constraints,
const FabricGlobalPortInfo &fabric_global_port_info,
const VprNetlistAnnotation &netlist_annotation,
const SimulationSetting &simulation_setting,
const VerilogTestbenchOption &options) {
vtr::ScopedStartFinishTimer timer("Write Verilog testbenches for a preconfigured FPGA fabric\n");
std::string src_dir_path = format_dir_path(options.output_directory());
std::string netlist_name = atom_ctx.nlist.netlist_name();
int status = CMD_EXEC_SUCCESS;
/* Create directories */
create_directory(src_dir_path);
/* Output preprocessing flags for HDL simulations */
print_verilog_simulation_preprocessing_flags(std::string(src_dir_path),
options);
/* Generate top-level testbench using random vectors */
std::string random_top_testbench_file_path = src_dir_path + netlist_name + std::string(RANDOM_TOP_TESTBENCH_VERILOG_FILE_POSTFIX);
print_verilog_random_top_testbench(netlist_name,
random_top_testbench_file_path,
atom_ctx,
netlist_annotation,
module_manager,
fabric_global_port_info,
pin_constraints,
simulation_setting,
options);
/* Generate a Verilog file including all the netlists that have been generated */
print_verilog_testbench_include_netlists(src_dir_path,
netlist_name,
options.fabric_netlist_file_path(),
options.reference_benchmark_file_path());
return status;
}
/********************************************************************
* A top-level function of FPGA-Verilog which focuses on fabric Verilog generation
* This function will generate
* - An interchangable file containing simulation task configuration
********************************************************************/
int fpga_verilog_simulation_task_info(const ModuleManager &module_manager,
const BitstreamManager &bitstream_manager,
const AtomContext &atom_ctx,
const PlacementContext &place_ctx,
const IoLocationMap &io_location_map,
const SimulationSetting &simulation_setting,
const ConfigProtocol &config_protocol,
const VerilogTestbenchOption &options) {
vtr::ScopedStartFinishTimer timer("Write interchangeable simulation task configuration\n");
std::string src_dir_path = format_dir_path(options.output_directory());
std::string netlist_name = atom_ctx.nlist.netlist_name();
int status = CMD_EXEC_SUCCESS;
/* Create directories */
create_directory(src_dir_path);
/* Generate exchangeable files which contains simulation settings */
std::string simulation_ini_file_name = options.simulation_ini_path();
VTR_ASSERT(true != options.simulation_ini_path().empty());
print_verilog_simulation_info(simulation_ini_file_name,
netlist_name,
src_dir_path,
atom_ctx, place_ctx, io_location_map,
module_manager,
config_protocol.type(),
bitstream_manager.num_bits(),
simulation_setting.num_clock_cycles(),
simulation_setting.programming_clock_frequency(),
simulation_setting.default_operating_clock_frequency());
return status;
}
} /* end namespace openfpga */

View File

@ -43,20 +43,49 @@ void fpga_fabric_verilog(ModuleManager& module_manager,
const DeviceRRGSB& device_rr_gsb,
const FabricVerilogOption& 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);
int fpga_verilog_full_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 std::string& bitstream_file,
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_preconfigured_fabric_wrapper(const ModuleManager &module_manager,
const BitstreamManager &bitstream_manager,
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 ConfigProtocol &config_protocol,
const VerilogTestbenchOption &options);
int fpga_verilog_preconfigured_testbench(const ModuleManager &module_manager,
const AtomContext &atom_ctx,
const PinConstraints& pin_constraints,
const FabricGlobalPortInfo &fabric_global_port_info,
const VprNetlistAnnotation &netlist_annotation,
const SimulationSetting &simulation_setting,
const VerilogTestbenchOption &options);
int fpga_verilog_simulation_task_info(const ModuleManager &module_manager,
const BitstreamManager &bitstream_manager,
const AtomContext &atom_ctx,
const PlacementContext &place_ctx,
const IoLocationMap &io_location_map,
const SimulationSetting &simulation_setting,
const ConfigProtocol &config_protocol,
const VerilogTestbenchOption &options);
} /* end namespace openfpga */

View File

@ -56,12 +56,13 @@ void print_verilog_top_random_testbench_ports(std::fstream& fp,
const std::string& circuit_name,
const std::vector<std::string>& clock_port_names,
const AtomContext& atom_ctx,
const VprNetlistAnnotation& netlist_annotation) {
const VprNetlistAnnotation& netlist_annotation,
const e_verilog_default_net_type& default_net_type) {
/* Validate the file stream */
valid_file_stream(fp);
print_verilog_default_net_type_declaration(fp,
VERILOG_DEFAULT_NET_TYPE_NONE);
default_net_type);
/* Print the declaration for the module */
fp << "module " << circuit_name << FORMAL_RANDOM_TOP_TESTBENCH_POSTFIX << ";" << std::endl;
@ -278,7 +279,7 @@ void print_verilog_random_top_testbench(const std::string& circuit_name,
const FabricGlobalPortInfo& global_ports,
const PinConstraints& pin_constraints,
const SimulationSetting& simulation_parameters,
const bool& explicit_port_mapping) {
const VerilogTestbenchOption &options) {
std::string timer_message = std::string("Write configuration-skip testbench for FPGA top-level Verilog netlist implemented by '") + circuit_name.c_str() + std::string("'");
/* Start time count */
@ -299,17 +300,17 @@ void print_verilog_random_top_testbench(const std::string& circuit_name,
std::vector<std::string> clock_port_names = find_atom_netlist_clock_port_names(atom_ctx.nlist, netlist_annotation);
/* Start of testbench */
print_verilog_top_random_testbench_ports(fp, circuit_name, clock_port_names, atom_ctx, netlist_annotation);
print_verilog_top_random_testbench_ports(fp, circuit_name, clock_port_names, atom_ctx, netlist_annotation, options.default_net_type());
/* Call defined top-level module */
print_verilog_random_testbench_fpga_instance(fp, circuit_name,
atom_ctx, netlist_annotation,
explicit_port_mapping);
options.explicit_port_mapping());
/* Call defined benchmark */
print_verilog_top_random_testbench_benchmark_instance(fp, circuit_name,
atom_ctx, netlist_annotation,
explicit_port_mapping);
options.explicit_port_mapping());
/* Find clock port to be used */
std::vector<BasicPort> clock_ports = generate_verilog_testbench_clock_port(clock_port_names, std::string(DEFAULT_CLOCK_NAME));
@ -359,7 +360,6 @@ void print_verilog_random_top_testbench(const std::string& circuit_name,
/* Add Icarus requirement */
print_verilog_timeout_and_vcd(fp,
std::string(ICARUS_SIMULATOR_FLAG),
std::string(circuit_name + std::string(FORMAL_RANDOM_TOP_TESTBENCH_POSTFIX)),
std::string(circuit_name + std::string("_formal.vcd")),
std::string(FORMAL_TB_SIM_START_PORT_NAME),

View File

@ -10,6 +10,7 @@
#include "module_manager.h"
#include "fabric_global_port_info.h"
#include "simulation_setting.h"
#include "verilog_testbench_options.h"
/********************************************************************
* Function declaration
@ -26,7 +27,7 @@ void print_verilog_random_top_testbench(const std::string& circuit_name,
const FabricGlobalPortInfo& global_ports,
const PinConstraints& pin_constraints,
const SimulationSetting& simulation_parameters,
const bool& explicit_port_mapping);
const VerilogTestbenchOption &options);
} /* end namespace openfpga */

View File

@ -442,7 +442,7 @@ int print_verilog_preconfig_top_module(const ModuleManager &module_manager,
const VprNetlistAnnotation &netlist_annotation,
const std::string &circuit_name,
const std::string &verilog_fname,
const bool &explicit_port_mapping) {
const VerilogTestbenchOption& options) {
std::string timer_message = std::string("Write pre-configured FPGA top-level Verilog netlist for design '") + circuit_name + std::string("'");
int status = CMD_EXEC_SUCCESS;
@ -462,7 +462,7 @@ int print_verilog_preconfig_top_module(const ModuleManager &module_manager,
print_verilog_file_header(fp, title);
print_verilog_default_net_type_declaration(fp,
VERILOG_DEFAULT_NET_TYPE_NONE);
options.default_net_type());
/* Print module declaration and ports */
print_verilog_preconfig_top_module_ports(fp, circuit_name, atom_ctx, netlist_annotation);
@ -477,7 +477,7 @@ int print_verilog_preconfig_top_module(const ModuleManager &module_manager,
/* 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);
options.explicit_port_mapping());
/* Find clock ports in benchmark */
std::vector<std::string> benchmark_clock_port_names = find_atom_netlist_clock_port_names(atom_ctx.nlist, netlist_annotation);

View File

@ -15,6 +15,7 @@
#include "fabric_global_port_info.h"
#include "config_protocol.h"
#include "vpr_netlist_annotation.h"
#include "verilog_testbench_options.h"
/********************************************************************
* Function declaration
@ -35,7 +36,7 @@ int print_verilog_preconfig_top_module(const ModuleManager& module_manager,
const VprNetlistAnnotation& netlist_annotation,
const std::string& circuit_name,
const std::string& verilog_fname,
const bool& explicit_port_mapping);
const VerilogTestbenchOption& options);
} /* end namespace openfpga */

View File

@ -23,6 +23,7 @@ VerilogTestbenchOption::VerilogTestbenchOption() {
explicit_port_mapping_ = false;
support_icarus_simulator_ = false;
include_signal_init_ = false;
default_net_type_ = VERILOG_DEFAULT_NET_TYPE_NONE;
verbose_output_ = false;
}
@ -77,6 +78,10 @@ bool VerilogTestbenchOption::support_icarus_simulator() const {
return support_icarus_simulator_;
}
e_verilog_default_net_type VerilogTestbenchOption::default_net_type() const {
return default_net_type_;
}
bool VerilogTestbenchOption::verbose_output() const {
return verbose_output_;
}
@ -141,6 +146,20 @@ void VerilogTestbenchOption::set_support_icarus_simulator(const bool& enabled) {
support_icarus_simulator_ = enabled;
}
void VerilogTestbenchOption::set_default_net_type(const std::string& default_net_type) {
/* Decode from net type string */;
if (default_net_type == std::string(VERILOG_DEFAULT_NET_TYPE_STRING[VERILOG_DEFAULT_NET_TYPE_NONE])) {
default_net_type_ = VERILOG_DEFAULT_NET_TYPE_NONE;
} else if (default_net_type == std::string(VERILOG_DEFAULT_NET_TYPE_STRING[VERILOG_DEFAULT_NET_TYPE_WIRE])) {
default_net_type_ = VERILOG_DEFAULT_NET_TYPE_WIRE;
} else {
VTR_LOG_WARN("Invalid default net type: '%s'! Expect ['%s'|'%s']\n",
default_net_type.c_str(),
VERILOG_DEFAULT_NET_TYPE_STRING[VERILOG_DEFAULT_NET_TYPE_NONE],
VERILOG_DEFAULT_NET_TYPE_STRING[VERILOG_DEFAULT_NET_TYPE_WIRE]);
}
}
void VerilogTestbenchOption::set_verbose_output(const bool& enabled) {
verbose_output_ = enabled;
}

View File

@ -5,6 +5,7 @@
* Include header files required by the data structure definition
*******************************************************************/
#include <string>
#include "verilog_port_types.h"
/* Begin namespace openfpga */
namespace openfpga {
@ -34,6 +35,7 @@ class VerilogTestbenchOption {
bool explicit_port_mapping() const;
bool include_signal_init() const;
bool support_icarus_simulator() const;
e_verilog_default_net_type default_net_type() const;
bool verbose_output() const;
public: /* Public validator */
bool validate() const;
@ -58,6 +60,7 @@ class VerilogTestbenchOption {
void set_explicit_port_mapping(const bool& enabled);
void set_include_signal_init(const bool& enabled);
void set_support_icarus_simulator(const bool& enabled);
void set_default_net_type(const std::string& default_net_type);
void set_verbose_output(const bool& enabled);
private: /* Internal Data */
std::string output_directory_;
@ -72,6 +75,7 @@ class VerilogTestbenchOption {
bool explicit_port_mapping_;
bool support_icarus_simulator_;
bool include_signal_init_;
e_verilog_default_net_type default_net_type_;
bool verbose_output_;
};

View File

@ -300,7 +300,6 @@ void print_verilog_testbench_connect_fpga_ios(std::fstream& fp,
* Note that: these codes are tuned for Icarus simulator!!!
*******************************************************************/
void print_verilog_timeout_and_vcd(std::fstream& fp,
const std::string& icarus_preprocessing_flag,
const std::string& module_name,
const std::string& vcd_fname,
const std::string& simulation_start_counter_name,
@ -309,20 +308,14 @@ void print_verilog_timeout_and_vcd(std::fstream& fp,
/* Validate the file stream */
valid_file_stream(fp);
/* The following verilog codes are tuned for Icarus */
print_verilog_preprocessing_flag(fp, icarus_preprocessing_flag);
print_verilog_comment(fp, std::string("----- Begin Icarus requirement -------"));
print_verilog_comment(fp, std::string("----- Begin output waveform to VCD file-------"));
fp << "\tinitial begin" << std::endl;
fp << "\t\t$dumpfile(\"" << vcd_fname << "\");" << std::endl;
fp << "\t\t$dumpvars(1, " << module_name << ");" << std::endl;
fp << "\tend" << std::endl;
/* Condition ends for the Icarus requirement */
print_verilog_endif(fp);
print_verilog_comment(fp, std::string("----- END Icarus requirement -------"));
print_verilog_comment(fp, std::string("----- END output waveform to VCD file -------"));
/* Add an empty line as splitter */
fp << std::endl;

View File

@ -55,7 +55,6 @@ void print_verilog_testbench_connect_fpga_ios(std::fstream& fp,
const size_t& unused_io_value);
void print_verilog_timeout_and_vcd(std::fstream& fp,
const std::string& icarus_preprocessing_flag,
const std::string& module_name,
const std::string& vcd_fname,
const std::string& simulation_start_counter_name,

File diff suppressed because it is too large Load Diff

View File

@ -26,7 +26,7 @@
/* begin namespace openfpga */
namespace openfpga {
void print_verilog_top_testbench(const ModuleManager& module_manager,
int print_verilog_full_testbench(const ModuleManager& module_manager,
const BitstreamManager& bitstream_manager,
const FabricBitstream& fabric_bitstream,
const CircuitLibrary& circuit_lib,
@ -35,6 +35,7 @@ void print_verilog_top_testbench(const ModuleManager& module_manager,
const AtomContext& atom_ctx,
const PlacementContext& place_ctx,
const PinConstraints& pin_constraints,
const std::string& bitstream_file,
const IoLocationMap& io_location_map,
const VprNetlistAnnotation& netlist_annotation,
const std::string& circuit_name,

View File

@ -724,14 +724,20 @@ std::string generate_verilog_constant_values(const std::vector<size_t>& const_va
* Generate a verilog port with a deposite of constant values
********************************************************************/
std::string generate_verilog_port_constant_values(const BasicPort& output_port,
const std::vector<size_t>& const_values) {
const std::vector<size_t>& const_values,
const bool& is_register) {
std::string port_str;
/* Must check: the port width matches */
VTR_ASSERT( const_values.size() == output_port.get_width() );
port_str = generate_verilog_port(VERILOG_PORT_CONKT, output_port);
port_str += " = ";
if (is_register) {
port_str += " <= ";
} else {
VTR_ASSERT_SAFE(!is_register);
port_str += " = ";
}
port_str += generate_verilog_constant_values(const_values);
return port_str;
}

View File

@ -108,7 +108,8 @@ std::string generate_verilog_constant_values(const std::vector<size_t>& const_va
const bool& short_constant = true);
std::string generate_verilog_port_constant_values(const BasicPort& output_port,
const std::vector<size_t>& const_values);
const std::vector<size_t>& const_values,
const bool& is_register = false);
void print_verilog_wire_constant_values(std::fstream& fp,
const BasicPort& output_port,

View File

@ -28,6 +28,8 @@ namespace openfpga {
* - sink is an input of a primitive pb_type
*
* Note:
* - This function is applicable ONLY to single-mode pb_types!!! Because their routing traces
* are deterministic: there is only 1 valid path from a source pin to a sink pin!!!
* - If there is a fan-out of the current source pb graph pin is not a direct interconnection
* the direct search should stop.
* - This function is designed for pb graph without local routing
@ -58,6 +60,11 @@ bool rec_direct_search_sink_pb_graph_pins(const t_pb_graph_pin* source_pb_pin,
std::vector<t_pb_graph_pin*> sink_pb_pins_to_search;
/* Only support single-mode pb_type!!! */
//if (1 != source_pb_pin->parent_node->pb_type->num_modes) {
// return false;
//}
for (int iedge = 0; iedge < source_pb_pin->num_output_edges; ++iedge) {
if (DIRECT_INTERC != source_pb_pin->output_edges[iedge]->interconnect->type) {
return false;
@ -230,6 +237,38 @@ std::vector<t_pb_graph_pin*> find_routed_pb_graph_pins_atom_net(const t_pb* pb,
return sink_pb_pins;
}
/***************************************************************************************
* This function will find the actual routing traces of the demanded net
* There is a specific search space applied when searching the routing traces:
* - ONLY applicable to the pb_pin of top-level pb_graph_node
* - candidate can be limited to a set of pb pins
***************************************************************************************/
static
std::vector<int> find_pb_route_by_atom_net(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;
for (int pin = 0; pin < pb->pb_graph_node->total_pb_pins; ++pin) {
/* Bypass unused pins */
if ((0 == pb->pb_route.count(pin)) || (AtomNetId::INVALID() == pb->pb_route.at(pin).atom_net_id)) {
continue;
}
/* Get the driver pb pin id, it must be valid */
if (atom_net_id != pb->pb_route.at(pin).atom_net_id) {
continue;
}
if (source_pb_pin->port == pb->pb_route.at(pin).pb_graph_pin->port) {
pb_route_indices.push_back(pin);
}
}
return pb_route_indices;
}
/***************************************************************************************
* This function will find the actual source_pb_pin that is mapped by packed in the pb route
* As the inputs of clustered block may be renamed during routing,
@ -422,18 +461,7 @@ void add_lb_router_nets(LbRouter& lb_router,
AtomNetId atom_net_id = pb_pin_mapped_nets[source_pb_pin];
/* 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;
}
}
std::string constrained_net_name = design_constraints.find_constrained_pin_net(std::string(lb_type->pb_type->name), BasicPort(std::string(source_pb_pin->port->name), source_pb_pin->pin_number, source_pb_pin->pin_number));
/* Find the constrained net mapped to this pin in clustering results */
AtomNetId constrained_atom_net_id = AtomNetId::INVALID();
@ -443,16 +471,21 @@ void add_lb_router_nets(LbRouter& lb_router,
* - 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());
}
if ( (!design_constraints.unconstrained_net(constrained_net_name))
&& (!design_constraints.unmapped_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(false == atom_ctx.nlist.valid_net_id(constrained_atom_net_id));
VTR_LOGV(verbose,
"Accept net '%s' to be constrained on pin '%s[%d]' during repacking\n",
constrained_net_name.c_str(),
source_pb_pin->port->name,
source_pb_pin->pin_number);
}
} else {
VTR_ASSERT_SAFE(constrained_net_name.empty());
} else if (design_constraints.unconstrained_net(constrained_net_name)) {
constrained_atom_net_id = atom_net_id;
}
@ -486,18 +519,35 @@ void add_lb_router_nets(LbRouter& lb_router,
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));
/* Output verbose messages for debugging only */
VTR_LOGV(verbose,
"Pb route for Net %s:\n",
atom_ctx.nlist.net_name(atom_net_id_to_route).c_str());
/* 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
*
* When there is a pin constraint applied. The routing trace
* - Find the routing traces from packing results which is mapped to the net
* with the same port constraints
*/
std::vector<int> pb_route_indices = find_pb_route_remapped_source_pb_pin(pb, source_pb_pin, atom_net_id_to_route);
std::vector<int> pb_route_indices;
if (design_constraints.unconstrained_net(constrained_net_name)) {
pb_route_indices = find_pb_route_remapped_source_pb_pin(pb, source_pb_pin, atom_net_id_to_route);
} else {
VTR_ASSERT_SAFE(!design_constraints.unconstrained_net(constrained_net_name));
pb_route_indices = find_pb_route_by_atom_net(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()) {
VTR_LOGV(verbose,
"Bypass routing due to no routing traces found\n");
continue;
} else {
VTR_ASSERT(1 == pb_route_indices.size());
@ -512,9 +562,6 @@ void add_lb_router_nets(LbRouter& lb_router,
VTR_ASSERT(sink_lb_rr_nodes.size() == sink_pb_graph_pins.size());
/* Output verbose messages for debugging only */
VTR_LOGV(verbose,
"Pb route for Net %s:\n",
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(),

View File

@ -0,0 +1,49 @@
/////////////////////////////////////////
// Functionality: Two 2-input AND with clocked
// and combinational outputs
// Each of which are controlled by different clocks
// Author: Xifan Tang
////////////////////////////////////////
`timescale 1ns / 1ps
module and2_latch_2clock(
a0,
b0,
clk0,
a1,
b1,
clk1,
c0,
d0,
c1,
d1);
input wire clk0;
input wire a0;
input wire b0;
output wire c0;
output reg d0;
input wire clk1;
input wire a1;
input wire b1;
output wire c1;
output reg d1;
assign c0 = a0 & b0;
always @(posedge clk0) begin
d0 <= c0;
end
assign c1 = a1 & b1;
always @(posedge clk1) begin
d1 <= c1;
end
endmodule

View File

@ -0,0 +1,17 @@
// ------------------------------
// Design Name: Blinking
// Functionality: 1-bit blinking
// ------------------------------
module blinking(
clk,
out
);
input clk;
output out;
always @(posedge clk) begin
out = ~out;
end
endmodule

View File

@ -0,0 +1,58 @@
//-----------------------------------------------------
// Design Name : dual_port_ram_16k
// File Name : dual_port_ram_16k.v
// Function : Dual port RAM 2048x8bit
// Coder : Xifan Tang
//-----------------------------------------------------
module dual_port_ram_16k (
input clk,
input wen,
input ren,
input [10:0] waddr,
input [10:0] raddr,
input [7:0] din,
output [7:0] dout
);
dual_port_sram_16kb memory_0 (
.wclk (clk),
.wen (wen),
.waddr (waddr),
.data_in (din),
.rclk (clk),
.ren (ren),
.raddr (raddr),
.data_out (dout) );
endmodule
module dual_port_sram_16kb (
input wclk,
input wen,
input [10:0] waddr,
input [7:0] data_in,
input rclk,
input ren,
input [10:0] raddr,
output [7:0] data_out
);
reg [7:0] ram[2047:0];
reg [7:0] internal;
assign data_out = internal;
always @(posedge wclk) begin
if(wen) begin
ram[waddr] <= data_in;
end
end
always @(posedge rclk) begin
if(ren) begin
internal <= ram[raddr];
end
end
endmodule

View File

@ -0,0 +1,58 @@
//-----------------------------------------------------
// Design Name : dual_port_ram_1k
// File Name : dual_port_ram_1k.v
// Function : Dual port RAM 128x8bit
// Coder : Xifan Tang
//-----------------------------------------------------
module dual_port_ram_1k (
input clk,
input wen,
input ren,
input [6:0] waddr,
input [6:0] raddr,
input [7:0] din,
output [7:0] dout
);
dual_port_sram_1kb memory_0 (
.wclk (clk),
.wen (wen),
.waddr (waddr),
.data_in (din),
.rclk (clk),
.ren (ren),
.raddr (raddr),
.data_out (dout) );
endmodule
module dual_port_sram_1kb (
input wclk,
input wen,
input [6:0] waddr,
input [7:0] data_in,
input rclk,
input ren,
input [6:0] raddr,
output [7:0] data_out
);
reg [7:0] ram[127:0];
reg [7:0] internal;
assign data_out = internal;
always @(posedge wclk) begin
if(wen) begin
ram[waddr] <= data_in;
end
end
always @(posedge rclk) begin
if(ren) begin
internal <= ram[raddr];
end
end
endmodule

View File

@ -0,0 +1,97 @@
// FIFO buffer implemented with synchronous dual-port block ram
// Reference:
// https://embeddedthoughts.com/2016/07/13/fifo-buffer-using-block-ram-on-a-xilinx-spartan-3-fpga/
module fifo
#( parameter ADDRESS_WIDTH = 4, // number of words in ram
DATA_WIDTH = 4 // number of bits in word
)
// IO ports
(
input wire clk, reset,
input wire read, write,
input wire [DATA_WIDTH-1:0] write_data,
output wire empty, full,
output wire [DATA_WIDTH-1:0] read_data
);
// internal signal declarations
reg [ADDRESS_WIDTH-1:0] write_address_reg, write_address_next, write_address_after;
reg [ADDRESS_WIDTH-1:0] read_address_reg, read_address_next, read_address_after;
reg full_reg, empty_reg, full_next, empty_next;
wire write_en;
// write enable is asserted when write input is asserted and FIFO isn't full
assign write_en = write & ~full_reg;
// instantiate synchronous block ram
sync_dual_port_ram #(.ADDRESS_WIDTH(ADDRESS_WIDTH), .DATA_WIDTH(DATA_WIDTH)) ram
(.clk(clk), .write_en(write_en), .write_address(write_address_reg),
.read_address(read_address_reg), .write_data_in(write_data),
.write_data_out(), .read_data_out(read_data));
// register for address pointers, full/empty status
always @(posedge clk, posedge reset)
if (reset)
begin
write_address_reg <= 0;
read_address_reg <= 0;
full_reg <= 1'b0;
empty_reg <= 1'b1;
end
else
begin
write_address_reg <= write_address_next;
read_address_reg <= read_address_next;
full_reg <= full_next;
empty_reg <= empty_next;
end
// next-state logic for address index values after read/write operations
always @*
begin
write_address_after = write_address_reg + 1;
read_address_after = read_address_reg + 1;
end
// next-state logic for address pointers
always @*
begin
// defaults
write_address_next = write_address_reg;
read_address_next = read_address_reg;
full_next = full_reg;
empty_next = empty_reg;
// if read input asserted and FIFO isn't empty
if(read && ~empty_reg && ~write)
begin
read_address_next = read_address_after; // read address moves forward
full_next = 1'b0; // FIFO isn't full if a read occured
if (read_address_after == write_address_reg) // if read address caught up with write address,
empty_next = 1'b1; // FIFO is empty
end
// if write input asserted and FIFO isn't full
else if(write && ~full_reg && ~read)
begin
write_address_next = write_address_after; // write address moves forward
empty_next = 1'b0; // FIFO isn't empty if write occured
if (write_address_after == read_address_reg) // if write address caught up with read address
full_next = 1'b1; // FIFO is full
end
// if write and read are asserted
else if(write && read)
begin
write_address_next = write_address_after; // write address moves forward
read_address_next = read_address_after; // read address moves forward
end
end
// assign full/empty status to output ports
assign full = full_reg;
assign empty = empty_reg;
endmodule

View File

@ -0,0 +1,35 @@
// Synchronous dual-port block ram
// Reference:
// https://embeddedthoughts.com/2016/07/13/fifo-buffer-using-block-ram-on-a-xilinx-spartan-3-fpga/
module sync_dual_port_ram
#( parameter ADDRESS_WIDTH = 4, // number of words in ram
DATA_WIDTH = 4 // number of bits in word
)
// IO ports
(
input wire clk, // clk for synchronous read/write
input wire write_en, // signal to enable synchronous write
input wire [ADDRESS_WIDTH-1:0] read_address, write_address, // inputs for dual port addresses
input wire [DATA_WIDTH-1:0] write_data_in, // input for data to write to ram
output wire [DATA_WIDTH-1:0] read_data_out, write_data_out // outputs for dual data ports
);
// internal signal declarations
reg [DATA_WIDTH-1:0] ram [2**ADDRESS_WIDTH-1:0]; // ADDRESS_WIDTH x DATA_WIDTH RAM declaration
reg [ADDRESS_WIDTH-1:0] read_address_reg, write_address_reg; // dual port address declarations
// synchronous write and address update
always @(posedge clk)
begin
if (write_en) // if write enabled
ram[write_address] <= write_data_in; // write data to ram and write_address
read_address_reg <= read_address; // store read_address to reg
write_address_reg <= write_address; // store write_address to reg
end
// assignments for two data out ports
assign read_data_out = ram[read_address_reg];
assign write_data_out = ram[write_address_reg];
endmodule

View File

@ -0,0 +1,22 @@
//-------------------------------------------------------
// Functionality: A 12-bit multiply-acculumate circuit
// Author: Xifan Tang
//-------------------------------------------------------
module mac_12(a, b, c, out);
parameter DATA_WIDTH = 12; /* declare a parameter. default required */
input [DATA_WIDTH - 1 : 0] a, b, c;
output [DATA_WIDTH - 1 : 0] out;
assign out = a * b + c;
endmodule

View File

@ -0,0 +1,22 @@
//-------------------------------------------------------
// Functionality: A 16-bit multiply-acculumate circuit
// Author: Xifan Tang
//-------------------------------------------------------
module mac_16(a, b, c, out);
parameter DATA_WIDTH = 16; /* declare a parameter. default required */
input [DATA_WIDTH - 1 : 0] a, b, c;
output [DATA_WIDTH - 1 : 0] out;
assign out = a * b + c;
endmodule

View File

@ -0,0 +1,22 @@
//-------------------------------------------------------
// Functionality: A 2-bit multiply-acculumate circuit
// Author: Xifan Tang
//-------------------------------------------------------
module mac_2(a, b, c, out);
parameter DATA_WIDTH = 2; /* declare a parameter. default required */
input [DATA_WIDTH - 1 : 0] a, b, c;
output [DATA_WIDTH - 1 : 0] out;
assign out = a * b + c;
endmodule

View File

@ -0,0 +1,22 @@
//-------------------------------------------------------
// Functionality: A 32-bit multiply-acculumate circuit
// Author: Xifan Tang
//-------------------------------------------------------
module mac_32(a, b, c, out);
parameter DATA_WIDTH = 32; /* declare a parameter. default required */
input [DATA_WIDTH - 1 : 0] a, b, c;
output [DATA_WIDTH - 1 : 0] out;
assign out = a * b + c;
endmodule

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