Merge branch 'master' of https://github.com/verilog-to-routing/vtr-verilog-to-routing
diff --git a/.readthedocs.yaml b/.readthedocs.yaml
new file mode 100644
index 0000000..098c5f6
--- /dev/null
+++ b/.readthedocs.yaml
@@ -0,0 +1,20 @@
+# .readthedocs.yml
+# Read the Docs configuration file
+# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
+
+# Required configuration file version
+version: 2
+
+# Build documentation in the docs/ directory with Sphinx
+sphinx:
+ builder: htmldir
+ configuration: doc/src/conf.py
+
+# Optionally build your docs in additional formats such as PDF and ePub
+formats: all
+
+# Optionally set the version of Python and requirements required to build your docs
+python:
+ version: 2
+ install:
+ - requirements: doc/requirements.txt
diff --git a/doc/requirements.txt b/doc/requirements.txt
index ea8c245..aa6547f 100644
--- a/doc/requirements.txt
+++ b/doc/requirements.txt
@@ -15,10 +15,16 @@
git+https://github.com/SymbiFlow/sphinxcontrib-markdown-symlinks@bd0869b817568dce268bcdc3dc3dc7a7bd40c392
#Handle references in bibtex format
-sphinxcontrib-bibtex
+#
+# To work around citations not resolving we need to use a version < 1 (0.4.2 is the latest), until
+# we upgrade to using sphinx-2.0
+sphinxcontrib-bibtex==0.4.2
#Work-around bug "AttributeError: 'Values' object has no attribute 'character_level_inline_markup'" with docutils 0.13.1
#See:
# * https://github.com/sphinx-doc/sphinx/issues/3951
# * https://sourceforge.net/p/docutils/bugs/304/
docutils>=0.14
+
+#Generates a project specific 404 (page not found) page
+sphinx-notfound-page
diff --git a/doc/src/conf.py b/doc/src/conf.py
index a50d72d..491ad5c 100644
--- a/doc/src/conf.py
+++ b/doc/src/conf.py
@@ -55,6 +55,7 @@
extensions = [
'sphinx.ext.todo',
'sphinx.ext.mathjax',
+ 'notfound.extension',
'sphinx_markdown_tables',
'sdcdomain',
'archdomain',
@@ -324,6 +325,19 @@
# If true, do not generate a @detailmenu in the "Top" node's menu.
#texinfo_no_detailmenu = False
+# -- Options for 404 page -------------------------------------------
+
+# sphinx-notfound-page
+# https://github.com/readthedocs/sphinx-notfound-page
+notfound_context = {
+ 'title': 'Page Not Found',
+ 'body': '''
+<h1>Page Not Found</h1>
+<p>Sorry, we couldn't find that page.</p>
+<p>Try using the search box or go to the homepage.</p>
+''',
+}
+
def setup(app):
github_code_repo = 'https://github.com/verilog-to-routing/vtr-verilog-to-routing/'
github_code_branch = 'blob/master/'
diff --git a/doc/src/index.rst b/doc/src/index.rst
index 63a2e08..2f0e3bd 100644
--- a/doc/src/index.rst
+++ b/doc/src/index.rst
@@ -36,7 +36,7 @@
contact
glossary
- references
+ zreferences
Indices and tables
==================
diff --git a/doc/src/vpr/basic_flow.rst b/doc/src/vpr/basic_flow.rst
new file mode 100644
index 0000000..b7bbe97
--- /dev/null
+++ b/doc/src/vpr/basic_flow.rst
@@ -0,0 +1,110 @@
+Basic flow
+==========
+
+The Place and Route process in VPR consists of several steps:
+
+- Packing (combinines primitives into complex blocks)
+- Placment (places complex blocks within the FPGA grid)
+- Routing (determines interconnections between blocks)
+- Analysis (analyzes the implementation)
+
+Each of these steps provides additional configuration options that can be used to customize the whole process.
+
+Packing
+-------
+
+The packing algorithm tries to combine primitive netlist blocks (e.g. LUTs, FFs) into groups, called Complex Blocks (as specified in the :ref:`FPGA architecture file <arch_complex_blocks>`).
+The results from the packing process are written into a ``.net`` file.
+It contains a description of complex blocks with their inputs, outputs, used clocks and relations to other signals.
+It can be useful in analyzing how VPR packs primitives together.
+
+A detailed description of the ``.net`` file format can be found in the :ref:`vpr_pack_file` section.
+
+Placement
+---------
+
+This step assigns a location to the Complex Blocks (produced by packing) with the FPGA grid, while optimizing for wirelength and timing.
+The output from this step is written to the ``.place`` file, which contains the physical location of the blocks from the ``.net`` file.
+
+The file has the following format:
+
+.. code-block:: none
+
+ block_name x y subblock_number
+
+where ``x`` and ``y`` are positions in the VPR grid and ``block_name`` comes from the ``.net`` file.
+
+Example of a placing file:
+
+.. code-block:: none
+
+ Netlist_File: top.net Netlist_ID: SHA256:ce5217d251e04301759ee5a8f55f67c642de435b6c573148b67c19c5e054c1f9
+ Array size: 149 x 158 logic blocks
+
+ #block name x y subblk block number
+ #---------- -- -- ------ ------------
+ $auto$alumacc.cc:474:replace_alu$24.slice[1].carry4_full 53 32 0 #0
+ $auto$alumacc.cc:474:replace_alu$24.slice[2].carry4_full 53 31 0 #1
+ $auto$alumacc.cc:474:replace_alu$24.slice[3].carry4_full 53 30 0 #2
+ $auto$alumacc.cc:474:replace_alu$24.slice[4].carry4_full 53 29 0 #3
+ $auto$alumacc.cc:474:replace_alu$24.slice[5].carry4_full 53 28 0 #4
+ $auto$alumacc.cc:474:replace_alu$24.slice[6].carry4_part 53 27 0 #5
+ $auto$alumacc.cc:474:replace_alu$24.slice[0].carry4_1st_full 53 33 0 #6
+ out:LD7 9 5 0 #7
+ clk 42 26 0 #8
+ $false 35 26 0 #9
+
+A detailed description of the ``.place`` file format can be found in the :ref:`vpr_place_file` section.
+
+Routing
+-------
+
+This step determines how to connect the placed Complex Blocks together, according to the netlist connectivity and the routing resources of the FPGA chip.
+The router uses a Routing Resource (RR) Graph :cite:`betz_arch_cad` to represent the FPGA's available routing resources.
+The RR graph can be created in two ways:
+
+#. Automatically generated by VPR from the :ref:`FPGA architecture description <arch_reference>` :cite:`betz_automatic_generation_of_fpga_routing`, or
+#. Loaded from an external :ref:`RR graph file <vpr_route_resource_file>`.
+
+The output of routing is written into a ``.route`` file.
+The file describes each connection from input to its output through different routing resources of the FPGA.
+Each net starts with a ``SOURCE`` node and ends in a ``SINK`` node, potentially passing through complex block input/output pins (``IPIN``/``OPIN`` nodes) and horizontal/vertical routing wires (``CHANX``/``CHANY`` nodes).
+The pair of numbers in round brackets provides information on the (x, y) resource location on the VPR grid.
+The additional field provides information about the specific node.
+
+An example routing file could look as follows:
+
+.. code-block:: none
+
+ Placement_File: top.place Placement_ID: SHA256:88d45f0bf7999e3f9331cdfd3497d0028be58ffa324a019254c2ae7b4f5bfa7a
+ Array size: 149 x 158 logic blocks.
+
+ Routing:
+
+ Net 0 (counter[4])
+
+ Node: 203972 SOURCE (53,32) Class: 40 Switch: 0
+ Node: 204095 OPIN (53,32) Pin: 40 BLK-TL-SLICEL.CQ[0] Switch: 189
+ Node: 1027363 CHANY (52,32) Track: 165 Switch: 7
+ Node: 601704 CHANY (52,32) Track: 240 Switch: 161
+ Node: 955959 CHANY (52,32) to (52,33) Track: 90 Switch: 130
+ Node: 955968 CHANY (52,32) Track: 238 Switch: 128
+ Node: 955976 CHANY (52,32) Track: 230 Switch: 131
+ Node: 601648 CHANY (52,32) Track: 268 Switch: 7
+ Node: 1027319 CHANY (52,32) Track: 191 Switch: 183
+ Node: 203982 IPIN (53,32) Pin: 1 BLK-TL-SLICEL.A2[0] Switch: 0
+ Node: 203933 SINK (53,32) Class: 1 Switch: -1
+
+ Net 1 ($auto$alumacc.cc:474:replace_alu$24.O[6])
+ ...
+
+A detailed description of the ``.route`` file format can be found in the :ref:`vpr_route_file` section.
+
+Analysis
+--------
+This step analyzes the resulting implementation, producing information about:
+ - Resource usage (e.g. block types, wiring)
+ - Timing (e.g. critical path delays and timing paths)
+ - Power (e.g. total power used, power broken down by blocks)
+
+Note that VPR's analysis can be used independently of VPR's optimization stages, so long as the appropriate ``.net``/``.place``/``.route`` files are available.
diff --git a/doc/src/vpr/command_line_usage.rst b/doc/src/vpr/command_line_usage.rst
index f2ad858..4197c73 100644
--- a/doc/src/vpr/command_line_usage.rst
+++ b/doc/src/vpr/command_line_usage.rst
@@ -33,6 +33,7 @@
Values in curly braces separated by vertical bars, e.g. ``{on | off}``, indicate all the permissible choices for an option.
.. _stage_options:
+
Stage Options
^^^^^^^^^^^^^
VPR runs all stages of (pack, place, route, and analysis) if none of :option:`--pack`, :option:`--place`, :option:`--route` or :option:`--analysis` are specified.
@@ -63,6 +64,7 @@
**Default:** ``off``
.. _graphics_options:
+
Graphics Options
^^^^^^^^^^^^^^^^
@@ -82,6 +84,7 @@
**Default:** ``1``
.. _general_options:
+
General Options
^^^^^^^^^^^^^^^
.. option:: -h, --help
@@ -186,6 +189,7 @@
**Default:** ``on``
.. _filename_options:
+
Filename Options
^^^^^^^^^^^^^^^^
VPR by default appends .blif, .net, .place, and .route to the circuit name provided by the user, and looks for an SDC file in the working directory with the same name as the circuit.
@@ -245,8 +249,6 @@
Prefix for output files
-.. _general_options:
-
.. _netlist_options:
Netlist Options
@@ -463,7 +465,7 @@
**Default:** ``auto``
-.. option:: --pack_prioritize_transitive_connectivity {on, off}
+.. option:: --pack_prioritize_transitive_connectivity {on | off}
Controls whether transitive connectivity is prioritized over high-fanout connectivity during packing.
@@ -829,7 +831,14 @@
Selects which router algorithm to use.
- The ``breadth_first`` router focuses solely on routing a design successfully, while the ``timing_driven`` router focuses both on achieving a successful route and achieving good circuit speed.
+ .. warning::
+
+ The ``breadth_first`` router **should NOT be used to compare the run-time/quality** of alternate routing algorithms.
+
+ It is inferrior to the ``timing_driven`` router from a circuit speed (2x - 10x slower) and run-time perspective (takes 10-100x longer on the large benchmarks).
+ The ``breadth_first`` router is deprecated and may be removed in a future release.
+
+ The ``breadth_first`` router :cite:`betz_arch_cad` focuses solely on routing a design successfully, while the ``timing_driven`` router :cite:`betz_arch_cad,murray_air` focuses both on achieving a successful route and achieving good circuit speed.
The breadth-first router is capable of routing a design using slightly fewer tracks than the timing-driving router (typically 5% if the timing-driven router uses its default parameters.
This can be reduced to about 2% if the router parameters are set so the timing-driven router pays more attention to routability and less to area).
@@ -884,7 +893,8 @@
If the first routing iteration uses more than this fraction of available wirelength routing is aborted.
**Default:** ``0.85``
-.. option:: --incremental_reroute_delay_ripup {on, off, auto}
+
+.. option:: --incremental_reroute_delay_ripup {on | off | auto}
Controls whether incremental net routing will rip-up (and re-route) a critical connection for delay, even if the routing is legal.
``auto`` enables delay-based rip-up unless routability becomes a concern.
@@ -920,7 +930,7 @@
**Default:** ``disable``
-.. option:: --save_routing_per_iteration {on, off}
+.. option:: --save_routing_per_iteration {on | off}
Controls whether VPR saves the current routing to a file after each routing iteration.
May be helpful for debugging.
diff --git a/doc/src/vpr/file_formats.rst b/doc/src/vpr/file_formats.rst
index 47dcdf6..4c583db 100644
--- a/doc/src/vpr/file_formats.rst
+++ b/doc/src/vpr/file_formats.rst
@@ -159,6 +159,170 @@
.blackbox
.end
+.. _vpr_blif_naming_convention:
+
+BLIF Naming Convention
+~~~~~~~~~~~~~~~~~~~~~~
+VPR follows a naming convention to refer to primitives and pins in the BLIF netlist.
+These names appear in the :ref:`VPR GUI <vpr_graphics>`, in log and error messages, and in can be used elsewhere (e.g. in :ref:`SDC constraints <sdc_commands>`).
+
+.. _vpr_blif_naming_convention_nets:
+
+Net Names
+^^^^^^^^^
+The BLIF format uses explicit names to refer to nets.
+These names are used directly as is by VPR (although some nets may be merged/removed by :ref:`netlist cleaning <netlist_options>`).
+
+For example, the following netlist:
+
+.. code-block:: none
+
+ .model top
+ .inputs a b
+ .outputs c
+
+ .names a b c
+ 11 1
+
+ .end
+
+contains nets named:
+
+- ``a``
+- ``b``
+- ``c``
+
+.. _vpr_blif_naming_convention_primitives:
+
+Primitive Names
+^^^^^^^^^^^^^^^
+The standard BLIF format has no mechanism for specifying the names of primitives (e.g. ``.names``/``.latch``/``.subckt``).
+As a result, tools processing BLIF follow a naming convention which generates unique names for each netlist primitive.
+
+The VPR primitive naming convention is as follows:
+
++---------------+--------------------------+-------------------------+
+| Primitive | Drives at least one net? | Primitive Name |
++===============+==========================+=========================+
+| - ``.input`` | Yes | Name of first |
+| - ``.names`` | | driven net |
+| - ``.latch`` +--------------------------+-------------------------+
+| - ``.subckt`` | No | Arbitrarily |
+| | | generated (e.g. |
+| | | ``unamed_instances_K``) |
++---------------+--------------------------+-------------------------+
+| - ``.output`` | N/A | .output name |
+| | | prefixed with |
+| | | ``out:`` |
++---------------+--------------------------+-------------------------+
+
+which ensures each netlist primitive is given a unique name.
+
+For example, in the following:
+
+.. code-block:: none
+
+ .model top
+ .inputs a b x y z clk
+ .outputs c c_reg cout[0] sum[0]
+
+ .names a b c
+ 11 1
+
+ .latch c c_reg re clk 0
+
+ .subckt adder a=x b=y cin=z cout=cout[0] sumout=sum[0]
+
+ .end
+
+ .model adder
+ .inputs a b cin
+ .outputs cout sumout
+ .blackbox
+ .end
+
+- The circuit primary inputs (``.inputs``) are named: ``a``, ``b``, ``x``, ``y``, ``z``, ``clk``,
+- The 2-LUT (``.names``) is named ``c``,
+- The FF (``.latch``) is named ``c_reg``,
+- The ``adder`` (``.subckt``) is named ``cout[0]`` (the name of the first net it drives), and
+- The circuit primary outputs (``.outputs``) are named: ``out:c``, ``out:c_reg``, ``out:cout[0]``, ``out:sum[0]``.
+
+.. seealso:: EBLIF's :ref:`.cname <vpr_eblif_cname>` extension, which allows explicit primitive names to be specified.
+
+
+.. _vpr_blif_naming_convention_pins:
+
+Pin Names
+^^^^^^^^^
+It is useful to be able to refer to particular pins in the netlist.
+VPR uses the convention: ``<primitive_instance_name>.<pin_name>``.
+Where ``<primitive_instance_name>`` is replaced with the netlist primitive name, and ``<pin_name>`` is the name of the relevant pin.
+
+For example, the following ``adder``:
+
+.. code-block:: none
+
+ .subckt adder a=x b=y cin=z cout=cout[0] sumout=sum[0]
+
+which has pin names:
+
+- ``cout[0].a[0]`` (driven by net ``x``)
+- ``cout[0].b[0]`` (driven by net ``y``)
+- ``cout[0].cin[0]`` (driven by net ``z``)
+- ``cout[0].cout[0]`` (drives net ``cout[0]``)
+- ``cout[0].sumout[0]`` (drives net ``sum[0]``)
+
+Since the primitive instance itself is named ``cout[0]`` :ref:`by convention <vpr_blif_naming_convention_primitives>`.
+
+
+Built-in Primitive Pin Names
+""""""""""""""""""""""""""""
+The built-in primitives in BLIF (``.names``, ``.latch``) do not explicitly list the names of their input/output pins.
+VPR uses the following convention:
+
++------------+---------+---------+
+| Primitive | Port | Name |
++============+=========+=========+
+| ``.names`` | input | ``in`` |
+| +---------+---------+
+| | output | ``out`` |
++------------+---------+---------+
+| ``.latch`` | input | ``D`` |
+| +---------+---------+
+| | output | ``Q`` |
+| +---------+---------+
+| | control | ``clk`` |
++------------+---------+---------+
+
+
+Consider the following:
+
+.. code-block:: none
+
+ .names a b c d e f
+ 11111 1
+
+ .latch g h re clk 0
+
+The ``.names``' pin names are:
+
+- ``f.in[0]`` (driven by net ``a``)
+- ``f.in[1]`` (driven by net ``b``)
+- ``f.in[2]`` (driven by net ``c``)
+- ``f.in[3]`` (driven by net ``d``)
+- ``f.in[4]`` (driven by net ``e``)
+- ``f.out[0]`` (drives net ``f``)
+
+and the ``.latch`` pin names are:
+
+- ``h.D[0]`` (driven by net ``g``)
+- ``h.Q[0]`` (drives net ``h``)
+- ``h.clk[0]`` (driven by net ``clk``)
+
+since the ``.names`` and ``.latch`` primitives are named ``f`` and ``h`` :ref:`by convention <vpr_blif_naming_convention_primitives>`.
+
+.. note:: To support pins within multi-bit ports unambiguously, the bit index of the pin within its associated port is included in the pin name (for single-bit ports this will always be ``[0]``).
+
.. _vpr_eblif_file:
Extended BLIF (.eblif)
@@ -202,6 +366,8 @@
.end
+.. _vpr_eblif_cname:
+
.cname
~~~~~~
The ``.cname`` statement allows names to be specified for BLIF primitives (e.g. ``.latch``, ``.names``, ``.subckt``).
diff --git a/doc/src/vpr/index.rst b/doc/src/vpr/index.rst
index e3ba964..a824d77 100644
--- a/doc/src/vpr/index.rst
+++ b/doc/src/vpr/index.rst
@@ -23,6 +23,7 @@
.. toctree::
:maxdepth: 2
+ basic_flow
command_line_usage
graphics
diff --git a/doc/src/vpr/sdc_commands.rst b/doc/src/vpr/sdc_commands.rst
index 5f1bc26..14f8f30 100644
--- a/doc/src/vpr/sdc_commands.rst
+++ b/doc/src/vpr/sdc_commands.rst
@@ -2,7 +2,7 @@
SDC Commands
============
-The following subset of SDC syntax is supported by VPR:
+The following subset of SDC syntax is supported by VPR.
create_clock
------------
@@ -244,6 +244,8 @@
Specifies the sink/capture netlist pins to which the multicycle is applied.
+ .. seealso:: VPR's :ref:`pin naming convention <vpr_blif_naming_convention_pins>`.
+
**Required:** No
.. sdc:option:: <path_multiplier>
@@ -446,12 +448,16 @@
Specifies the source netlist pins.
+ .. seealso:: VPR's :ref:`pin naming convention <vpr_blif_naming_convention_pins>`.
+
**Required:** Yes
.. sdc:option:: -to [get_pins <pin list or regexes>]
Specifies the sink netlist pins.
+ .. seealso:: VPR's :ref:`pin naming convention <vpr_blif_naming_convention_pins>`.
+
**Required:** Yes
.. note::
diff --git a/doc/src/z_references.bib b/doc/src/z_references.bib
index 7c599d1..130439f 100644
--- a/doc/src/z_references.bib
+++ b/doc/src/z_references.bib
@@ -390,3 +390,10 @@
month={Dec},
}
+@INPROCEEDINGS{murray_air,
+ author={K. E. Murray and S. Zhong and V. Betz},
+ booktitle={To appear in Asia Pacific Design Automation Conference (ASP-DAC)},
+ title={AIR: A Fast but Lazy Timing-Driven FPGA Router},
+ year={2020},
+ doi={}
+}
diff --git a/doc/src/references.rst b/doc/src/zreferences.rst
similarity index 100%
rename from doc/src/references.rst
rename to doc/src/zreferences.rst
diff --git a/libs/EXTERNAL/libezgl/CMakeLists.txt b/libs/EXTERNAL/libezgl/CMakeLists.txt
index 164887e..6ab3345 100644
--- a/libs/EXTERNAL/libezgl/CMakeLists.txt
+++ b/libs/EXTERNAL/libezgl/CMakeLists.txt
@@ -3,7 +3,7 @@
# create the project
project(
ezgl
- VERSION 0.0.1
+ VERSION 1.0.1
LANGUAGES CXX
)
diff --git a/libs/EXTERNAL/libezgl/README.adoc b/libs/EXTERNAL/libezgl/README.adoc
index da62577..836033e 100644
--- a/libs/EXTERNAL/libezgl/README.adoc
+++ b/libs/EXTERNAL/libezgl/README.adoc
@@ -1,5 +1,7 @@
= EZGL - An Easy Graphics Library
+image:https://codedocs.xyz/mariobadr/ezgl.svg[link="https://codedocs.xyz/mariobadr/ezgl"]
+
EZGL is a library for use in ece297 as a simple way to create a GUI application.
The library provides a thin wrapper around GTK and drawing functionality.
diff --git a/libs/EXTERNAL/libezgl/examples/basic-application/basic_application.cpp b/libs/EXTERNAL/libezgl/examples/basic-application/basic_application.cpp
index 11071b0..2b5e288 100644
--- a/libs/EXTERNAL/libezgl/examples/basic-application/basic_application.cpp
+++ b/libs/EXTERNAL/libezgl/examples/basic-application/basic_application.cpp
@@ -29,7 +29,7 @@
void act_on_mouse_press(ezgl::application *application, GdkEventButton *event, double x, double y);
void act_on_mouse_move(ezgl::application *application, GdkEventButton *event, double x, double y);
void act_on_key_press(ezgl::application *application, GdkEventKey *event, char *key_name);
-void initial_setup(ezgl::application *application);
+void initial_setup(ezgl::application *application, bool new_window);
void test_button(GtkWidget *widget, ezgl::application *application);
/**
@@ -37,19 +37,19 @@
*
* The graphics object expects that x and y values will be in the main canvas' world coordinate system.
*/
-void draw_main_canvas(ezgl::renderer &g);
+void draw_main_canvas(ezgl::renderer *g);
/**
* draw_main_canvas helper functions
*/
-void draw_rectangle_example(ezgl::renderer &g);
-void draw_arc_example(ezgl::renderer &g);
-void rotated_text_example(ezgl::renderer &g);
-void draw_poly_example(ezgl::renderer &g);
-void draw_text_example(ezgl::renderer &g);
-void draw_line_example(ezgl::renderer &g);
-void screen_coordinates_example(ezgl::renderer &g);
-void draw_png_example(ezgl::renderer &g);
+void draw_rectangle_example(ezgl::renderer *g);
+void draw_arc_example(ezgl::renderer *g);
+void rotated_text_example(ezgl::renderer *g);
+void draw_poly_example(ezgl::renderer *g);
+void draw_text_example(ezgl::renderer *g);
+void draw_line_example(ezgl::renderer *g);
+void screen_coordinates_example(ezgl::renderer *g);
+void draw_png_example(ezgl::renderer *g);
static ezgl::rectangle initial_world{{0, 0}, 1100, 1150};
@@ -99,7 +99,7 @@
/**
* The redrawing function for still pictures
*/
-void draw_main_canvas(ezgl::renderer &g)
+void draw_main_canvas(ezgl::renderer *g)
{
// Draw some rectangles
draw_rectangle_example(g);
@@ -129,7 +129,7 @@
/**
* Draw some rectangles with different colors
*/
-void draw_rectangle_example(ezgl::renderer &g)
+void draw_rectangle_example(ezgl::renderer *g)
{
const float rectangle_width = 50;
const float rectangle_height = rectangle_width;
@@ -152,25 +152,25 @@
};
// format text font and color
- g.set_color(ezgl::BLACK);
- g.format_font("monospace", ezgl::font_slant::normal, ezgl::font_weight::normal, 10);
+ g->set_color(ezgl::BLACK);
+ g->format_font("monospace", ezgl::font_slant::normal, ezgl::font_weight::normal, 10);
// draw text
- g.draw_text({110, color_rectangle.center_y()}, "colors", 2 * (start_point.x - 110), rectangle_height);
+ g->draw_text({110, color_rectangle.center_y()}, "colors", 2 * (start_point.x - 110), rectangle_height);
for (size_t i = 0; i < sizeof (color_indicies) / sizeof (color_indicies[0]); ++i) {
// Change the color of next draw calls
- g.set_color(color_indicies[i]);
+ g->set_color(color_indicies[i]);
// Draw filled in rectangles
- g.fill_rectangle(color_rectangle);
+ g->fill_rectangle(color_rectangle);
// Increment the start point
color_rectangle += {rectangle_width, 0};
}
// Draw text
- g.draw_text({400, color_rectangle.center_y()}, "fill_rectangle", DBL_MAX, rectangle_height);
+ g->draw_text({400, color_rectangle.center_y()}, "fill_rectangle", DBL_MAX, rectangle_height);
/* Draw some rectangles with RGB triplet colors and alpha (transparency) */
@@ -182,162 +182,162 @@
color_rectangle += {rectangle_width, 0};
// Change the next draw calls color. rgb and alpha values range from 0 to 255
- g.set_color(std::rand() % 256, std::rand() % 256, std::rand() % 256, 255);
+ g->set_color(std::rand() % 256, std::rand() % 256, std::rand() % 256, 255);
// Draw filled in rectangles
- g.fill_rectangle(color_rectangle);
+ g->fill_rectangle(color_rectangle);
}
/* Draw a black border rectangle */
// Change the next draw calls color to black
- g.set_color(ezgl::BLACK);
+ g->set_color(ezgl::BLACK);
// Change the next draw calls line width
- g.set_line_width(1);
+ g->set_line_width(1);
// Draw a rectangle bordering all the drawn rectangles
- g.draw_rectangle(start_point, color_rectangle.top_right());
+ g->draw_rectangle(start_point, color_rectangle.top_right());
}
/**
* Draw some example lines, shapes, and arcs
*/
-void draw_arc_example(ezgl::renderer &g)
+void draw_arc_example(ezgl::renderer *g)
{
float radius = 50;
// Draw solid line
- g.set_color(ezgl::BLACK);
- g.draw_text({250, 150}, "draw_line", 150.0, DBL_MAX);
- g.set_line_dash(ezgl::line_dash::none);
- g.draw_line({200, 120}, {200, 200});
+ g->set_color(ezgl::BLACK);
+ g->draw_text({250, 150}, "draw_line", 150.0, DBL_MAX);
+ g->set_line_dash(ezgl::line_dash::none);
+ g->draw_line({200, 120}, {200, 200});
// Draw dashed line
- g.set_line_dash(ezgl::line_dash::asymmetric_5_3);
- g.draw_line({300, 120}, {300, 200});
+ g->set_line_dash(ezgl::line_dash::asymmetric_5_3);
+ g->draw_line({300, 120}, {300, 200});
// Draw elliptic arc
- g.set_color(ezgl::MAGENTA);
- g.draw_text({450, 160}, "draw_elliptic_arc", 150.0, DBL_MAX);
- g.draw_elliptic_arc({550, 160}, 30, 60, 90, 270);
+ g->set_color(ezgl::MAGENTA);
+ g->draw_text({450, 160}, "draw_elliptic_arc", 150.0, DBL_MAX);
+ g->draw_elliptic_arc({550, 160}, 30, 60, 90, 270);
// Draw filled in elliptic arc
- g.draw_text({700, 160}, "fill_elliptic_arc", 150.0, DBL_MAX);
- g.fill_elliptic_arc({800, 160}, 30, 60, 90, 270);
+ g->draw_text({700, 160}, "fill_elliptic_arc", 150.0, DBL_MAX);
+ g->fill_elliptic_arc({800, 160}, 30, 60, 90, 270);
// Draw arcs
- g.set_color(ezgl::BLUE);
- g.draw_text({190, 300}, "draw_arc", radius * 2, 150);
- g.draw_arc({190, 300}, radius, 0, 270);
- g.draw_arc({300, 300}, radius, 0, -180);
+ g->set_color(ezgl::BLUE);
+ g->draw_text({190, 300}, "draw_arc", radius * 2, 150);
+ g->draw_arc({190, 300}, radius, 0, 270);
+ g->draw_arc({300, 300}, radius, 0, -180);
// Draw filled in arcs
- g.fill_arc({410, 300}, radius, 90, -90);
- g.fill_arc({520, 300}, radius, 0, 360);
- g.set_color(ezgl::BLACK);
- g.draw_text({520, 300}, "fill_arc", radius * 2, 150);
- g.set_color(ezgl::BLUE);
- g.fill_arc({630, 300}, radius, 90, 180);
- g.fill_arc({740, 300}, radius, 90, 270);
- g.fill_arc({850, 300}, radius, 90, 30);
+ g->fill_arc({410, 300}, radius, 90, -90);
+ g->fill_arc({520, 300}, radius, 0, 360);
+ g->set_color(ezgl::BLACK);
+ g->draw_text({520, 300}, "fill_arc", radius * 2, 150);
+ g->set_color(ezgl::BLUE);
+ g->fill_arc({630, 300}, radius, 90, 180);
+ g->fill_arc({740, 300}, radius, 90, 270);
+ g->fill_arc({850, 300}, radius, 90, 30);
}
/**
* Draw some rotated text
*/
-void rotated_text_example(ezgl::renderer &g)
+void rotated_text_example(ezgl::renderer *g)
{
const float textsquare_width = 200;
ezgl::rectangle textsquare = {{100, 400}, textsquare_width, textsquare_width};
- g.set_color(ezgl::BLUE);
- g.draw_rectangle(textsquare);
+ g->set_color(ezgl::BLUE);
+ g->draw_rectangle(textsquare);
- g.set_color(ezgl::GREEN);
- g.draw_rectangle(textsquare.center(), {textsquare.right(), textsquare.top()});
- g.draw_rectangle({textsquare.left(), textsquare.bottom()}, textsquare.center());
+ g->set_color(ezgl::GREEN);
+ g->draw_rectangle(textsquare.center(), {textsquare.right(), textsquare.top()});
+ g->draw_rectangle({textsquare.left(), textsquare.bottom()}, textsquare.center());
- g.set_color(ezgl::RED);
- g.draw_line({textsquare.left(), textsquare.bottom()}, {textsquare.right(), textsquare.top()});
- g.draw_line({textsquare.left(), textsquare.top()}, {textsquare.right(), textsquare.bottom()});
+ g->set_color(ezgl::RED);
+ g->draw_line({textsquare.left(), textsquare.bottom()}, {textsquare.right(), textsquare.top()});
+ g->draw_line({textsquare.left(), textsquare.top()}, {textsquare.right(), textsquare.bottom()});
- g.set_color(0, 0, 0, 100);
- g.set_font_size(14);
- g.draw_text({textsquare.center_x(), textsquare.bottom()}, "0 degrees", textsquare.width(), textsquare.height());
+ g->set_color(0, 0, 0, 100);
+ g->set_font_size(14);
+ g->draw_text({textsquare.center_x(), textsquare.bottom()}, "0 degrees", textsquare.width(), textsquare.height());
- g.set_text_rotation(90);
- g.draw_text({textsquare.right(), textsquare.center_y()}, "90 degrees", textsquare.width(), textsquare.height());
+ g->set_text_rotation(90);
+ g->draw_text({textsquare.right(), textsquare.center_y()}, "90 degrees", textsquare.width(), textsquare.height());
- g.set_text_rotation(180);
- g.draw_text({textsquare.center_x(), textsquare.top()}, "180 degrees", textsquare.width(), textsquare.height());
+ g->set_text_rotation(180);
+ g->draw_text({textsquare.center_x(), textsquare.top()}, "180 degrees", textsquare.width(), textsquare.height());
- g.set_text_rotation(270);
- g.draw_text({textsquare.left(), textsquare.center_y()}, "270 degrees", textsquare.width(), textsquare.height());
+ g->set_text_rotation(270);
+ g->draw_text({textsquare.left(), textsquare.center_y()}, "270 degrees", textsquare.width(), textsquare.height());
- g.set_text_rotation(45);
- g.draw_text(textsquare.center(), "45 degrees", textsquare.width(), textsquare.height());
+ g->set_text_rotation(45);
+ g->draw_text(textsquare.center(), "45 degrees", textsquare.width(), textsquare.height());
- g.set_text_rotation(135);
- g.draw_text(textsquare.center(), "135 degrees", textsquare.width(), textsquare.height());
+ g->set_text_rotation(135);
+ g->draw_text(textsquare.center(), "135 degrees", textsquare.width(), textsquare.height());
// It is probably a good idea to set text rotation back to zero,
- g.set_text_rotation(0);
+ g->set_text_rotation(0);
}
/**
* Draw some Polygons
*/
-void draw_poly_example(ezgl::renderer &g)
+void draw_poly_example(ezgl::renderer *g)
{
- g.set_font_size(10);
- g.set_color(ezgl::RED);
+ g->set_font_size(10);
+ g->set_color(ezgl::RED);
// Draw a triangle
- g.fill_poly({{500, 400}, {440, 480}, {560, 480}});
+ g->fill_poly({{500, 400}, {440, 480}, {560, 480}});
// Draw a 4-point polygon
- g.fill_poly({{700, 400}, {650, 480}, {750, 480}, {800, 400}});
+ g->fill_poly({{700, 400}, {650, 480}, {750, 480}, {800, 400}});
- g.set_color(ezgl::BLACK);
- g.draw_text({500, 450}, "fill_poly", 80.0, DBL_MAX);
- g.draw_text({725, 440}, "fill_poly", 100.0, DBL_MAX);
+ g->set_color(ezgl::BLACK);
+ g->draw_text({500, 450}, "fill_poly", 80.0, DBL_MAX);
+ g->draw_text({725, 440}, "fill_poly", 100.0, DBL_MAX);
- g.set_color(ezgl::DARK_GREEN);
- g.set_line_dash(ezgl::line_dash::none);
+ g->set_color(ezgl::DARK_GREEN);
+ g->set_line_dash(ezgl::line_dash::none);
ezgl::rectangle rect = {{350, 550}, {650, 670}};
- g.draw_text(rect.center(), "draw_rectangle", rect.width(), rect.height());
- g.draw_rectangle(rect);
+ g->draw_text(rect.center(), "draw_rectangle", rect.width(), rect.height());
+ g->draw_rectangle(rect);
/* Draw some semi-transparent primitives */
- g.set_font_size(10);
+ g->set_font_size(10);
- g.set_color(255, 0, 0, 255);
- g.fill_rectangle({1000, 400}, {1050, 800});
+ g->set_color(255, 0, 0, 255);
+ g->fill_rectangle({1000, 400}, {1050, 800});
- g.set_color(0, 0, 255, 255);
- g.fill_rectangle({1000+50, 400}, {1050+50, 800});
+ g->set_color(0, 0, 255, 255);
+ g->fill_rectangle({1000+50, 400}, {1050+50, 800});
- g.set_color(0, 255, 0, 255/2); // 50% transparent
- g.fill_rectangle({1000+25, 400-100}, {1050+25, 800-200});
+ g->set_color(0, 255, 0, 255/2); // 50% transparent
+ g->fill_rectangle({1000+25, 400-100}, {1050+25, 800-200});
- g.set_color(255, 100, 255, 255/2);
- g.fill_poly({{465, 380}, {400, 450}, {765, 450}, {850, 380}});
+ g->set_color(255, 100, 255, 255/2);
+ g->fill_poly({{465, 380}, {400, 450}, {765, 450}, {850, 380}});
- g.set_color(100, 100, 255, 255/3);
- g.fill_poly({{550, 420}, {475, 500}, {875, 500}});
+ g->set_color(100, 100, 255, 255/3);
+ g->fill_poly({{550, 420}, {475, 500}, {875, 500}});
- g.set_color(ezgl::BLACK);
- g.set_text_rotation(90);
- g.draw_text({1000 - 50, 500}, "Partially transparent polys", 500, DBL_MAX);
- g.set_text_rotation(0);
+ g->set_color(ezgl::BLACK);
+ g->set_text_rotation(90);
+ g->draw_text({1000 - 50, 500}, "Partially transparent polys", 500, DBL_MAX);
+ g->set_text_rotation(0);
}
/**
* Draw some example text, with the bounding box functions
*/
-void draw_text_example(ezgl::renderer &g)
+void draw_text_example(ezgl::renderer *g)
{
const float text_example_width = 800;
@@ -362,16 +362,16 @@
{24, 32}
};
- g.set_color(ezgl::BLACK);
- g.set_line_dash(ezgl::line_dash::asymmetric_5_3);
+ g->set_color(ezgl::BLACK);
+ g->set_line_dash(ezgl::line_dash::asymmetric_5_3);
for (int i = 0; i < num_lines; ++i) {
ezgl::rectangle text_bbox = {{100., 710. + i * 60.}, text_example_width / num_strings_per_line[i], 60.};
for (int j = 0; j < num_strings_per_line[i]; ++j) {
- g.set_font_size(text_sizes[i][j]);
- g.draw_text(text_bbox.center(), line_text[i][j], text_bbox.width(), text_bbox.height());
- g.draw_rectangle(text_bbox);
+ g->set_font_size(text_sizes[i][j]);
+ g->draw_text(text_bbox.center(), line_text[i][j], text_bbox.width(), text_bbox.height());
+ g->draw_rectangle(text_bbox);
text_bbox = {{text_bbox.left() + text_example_width / num_strings_per_line[i], text_bbox.bottom()} , text_bbox.width(), text_bbox.height()};
}
}
@@ -380,52 +380,52 @@
/**
* Draw wide lines with different end shapes
*/
-void draw_line_example(ezgl::renderer &g)
+void draw_line_example(ezgl::renderer *g)
{
- g.set_font_size(10);
+ g->set_font_size(10);
for (int i = 0; i <= 2; ++i)
{
double offsetY = 50*i;
- g.set_horiz_text_just(ezgl::text_just::left);
+ g->set_horiz_text_just(ezgl::text_just::left);
if (i == 0) {
- g.set_color(ezgl::BLACK);
- g.set_line_cap(ezgl::line_cap::butt); // Butt ends
- g.set_line_dash(ezgl::line_dash::none); // Solid line
- g.draw_text({950, 920+offsetY}, "Butt ends, opaque", 400, DBL_MAX);
+ g->set_color(ezgl::BLACK);
+ g->set_line_cap(ezgl::line_cap::butt); // Butt ends
+ g->set_line_dash(ezgl::line_dash::none); // Solid line
+ g->draw_text({950, 920+offsetY}, "Butt ends, opaque", 400, DBL_MAX);
}
else if (i == 1) {
- g.set_color(ezgl::GREEN, 255*2/3); // Green line that is 33% transparent)
- g.set_line_cap(ezgl::line_cap::round); // Round ends
- g.set_line_dash(ezgl::line_dash::none); // Solid line
- g.draw_text({950, 920+offsetY}, "Round ends, 33% transparent", 400, DBL_MAX);
+ g->set_color(ezgl::GREEN, 255*2/3); // Green line that is 33% transparent)
+ g->set_line_cap(ezgl::line_cap::round); // Round ends
+ g->set_line_dash(ezgl::line_dash::none); // Solid line
+ g->draw_text({950, 920+offsetY}, "Round ends, 33% transparent", 400, DBL_MAX);
}
else {
- g.set_color(ezgl::RED, 255/3); // Red line that is 67% transparent
- g.set_line_cap(ezgl::line_cap::butt); // butt ends
- g.set_line_dash(ezgl::line_dash::asymmetric_5_3); // Dashed line
- g.draw_text({950, 920+offsetY}, "Butt ends, 67% transparent", 400, DBL_MAX);
+ g->set_color(ezgl::RED, 255/3); // Red line that is 67% transparent
+ g->set_line_cap(ezgl::line_cap::butt); // butt ends
+ g->set_line_dash(ezgl::line_dash::asymmetric_5_3); // Dashed line
+ g->draw_text({950, 920+offsetY}, "Butt ends, 67% transparent", 400, DBL_MAX);
}
- g.set_horiz_text_just(ezgl::text_just::center);
+ g->set_horiz_text_just(ezgl::text_just::center);
- g.draw_text({200, 900+offsetY}, "Thin line (width 1)", 200, DBL_MAX);
- g.set_line_width(1);
- g.draw_line({100, 920+offsetY}, {300, 920+offsetY});
+ g->draw_text({200, 900+offsetY}, "Thin line (width 1)", 200, DBL_MAX);
+ g->set_line_width(1);
+ g->draw_line({100, 920+offsetY}, {300, 920+offsetY});
- g.draw_text({500, 900+offsetY}, "Width 3 Line", 200, DBL_MAX);
- g.set_line_width(3);
- g.draw_line({400, 920+offsetY}, {600, 920+offsetY});
+ g->draw_text({500, 900+offsetY}, "Width 3 Line", 200, DBL_MAX);
+ g->set_line_width(3);
+ g->draw_line({400, 920+offsetY}, {600, 920+offsetY});
- g.draw_text({800, 900+offsetY}, "Width 6 Line", 200, DBL_MAX);
- g.set_line_width(6);
- g.draw_line({700, 920+offsetY}, {900, 920+offsetY});
+ g->draw_text({800, 900+offsetY}, "Width 6 Line", 200, DBL_MAX);
+ g->set_line_width(6);
+ g->draw_line({700, 920+offsetY}, {900, 920+offsetY});
- g.set_line_width(1);
+ g->set_line_width(1);
}
}
@@ -433,33 +433,33 @@
* Draw to screen coordinates where (0,0) is the top-left corner of the window
* These coordinates are not transformed so the object will not pan or zoom.
*/
-void screen_coordinates_example(ezgl::renderer &g)
+void screen_coordinates_example(ezgl::renderer *g)
{
// Set the coordinate system to SCREEN
- g.set_coordinate_system(ezgl::SCREEN);
+ g->set_coordinate_system(ezgl::SCREEN);
- g.set_color(255, 0, 0, 255);
- g.set_line_dash(ezgl::line_dash::none);
- g.draw_rectangle({10, 10}, {100, 100});
- g.set_font_size(10);
- g.draw_text({55, 33}, "Screen coord");
- g.draw_text({55, 66}, "Fixed loc");
+ g->set_color(255, 0, 0, 255);
+ g->set_line_dash(ezgl::line_dash::none);
+ g->draw_rectangle({10, 10}, {100, 100});
+ g->set_font_size(10);
+ g->draw_text({55, 33}, "Screen coord");
+ g->draw_text({55, 66}, "Fixed loc");
// Set the coordinate system back to WORLD
- g.set_coordinate_system(ezgl::WORLD);
+ g->set_coordinate_system(ezgl::WORLD);
}
/**
* Draw a small PNG
*/
-void draw_png_example(ezgl::renderer &g)
+void draw_png_example(ezgl::renderer *g)
{
ezgl::surface *png_surface = ezgl::renderer::load_png("small_image.png");
- g.draw_surface(png_surface, {50, 200});
+ g->draw_surface(png_surface, {50, 200});
ezgl::renderer::free_surface(png_surface);
- g.set_font_size(10);
- g.set_color(ezgl::BLACK);
- g.draw_text ({50, 225}, "draw_surface", 200, DBL_MAX);
+ g->set_font_size(10);
+ g->set_color(ezgl::BLACK);
+ g->draw_text ({50, 225}, "draw_surface", 200, DBL_MAX);
}
/**
@@ -467,7 +467,7 @@
* Can be used to create additional buttons, initialize the status message,
* or connect added widgets to their callback functions
*/
-void initial_setup(ezgl::application *application)
+void initial_setup(ezgl::application *application, bool /*new_window*/)
{
// Update the status bar message
application->update_message("EZGL Application");
@@ -540,10 +540,10 @@
application->refresh_drawing();
// Draw a temporary rectangle border
- ezgl::renderer g = application->get_renderer();
- g.set_line_width(1);
- g.set_color(ezgl::BLACK);
- g.draw_rectangle({{0, 0}, 1100, 1150});
+ ezgl::renderer *g = application->get_renderer();
+ g->set_line_width(1);
+ g->set_color(ezgl::BLACK);
+ g->draw_rectangle({{0, 0}, 1100, 1150});
application->flush_drawing();
}
diff --git a/libs/EXTERNAL/libezgl/include/ezgl/application.hpp b/libs/EXTERNAL/libezgl/include/ezgl/application.hpp
index 256d0b0..8015f2e 100644
--- a/libs/EXTERNAL/libezgl/include/ezgl/application.hpp
+++ b/libs/EXTERNAL/libezgl/include/ezgl/application.hpp
@@ -48,7 +48,7 @@
/**
* The signature of a setup callback function
*/
-using setup_callback_fn = void (*)(application *app);
+using setup_callback_fn = void (*)(application *app, bool new_window);
/**
* The signature of a button callback function
@@ -225,16 +225,14 @@
void refresh_drawing();
/**
- * Get a temporary renderer that can be used to draw on top of the main canvas
- *
- * The returned renderer should be used only in the same callback in which this function is called
+ * Get a renderer that can be used to draw on top of the main canvas
*/
- renderer get_renderer();
+ renderer *get_renderer();
/**
* Flush the drawings done by the renderer, returned from get_renderer(), to the on-screen buffer
*
- * The flushing is done after returning to the GTK event loop
+ * The flushing is done immediately
*/
void flush_drawing();
@@ -357,6 +355,9 @@
// A flag that indicates if the run() was called before or not to allow multiple reruns
bool first_run;
+ // A flag that indicates if we are resuming an older run to allow proper quitting
+ bool resume_run;
+
private:
// Called when our GtkApplication is initialized for the first time.
static void startup(GtkApplication *gtk_app, gpointer user_data);
diff --git a/libs/EXTERNAL/libezgl/include/ezgl/canvas.hpp b/libs/EXTERNAL/libezgl/include/ezgl/canvas.hpp
index 5bf4636..b6aa475 100644
--- a/libs/EXTERNAL/libezgl/include/ezgl/canvas.hpp
+++ b/libs/EXTERNAL/libezgl/include/ezgl/canvas.hpp
@@ -40,7 +40,7 @@
/**
* The signature of a function that draws to an ezgl::canvas.
*/
-using draw_canvas_fn = void (*)(renderer &);
+using draw_canvas_fn = void (*)(renderer*);
/**
* Responsible for creating, destroying, and maintaining the rendering context of a GtkWidget.
@@ -100,11 +100,9 @@
}
/**
- * Create a temporary renderer that can be used to draw on top of the current canvas
- *
- * The created renderer should be used only in the same callback in which it was created
+ * Create an animation renderer that can be used to draw on top of the current canvas
*/
- renderer create_temporary_renderer();
+ renderer *create_animation_renderer();
/**
* print_pdf, print_svg, and print_png generate a PDF, SVG, or PNG output file showing
@@ -158,6 +156,9 @@
// The off-screen cairo context that can be drawn to
cairo_t *m_context = nullptr;
+ // The animation renderer
+ renderer *m_animation_renderer = nullptr;
+
private:
// Called each time our drawing area widget has changed (e.g., in size).
static gboolean configure_event(GtkWidget *widget, GdkEventConfigure *event, gpointer data);
diff --git a/libs/EXTERNAL/libezgl/include/ezgl/graphics.hpp b/libs/EXTERNAL/libezgl/include/ezgl/graphics.hpp
index d9fd36a..35e41d4 100644
--- a/libs/EXTERNAL/libezgl/include/ezgl/graphics.hpp
+++ b/libs/EXTERNAL/libezgl/include/ezgl/graphics.hpp
@@ -467,6 +467,14 @@
*/
renderer(cairo_t *cairo, transform_fn transform, camera *m_camera, cairo_surface_t *m_surface);
+ /**
+ * Update the renderer when the cairo surface/context changes
+ *
+ * @param cairo The new cairo graphics state
+ * @param m_surface The new cairo surface
+ */
+ void update_renderer(cairo_t *cairo, cairo_surface_t *m_surface);
+
private:
void draw_rectangle_path(point2d start, point2d end, bool fill_flag);
@@ -496,16 +504,7 @@
// The x11 context
GC x11_context;
- // Current line width
- int current_line_width = 1;
-
- // Current line cap
- line_cap current_line_cap = line_cap::butt;
-
- // Current line dash
- line_dash current_line_dash = line_dash::none;
-
- // Transparency flag, if set cairo will be used
+ // Transparency flag, if set, cairo will be used
bool transparency_flag = false;
#endif
@@ -522,6 +521,18 @@
// Current vertical text justification
text_just vert_text_just = text_just::center;
+
+ // Current line width
+ int current_line_width = 1;
+
+ // Current line cap
+ line_cap current_line_cap = line_cap::butt;
+
+ // Current line dash
+ line_dash current_line_dash = line_dash::none;
+
+ // Current color
+ color current_color = {0, 0, 0, 255};
};
}
diff --git a/libs/EXTERNAL/libezgl/src/application.cpp b/libs/EXTERNAL/libezgl/src/application.cpp
index b850f86..0a1cdf7 100644
--- a/libs/EXTERNAL/libezgl/src/application.cpp
+++ b/libs/EXTERNAL/libezgl/src/application.cpp
@@ -63,7 +63,7 @@
}
if(ezgl_app->initial_setup_callback != nullptr)
- ezgl_app->initial_setup_callback(ezgl_app);
+ ezgl_app->initial_setup_callback(ezgl_app, true);
g_info("application::activate successful.");
}
@@ -87,6 +87,7 @@
g_signal_connect(m_application, "activate", G_CALLBACK(activate), this);
first_run = true;
+ resume_run = false;
}
application::~application()
@@ -156,9 +157,35 @@
mouse_move_callback = mouse_move_user_callback;
key_press_callback = key_press_user_callback;
+ if(first_run) {
+ // set the first_run flag to false
+ first_run = false;
+
+ g_info("The event loop is now starting.");
+
+ // see: https://developer.gnome.org/gio/stable/GApplication.html#g-application-run
+ return g_application_run(G_APPLICATION(m_application), 0, 0);
+ }
// The result of calling g_application_run() again after it returns is unspecified.
- // So we have to destruct and reconstruct the GTKApplication
- if(!first_run) {
+ // So in the subsequent runs instead of calling g_application_run(), we will go back to the event loop using gtk_main()
+ else if(!first_run && gtk_application_get_active_window(m_application) != nullptr) {
+
+ // Call user's initial setup call
+ if(initial_setup_callback != nullptr)
+ initial_setup_callback(this, false);
+
+ // set the resume_run flag to true
+ resume_run = true;
+
+ g_info("The event loop is now resuming.");
+
+ // see: https://developer.gnome.org/gtk3/stable/gtk3-General.html#gtk-main
+ gtk_main();
+
+ return 0;
+ }
+ // But if the GTK window is closed, we will have to destruct and reconstruct the GTKApplication
+ else {
// Destroy the GTK application
g_object_unref(m_application);
g_object_unref(m_builder);
@@ -168,25 +195,26 @@
m_builder = (gtk_builder_new());
g_signal_connect(m_application, "startup", G_CALLBACK(startup), this);
g_signal_connect(m_application, "activate", G_CALLBACK(activate), this);
+
+ // set the resume_run flag to false
+ resume_run = false;
+
+ g_info("The event loop is now restarting.");
+
+ // see: https://developer.gnome.org/gio/stable/GApplication.html#g-application-run
+ return g_application_run(G_APPLICATION(m_application), 0, 0);
}
-
- // set the first_run flag to false
- first_run = false;
-
- g_info("The event loop is now starting.");
-
- // see: https://developer.gnome.org/gio/unstable/GApplication.html#g-application-run
- return g_application_run(G_APPLICATION(m_application), 0, 0);
}
void application::quit()
{
- // Close the current window
- GObject *window = get_object(m_window_id.c_str());
- gtk_window_close(GTK_WINDOW(window));
-
- // Quit the GTK application
- g_application_quit(G_APPLICATION(m_application));
+ if(resume_run) {
+ // Quit the event loop (exit gtk_main())
+ gtk_main_quit();
+ } else {
+ // Quit the GTK application (exit g_application_run())
+ g_application_quit(G_APPLICATION(m_application));
+ }
}
void application::register_default_events_callbacks(ezgl::application *application)
@@ -213,6 +241,9 @@
// Connect scroll_mouse function to the mouse scroll event (up, down, left and right)
g_signal_connect(main_canvas, "scroll_event", G_CALLBACK(scroll_mouse), application);
+
+ // Connect press_proceed function to the close button of the MainWindow
+ g_signal_connect(window, "destroy", G_CALLBACK(press_proceed), application);
}
void application::register_default_buttons_callbacks(ezgl::application *application)
@@ -410,14 +441,18 @@
// queue a redraw of the GtkWidget
gtk_widget_queue_draw(drawing_area);
+
+ // run the main loop on pending events
+ while(gtk_events_pending())
+ gtk_main_iteration();
}
-renderer application::get_renderer()
+renderer *application::get_renderer()
{
// get the main canvas
canvas *cnv = get_canvas(m_canvas_id);
- return cnv->create_temporary_renderer();
+ return cnv->create_animation_renderer();
}
void set_disable_event_loop(bool new_setting)
diff --git a/libs/EXTERNAL/libezgl/src/canvas.cpp b/libs/EXTERNAL/libezgl/src/canvas.cpp
index fcf72f7..9821036 100644
--- a/libs/EXTERNAL/libezgl/src/canvas.cpp
+++ b/libs/EXTERNAL/libezgl/src/canvas.cpp
@@ -86,7 +86,7 @@
camera pdf_cam = m_camera;
pdf_cam.update_widget(surface_width, surface_height);
renderer g(context, std::bind(&camera::world_to_screen, pdf_cam, _1), &pdf_cam, pdf_surface);
- m_draw_callback(g);
+ m_draw_callback(&g);
// free surface & context
cairo_surface_destroy(pdf_surface);
@@ -125,7 +125,7 @@
camera svg_cam = m_camera;
svg_cam.update_widget(surface_width, surface_height);
renderer g(context, std::bind(&camera::world_to_screen, svg_cam, _1), &svg_cam, svg_surface);
- m_draw_callback(g);
+ m_draw_callback(&g);
// free surface & context
cairo_surface_destroy(svg_surface);
@@ -164,7 +164,7 @@
camera png_cam = m_camera;
png_cam.update_widget(surface_width, surface_height);
renderer g(context, std::bind(&camera::world_to_screen, png_cam, _1), &png_cam, png_surface);
- m_draw_callback(g);
+ m_draw_callback(&g);
// create png output file
cairo_surface_write_to_png(png_surface, file_name);
@@ -205,6 +205,10 @@
// Draw to the newly created surface.
ezgl_canvas->redraw();
+ // Update the animation renderer
+ if(ezgl_canvas->m_animation_renderer != nullptr)
+ ezgl_canvas->m_animation_renderer->update_renderer(p_context, p_surface);
+
g_info("canvas::configure_event has been handled.");
return TRUE; // the configure event was handled
}
@@ -241,6 +245,10 @@
if(m_context != nullptr) {
cairo_destroy(m_context);
}
+
+ if(m_animation_renderer != nullptr) {
+ delete m_animation_renderer;
+ }
}
int canvas::width() const
@@ -287,19 +295,21 @@
cairo_paint(m_context);
using namespace std::placeholders;
- renderer g(m_context, std::bind(&camera::world_to_screen, m_camera, _1), &m_camera, m_surface);
- m_draw_callback(g);
+ renderer g(m_context, std::bind(&camera::world_to_screen, &m_camera, _1), &m_camera, m_surface);
+ m_draw_callback(&g);
gtk_widget_queue_draw(m_drawing_area);
g_info("The canvas will be redrawn.");
}
-renderer canvas::create_temporary_renderer()
+renderer *canvas::create_animation_renderer()
{
- using namespace std::placeholders;
- renderer g(m_context, std::bind(&camera::world_to_screen, m_camera, _1), &m_camera, m_surface);
+ if(m_animation_renderer == nullptr) {
+ using namespace std::placeholders;
+ m_animation_renderer = new renderer(m_context, std::bind(&camera::world_to_screen, &m_camera, _1), &m_camera, m_surface);
+ }
- return g;
+ return m_animation_renderer;
}
} // namespace ezgl
diff --git a/libs/EXTERNAL/libezgl/src/graphics.cpp b/libs/EXTERNAL/libezgl/src/graphics.cpp
index b7574c4..28ce32f 100644
--- a/libs/EXTERNAL/libezgl/src/graphics.cpp
+++ b/libs/EXTERNAL/libezgl/src/graphics.cpp
@@ -56,6 +56,36 @@
#endif
}
+void renderer::update_renderer(cairo_t *cairo, cairo_surface_t *m_surface)
+{
+ // Update Cairo Context
+ m_cairo = cairo;
+
+ // Update X11 Context
+#ifdef EZGL_USE_X11
+ // Check if the created cairo surface is an XLIB surface
+ if (cairo_surface_get_type(m_surface) == CAIRO_SURFACE_TYPE_XLIB) {
+ // get the underlying x11 drawable used by cairo surface
+ x11_drawable = cairo_xlib_surface_get_drawable(m_surface);
+
+ // get the x11 display
+ x11_display = cairo_xlib_surface_get_display(m_surface);
+
+ // create the x11 context from the drawable of the cairo surface
+ if (x11_display != nullptr) {
+ XFreeGC(x11_display, x11_context);
+ x11_context = XCreateGC(x11_display, x11_drawable, 0, 0);
+ }
+ }
+#endif
+
+ // Restore graphics attributes
+ set_color(current_color);
+ set_line_width(current_line_width);
+ set_line_cap(current_line_cap);
+ set_line_dash(current_line_dash);
+}
+
void renderer::set_coordinate_system(t_coordinate_system new_coordinate_system)
{
current_coordinate_system = new_coordinate_system;
@@ -161,6 +191,9 @@
// set color for cairo
cairo_set_source_rgba(m_cairo, red / 255.0, green / 255.0, blue / 255.0, alpha / 255.0);
+ // set current_color
+ current_color = {red, green, blue, alpha};
+
#ifdef EZGL_USE_X11
// check transparency
if(alpha != 255)
@@ -185,9 +218,10 @@
auto cairo_cap = static_cast<cairo_line_cap_t>(cap);
cairo_set_line_cap(m_cairo, cairo_cap);
+ current_line_cap = cap;
+
#ifdef EZGL_USE_X11
if (x11_display != nullptr) {
- current_line_cap = cap;
XSetLineAttributes(x11_display, x11_context, current_line_width,
current_line_dash == line_dash::none ? LineSolid : LineOnOffDash,
current_line_cap == line_cap::butt ? CapButt : CapRound, JoinMiter);
@@ -208,9 +242,10 @@
cairo_set_dash(m_cairo, dashes, num_dashes, 0);
}
+ current_line_dash = dash;
+
#ifdef EZGL_USE_X11
if (x11_display != nullptr) {
- current_line_dash = dash;
XSetLineAttributes(x11_display, x11_context, current_line_width,
current_line_dash == line_dash::none ? LineSolid : LineOnOffDash,
current_line_cap == line_cap::butt ? CapButt : CapRound, JoinMiter);
@@ -222,9 +257,10 @@
{
cairo_set_line_width(m_cairo, width == 0 ? 1 : width);
+ current_line_width = width;
+
#ifdef EZGL_USE_X11
if (x11_display != nullptr) {
- current_line_width = width;
XSetLineAttributes(x11_display, x11_context, current_line_width,
current_line_dash == line_dash::none ? LineSolid : LineOnOffDash,
current_line_cap == line_cap::butt ? CapButt : CapRound, JoinMiter);
diff --git a/libs/libarchfpga/src/parse_switchblocks.cpp b/libs/libarchfpga/src/parse_switchblocks.cpp
index e40bfb2..e9d8cad 100644
--- a/libs/libarchfpga/src/parse_switchblocks.cpp
+++ b/libs/libarchfpga/src/parse_switchblocks.cpp
@@ -32,8 +32,7 @@
#include "physical_types.h"
#include "parse_switchblocks.h"
-using namespace std;
-using namespace pugiutil;
+using pugiutil::ReqOpt;
/**** Function Declarations ****/
/*---- Functions for Parsing Switchblocks from Architecture ----*/
@@ -85,7 +84,7 @@
pugi::xml_node SubElem;
/* count the number of specified wire connections for this SB */
- num_wireconns = count_children(Node, "wireconn", loc_data, OPTIONAL);
+ num_wireconns = count_children(Node, "wireconn", loc_data, ReqOpt::OPTIONAL);
sb->wireconns.reserve(num_wireconns);
if (num_wireconns > 0) {
@@ -266,11 +265,11 @@
pugi::xml_node SubElem;
/* get the number of specified permutation functions */
- int num_funcs = count_children(Node, "func", loc_data, OPTIONAL);
+ int num_funcs = count_children(Node, "func", loc_data, ReqOpt::OPTIONAL);
const char* func_type;
const char* func_formula;
- vector<string>* func_ptr;
+ std::vector<std::string>* func_ptr;
/* used to index into permutation map of switchblock */
SB_Side_Connection conn;
@@ -319,7 +318,7 @@
func_ptr = &(sb->permutation_map[conn]);
/* Here we load the specified switch function(s) */
- func_ptr->push_back(string(func_formula));
+ func_ptr->push_back(std::string(func_formula));
func_ptr = nullptr;
/* get the next switchblock function */
diff --git a/libs/libarchfpga/src/physical_types.h b/libs/libarchfpga/src/physical_types.h
index 794f04f..7743a39 100644
--- a/libs/libarchfpga/src/physical_types.h
+++ b/libs/libarchfpga/src/physical_types.h
@@ -1276,6 +1276,10 @@
//float Cmetal_per_m; /* Wire capacitance (per meter) */
};
+inline bool operator==(const t_segment_inf& a, const t_segment_inf& b) {
+ return a.name == b.name && a.frequency == b.frequency && a.length == b.length && a.arch_wire_switch == b.arch_wire_switch && a.arch_opin_switch == b.arch_opin_switch && a.frac_cb == b.frac_cb && a.frac_sb == b.frac_sb && a.longline == b.longline && a.Rmetal == b.Rmetal && a.Cmetal == b.Cmetal && a.directionality == b.directionality && a.cb == b.cb && a.sb == b.sb;
+}
+
enum class SwitchType {
MUX = 0, //A configurable (buffered) mux (single-driver)
TRISTATE, //A configurable tristate-able buffer (multi-driver)
diff --git a/libs/libarchfpga/src/read_xml_arch_file.cpp b/libs/libarchfpga/src/read_xml_arch_file.cpp
index bd1f528..dcca451 100644
--- a/libs/libarchfpga/src/read_xml_arch_file.cpp
+++ b/libs/libarchfpga/src/read_xml_arch_file.cpp
@@ -61,8 +61,8 @@
#include "read_xml_util.h"
#include "parse_switchblocks.h"
-using namespace std;
-using namespace pugiutil;
+using namespace std::string_literals;
+using pugiutil::ReqOpt;
struct t_fc_override {
std::string port_name;
@@ -257,7 +257,7 @@
/* TODO: do version processing properly with string delimiting on the . */
#if 0
- char* Prop = get_attribute(architecture, "version", loc_data, OPTIONAL).as_string(NULL);
+ char* Prop = get_attribute(architecture, "version", loc_data, ReqOpt::OPTIONAL).as_string(NULL);
if (Prop != NULL) {
if (atof(Prop) > atof(VPR_VERSION)) {
VTR_LOG_WARN( "This architecture version is for VPR %f while your current VPR version is " VPR_VERSION ", compatability issues may arise\n",
@@ -310,7 +310,7 @@
link_physical_logical_types(PhysicalTileTypes, LogicalBlockTypes);
/* Process directs */
- Next = get_single_child(architecture, "directlist", loc_data, OPTIONAL);
+ Next = get_single_child(architecture, "directlist", loc_data, ReqOpt::OPTIONAL);
if (Next) {
ProcessDirects(Next, &(arch->Directs), &(arch->num_directs),
arch->Switches, arch->num_switches,
@@ -318,7 +318,7 @@
}
/* Process Clock Networks */
- Next = get_single_child(architecture, "clocknetworks", loc_data, OPTIONAL);
+ Next = get_single_child(architecture, "clocknetworks", loc_data, ReqOpt::OPTIONAL);
if (Next) {
std::vector<std::string> expected_children = {"metal_layers", "clock_network", "clock_routing"};
expect_only_children(Next, expected_children, loc_data);
@@ -342,9 +342,9 @@
* then the power architecture information is required.
*/
if (arch->power) {
- POWER_REQD = REQUIRED;
+ POWER_REQD = ReqOpt::REQUIRED;
} else {
- POWER_REQD = OPTIONAL;
+ POWER_REQD = ReqOpt::OPTIONAL;
}
Next = get_single_child(architecture, "power", loc_data, POWER_REQD);
@@ -381,7 +381,7 @@
SyncModelsPbTypes(arch, LogicalBlockTypes);
UpdateAndCheckModels(arch);
- } catch (XmlError& e) {
+ } catch (pugiutil::XmlError& e) {
archfpga_throw(ArchFile, e.line(),
"%s", e.what());
}
@@ -465,8 +465,8 @@
expect_only_attributes(Cur, {"side", "xoffset", "yoffset"}, loc_data);
/* Get offset (ie. height) */
- int x_offset = get_attribute(Cur, "xoffset", loc_data, OPTIONAL).as_int(0);
- int y_offset = get_attribute(Cur, "yoffset", loc_data, OPTIONAL).as_int(0);
+ int x_offset = get_attribute(Cur, "xoffset", loc_data, ReqOpt::OPTIONAL).as_int(0);
+ int y_offset = get_attribute(Cur, "yoffset", loc_data, ReqOpt::OPTIONAL).as_int(0);
/* Get side */
e_side side = TOP;
@@ -950,16 +950,16 @@
int i = 0;
const char* Prop;
- if (get_attribute(Parent, "max", loc_data, OPTIONAL).as_string(nullptr)) {
+ if (get_attribute(Parent, "max", loc_data, ReqOpt::OPTIONAL).as_string(nullptr)) {
i++;
}
- if (get_attribute(Parent, "min", loc_data, OPTIONAL).as_string(nullptr)) {
+ if (get_attribute(Parent, "min", loc_data, ReqOpt::OPTIONAL).as_string(nullptr)) {
i++;
}
- if (get_attribute(Parent, "type", loc_data, OPTIONAL).as_string(nullptr)) {
+ if (get_attribute(Parent, "type", loc_data, ReqOpt::OPTIONAL).as_string(nullptr)) {
i++;
}
- if (get_attribute(Parent, "value", loc_data, OPTIONAL).as_string(nullptr)) {
+ if (get_attribute(Parent, "value", loc_data, ReqOpt::OPTIONAL).as_string(nullptr)) {
i++;
}
if (0 == strcmp(Parent.name(), "C_constant")
@@ -977,13 +977,13 @@
if (0 == strcmp(Parent.name(), "delay_constant")) {
annotation->type = E_ANNOT_PIN_TO_PIN_DELAY;
annotation->format = E_ANNOT_PIN_TO_PIN_CONSTANT;
- Prop = get_attribute(Parent, "max", loc_data, OPTIONAL).as_string(nullptr);
+ Prop = get_attribute(Parent, "max", loc_data, ReqOpt::OPTIONAL).as_string(nullptr);
if (Prop) {
annotation->prop[i] = (int)E_ANNOT_PIN_TO_PIN_DELAY_MAX;
annotation->value[i] = vtr::strdup(Prop);
i++;
}
- Prop = get_attribute(Parent, "min", loc_data, OPTIONAL).as_string(nullptr);
+ Prop = get_attribute(Parent, "min", loc_data, ReqOpt::OPTIONAL).as_string(nullptr);
if (Prop) {
annotation->prop[i] = (int)E_ANNOT_PIN_TO_PIN_DELAY_MIN;
annotation->value[i] = vtr::strdup(Prop);
@@ -1023,10 +1023,10 @@
annotation->prop[i] = (int)E_ANNOT_PIN_TO_PIN_CAPACITANCE_C;
i++;
- Prop = get_attribute(Parent, "in_port", loc_data, OPTIONAL).as_string(nullptr);
+ Prop = get_attribute(Parent, "in_port", loc_data, ReqOpt::OPTIONAL).as_string(nullptr);
annotation->input_pins = vtr::strdup(Prop);
- Prop = get_attribute(Parent, "out_port", loc_data, OPTIONAL).as_string(nullptr);
+ Prop = get_attribute(Parent, "out_port", loc_data, ReqOpt::OPTIONAL).as_string(nullptr);
annotation->output_pins = vtr::strdup(Prop);
VTR_ASSERT(annotation->output_pins != nullptr || annotation->input_pins != nullptr);
@@ -1037,10 +1037,10 @@
annotation->prop[i] = (int)E_ANNOT_PIN_TO_PIN_CAPACITANCE_C;
i++;
- Prop = get_attribute(Parent, "in_port", loc_data, OPTIONAL).as_string(nullptr);
+ Prop = get_attribute(Parent, "in_port", loc_data, ReqOpt::OPTIONAL).as_string(nullptr);
annotation->input_pins = vtr::strdup(Prop);
- Prop = get_attribute(Parent, "out_port", loc_data, OPTIONAL).as_string(nullptr);
+ Prop = get_attribute(Parent, "out_port", loc_data, ReqOpt::OPTIONAL).as_string(nullptr);
annotation->output_pins = vtr::strdup(Prop);
VTR_ASSERT(annotation->output_pins != nullptr || annotation->input_pins != nullptr);
@@ -1063,7 +1063,7 @@
} else if (0 == strcmp(Parent.name(), "T_clock_to_Q")) {
annotation->type = E_ANNOT_PIN_TO_PIN_DELAY;
annotation->format = E_ANNOT_PIN_TO_PIN_CONSTANT;
- Prop = get_attribute(Parent, "max", loc_data, OPTIONAL).as_string(nullptr);
+ Prop = get_attribute(Parent, "max", loc_data, ReqOpt::OPTIONAL).as_string(nullptr);
bool found_min_max_attrib = false;
if (Prop) {
@@ -1072,7 +1072,7 @@
i++;
found_min_max_attrib = true;
}
- Prop = get_attribute(Parent, "min", loc_data, OPTIONAL).as_string(nullptr);
+ Prop = get_attribute(Parent, "min", loc_data, ReqOpt::OPTIONAL).as_string(nullptr);
if (Prop) {
annotation->prop[i] = (int)E_ANNOT_PIN_TO_PIN_DELAY_CLOCK_TO_Q_MIN;
annotation->value[i] = vtr::strdup(Prop);
@@ -1138,7 +1138,7 @@
t_port* port;
int high, low;
- cur = get_first_child(parent, "port", loc_data, OPTIONAL);
+ cur = get_first_child(parent, "port", loc_data, ReqOpt::OPTIONAL);
while (cur) {
prop = get_attribute(cur, "name", loc_data).value();
@@ -1166,9 +1166,9 @@
/* Get scaled by factor */
bool reverse_scaled = false;
- prop = get_attribute(cur, "scaled_by_static_prob", loc_data, OPTIONAL).as_string(nullptr);
+ prop = get_attribute(cur, "scaled_by_static_prob", loc_data, ReqOpt::OPTIONAL).as_string(nullptr);
if (!prop) {
- prop = get_attribute(cur, "scaled_by_static_prob_n", loc_data, OPTIONAL).as_string(nullptr);
+ prop = get_attribute(cur, "scaled_by_static_prob_n", loc_data, ReqOpt::OPTIONAL).as_string(nullptr);
if (prop) {
reverse_scaled = true;
}
@@ -1196,7 +1196,7 @@
bool require_static_absolute = false;
bool require_dynamic_C_internal = false;
- cur = get_first_child(Parent, "power", loc_data, OPTIONAL);
+ cur = get_first_child(Parent, "power", loc_data, ReqOpt::OPTIONAL);
if (!cur) {
return;
}
@@ -1244,9 +1244,9 @@
prop = nullptr;
- cur = get_first_child(Parent, "power", loc_data, OPTIONAL);
+ cur = get_first_child(Parent, "power", loc_data, ReqOpt::OPTIONAL);
if (cur) {
- prop = get_attribute(cur, "method", loc_data, OPTIONAL).as_string(nullptr);
+ prop = get_attribute(cur, "method", loc_data, ReqOpt::OPTIONAL).as_string(nullptr);
}
if (pb_type->parent_mode && pb_type->parent_mode->parent_pb_type) {
@@ -1286,7 +1286,7 @@
pugi::xml_node Cur;
bool is_root_pb_type = !(mode != nullptr && mode->parent_pb_type != nullptr);
- bool is_leaf_pb_type = bool(get_attribute(Parent, "blif_model", loc_data, OPTIONAL));
+ bool is_leaf_pb_type = bool(get_attribute(Parent, "blif_model", loc_data, ReqOpt::OPTIONAL));
std::vector<std::string> children_to_expect = {"input", "output", "clock", "mode", "power", "metadata"};
if (!is_leaf_pb_type) {
@@ -1319,10 +1319,10 @@
char* class_name;
/* STL maps for checking various duplicate names */
- map<string, int> pb_port_names;
- map<string, int> mode_names;
- pair<map<string, int>::iterator, bool> ret_pb_ports;
- pair<map<string, int>::iterator, bool> ret_mode_names;
+ std::map<std::string, int> pb_port_names;
+ std::map<std::string, int> mode_names;
+ std::pair<std::map<std::string, int>::iterator, bool> ret_pb_ports;
+ std::pair<std::map<std::string, int>::iterator, bool> ret_mode_names;
int num_in_ports, num_out_ports, num_clock_ports;
int num_delay_constant, num_delay_matrix, num_C_constant, num_C_matrix,
num_T_setup, num_T_cq, num_T_hold;
@@ -1337,11 +1337,11 @@
/* same name as type */
}
- Prop = get_attribute(Parent, "blif_model", loc_data, OPTIONAL).as_string(nullptr);
+ Prop = get_attribute(Parent, "blif_model", loc_data, ReqOpt::OPTIONAL).as_string(nullptr);
pb_type->blif_model = vtr::strdup(Prop);
pb_type->class_type = UNKNOWN_CLASS;
- Prop = get_attribute(Parent, "class", loc_data, OPTIONAL).as_string(nullptr);
+ Prop = get_attribute(Parent, "class", loc_data, ReqOpt::OPTIONAL).as_string(nullptr);
class_name = vtr::strdup(Prop);
if (class_name) {
@@ -1367,9 +1367,9 @@
VTR_ASSERT(pb_type->num_pb > 0);
num_ports = num_in_ports = num_out_ports = num_clock_ports = 0;
- num_in_ports = count_children(Parent, "input", loc_data, OPTIONAL);
- num_out_ports = count_children(Parent, "output", loc_data, OPTIONAL);
- num_clock_ports = count_children(Parent, "clock", loc_data, OPTIONAL);
+ num_in_ports = count_children(Parent, "input", loc_data, ReqOpt::OPTIONAL);
+ num_out_ports = count_children(Parent, "output", loc_data, ReqOpt::OPTIONAL);
+ num_clock_ports = count_children(Parent, "clock", loc_data, ReqOpt::OPTIONAL);
num_ports = num_in_ports + num_out_ports + num_clock_ports;
pb_type->ports = (t_port*)vtr::calloc(num_ports, sizeof(t_port));
pb_type->num_ports = num_ports;
@@ -1396,13 +1396,13 @@
for (i = 0; i < 3; i++) {
if (i == 0) {
k = 0;
- Cur = get_first_child(Parent, "input", loc_data, OPTIONAL);
+ Cur = get_first_child(Parent, "input", loc_data, ReqOpt::OPTIONAL);
} else if (i == 1) {
k = 0;
- Cur = get_first_child(Parent, "output", loc_data, OPTIONAL);
+ Cur = get_first_child(Parent, "output", loc_data, ReqOpt::OPTIONAL);
} else {
k = 0;
- Cur = get_first_child(Parent, "clock", loc_data, OPTIONAL);
+ Cur = get_first_child(Parent, "clock", loc_data, ReqOpt::OPTIONAL);
}
while (Cur) {
pb_type->ports[j].parent_pb_type = pb_type;
@@ -1412,7 +1412,7 @@
pb_type->pb_type_power->estimation_method, is_root_pb_type, loc_data);
//Check port name duplicates
- ret_pb_ports = pb_port_names.insert(pair<string, int>(pb_type->ports[j].name, 0));
+ ret_pb_ports = pb_port_names.insert(std::pair<std::string, int>(pb_type->ports[j].name, 0));
if (!ret_pb_ports.second) {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(Cur),
"Duplicate port names in pb_type '%s': port '%s'\n",
@@ -1447,7 +1447,7 @@
//TODO: eventually remove
try {
expect_child_node_count(Parent, "max_internal_delay", 0, loc_data);
- } catch (XmlError& e) {
+ } catch (pugiutil::XmlError& e) {
std::string msg = e.what();
msg += ". <max_internal_delay> has been replaced with <delay_constant>/<delay_matrix> between sequential primitive ports.";
msg += " Please upgrade your architecture file.";
@@ -1461,13 +1461,13 @@
if (pb_type->blif_model != nullptr) {
/* Process delay and capacitance annotations */
num_annotations = 0;
- num_delay_constant = count_children(Parent, "delay_constant", loc_data, OPTIONAL);
- num_delay_matrix = count_children(Parent, "delay_matrix", loc_data, OPTIONAL);
- num_C_constant = count_children(Parent, "C_constant", loc_data, OPTIONAL);
- num_C_matrix = count_children(Parent, "C_matrix", loc_data, OPTIONAL);
- num_T_setup = count_children(Parent, "T_setup", loc_data, OPTIONAL);
- num_T_cq = count_children(Parent, "T_clock_to_Q", loc_data, OPTIONAL);
- num_T_hold = count_children(Parent, "T_hold", loc_data, OPTIONAL);
+ num_delay_constant = count_children(Parent, "delay_constant", loc_data, ReqOpt::OPTIONAL);
+ num_delay_matrix = count_children(Parent, "delay_matrix", loc_data, ReqOpt::OPTIONAL);
+ num_C_constant = count_children(Parent, "C_constant", loc_data, ReqOpt::OPTIONAL);
+ num_C_matrix = count_children(Parent, "C_matrix", loc_data, ReqOpt::OPTIONAL);
+ num_T_setup = count_children(Parent, "T_setup", loc_data, ReqOpt::OPTIONAL);
+ num_T_cq = count_children(Parent, "T_clock_to_Q", loc_data, ReqOpt::OPTIONAL);
+ num_T_hold = count_children(Parent, "T_hold", loc_data, ReqOpt::OPTIONAL);
num_annotations = num_delay_constant + num_delay_matrix + num_C_constant
+ num_C_matrix + num_T_setup + num_T_cq + num_T_hold;
@@ -1477,19 +1477,19 @@
j = 0;
for (i = 0; i < 7; i++) {
if (i == 0) {
- Cur = get_first_child(Parent, "delay_constant", loc_data, OPTIONAL);
+ Cur = get_first_child(Parent, "delay_constant", loc_data, ReqOpt::OPTIONAL);
} else if (i == 1) {
- Cur = get_first_child(Parent, "delay_matrix", loc_data, OPTIONAL);
+ Cur = get_first_child(Parent, "delay_matrix", loc_data, ReqOpt::OPTIONAL);
} else if (i == 2) {
- Cur = get_first_child(Parent, "C_constant", loc_data, OPTIONAL);
+ Cur = get_first_child(Parent, "C_constant", loc_data, ReqOpt::OPTIONAL);
} else if (i == 3) {
- Cur = get_first_child(Parent, "C_matrix", loc_data, OPTIONAL);
+ Cur = get_first_child(Parent, "C_matrix", loc_data, ReqOpt::OPTIONAL);
} else if (i == 4) {
- Cur = get_first_child(Parent, "T_setup", loc_data, OPTIONAL);
+ Cur = get_first_child(Parent, "T_setup", loc_data, ReqOpt::OPTIONAL);
} else if (i == 5) {
- Cur = get_first_child(Parent, "T_clock_to_Q", loc_data, OPTIONAL);
+ Cur = get_first_child(Parent, "T_clock_to_Q", loc_data, ReqOpt::OPTIONAL);
} else if (i == 6) {
- Cur = get_first_child(Parent, "T_hold", loc_data, OPTIONAL);
+ Cur = get_first_child(Parent, "T_hold", loc_data, ReqOpt::OPTIONAL);
}
while (Cur) {
ProcessPinToPinAnnotations(Cur, &pb_type->annotations[j],
@@ -1514,12 +1514,12 @@
} else {
/* other leaf pb_type do not have modes */
pb_type->num_modes = 0;
- VTR_ASSERT(count_children(Parent, "mode", loc_data, OPTIONAL) == 0);
+ VTR_ASSERT(count_children(Parent, "mode", loc_data, ReqOpt::OPTIONAL) == 0);
}
} else {
/* container pb_type, process modes */
VTR_ASSERT(pb_type->class_type == UNKNOWN_CLASS);
- pb_type->num_modes = count_children(Parent, "mode", loc_data, OPTIONAL);
+ pb_type->num_modes = count_children(Parent, "mode", loc_data, ReqOpt::OPTIONAL);
pb_type->pb_type_power->leakage_default_mode = 0;
if (pb_type->num_modes == 0) {
@@ -1540,7 +1540,7 @@
pb_type->modes[i].index = i;
ProcessMode(Cur, &pb_type->modes[i], timing_enabled, arch, loc_data);
- ret_mode_names = mode_names.insert(pair<string, int>(pb_type->modes[i].name, 0));
+ ret_mode_names = mode_names.insert(std::pair<std::string, int>(pb_type->modes[i].name, 0));
if (!ret_mode_names.second) {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(Cur),
"Duplicate mode name: '%s' in pb_type '%s'.\n",
@@ -1579,13 +1579,13 @@
port->port_power->buffer_type = POWER_BUFFER_TYPE_NONE;
}
- cur = get_single_child(Parent, "power", loc_data, OPTIONAL);
+ cur = get_single_child(Parent, "power", loc_data, ReqOpt::OPTIONAL);
if (cur) {
/* Wire capacitance */
/* Absolute C provided */
- prop = get_attribute(cur, "wire_capacitance", loc_data, OPTIONAL).as_string(nullptr);
+ prop = get_attribute(cur, "wire_capacitance", loc_data, ReqOpt::OPTIONAL).as_string(nullptr);
if (prop) {
if (!(power_method == POWER_METHOD_AUTO_SIZES
|| power_method == POWER_METHOD_SPECIFY_SIZES)) {
@@ -1600,7 +1600,7 @@
}
/* Wire absolute length provided */
- prop = get_attribute(cur, "wire_length", loc_data, OPTIONAL).as_string(nullptr);
+ prop = get_attribute(cur, "wire_length", loc_data, ReqOpt::OPTIONAL).as_string(nullptr);
if (prop) {
if (!(power_method == POWER_METHOD_AUTO_SIZES
|| power_method == POWER_METHOD_SPECIFY_SIZES)) {
@@ -1622,7 +1622,7 @@
}
/* Wire relative length provided */
- prop = get_attribute(cur, "wire_relative_length", loc_data, OPTIONAL).as_string(nullptr);
+ prop = get_attribute(cur, "wire_relative_length", loc_data, ReqOpt::OPTIONAL).as_string(nullptr);
if (prop) {
if (!(power_method == POWER_METHOD_AUTO_SIZES
|| power_method == POWER_METHOD_SPECIFY_SIZES)) {
@@ -1641,7 +1641,7 @@
}
/* Buffer Size */
- prop = get_attribute(cur, "buffer_size", loc_data, OPTIONAL).as_string(nullptr);
+ prop = get_attribute(cur, "buffer_size", loc_data, ReqOpt::OPTIONAL).as_string(nullptr);
if (prop) {
if (!(power_method == POWER_METHOD_AUTO_SIZES
|| power_method == POWER_METHOD_SPECIFY_SIZES)) {
@@ -1674,10 +1674,10 @@
Prop = get_attribute(Parent, "name", loc_data).value();
port->name = vtr::strdup(Prop);
- Prop = get_attribute(Parent, "port_class", loc_data, OPTIONAL).as_string(nullptr);
+ Prop = get_attribute(Parent, "port_class", loc_data, ReqOpt::OPTIONAL).as_string(nullptr);
port->port_class = vtr::strdup(Prop);
- Prop = get_attribute(Parent, "equivalent", loc_data, OPTIONAL).as_string(nullptr);
+ Prop = get_attribute(Parent, "equivalent", loc_data, ReqOpt::OPTIONAL).as_string(nullptr);
if (Prop) {
if (Prop == "none"s) {
port->equivalent = PortEquivalence::NONE;
@@ -1697,7 +1697,7 @@
}
port->num_pins = get_attribute(Parent, "num_pins", loc_data).as_int(0);
port->is_non_clock_global = get_attribute(Parent,
- "is_non_clock_global", loc_data, OPTIONAL)
+ "is_non_clock_global", loc_data, ReqOpt::OPTIONAL)
.as_bool(false);
if (port->num_pins <= 0) {
@@ -1804,13 +1804,13 @@
pugi::xml_node Cur;
pugi::xml_node Cur2;
- map<string, int> interc_names;
- pair<map<string, int>::iterator, bool> ret_interc_names;
+ std::map<std::string, int> interc_names;
+ std::pair<std::map<std::string, int>::iterator, bool> ret_interc_names;
num_complete = num_direct = num_mux = 0;
- num_complete = count_children(Parent, "complete", loc_data, OPTIONAL);
- num_direct = count_children(Parent, "direct", loc_data, OPTIONAL);
- num_mux = count_children(Parent, "mux", loc_data, OPTIONAL);
+ num_complete = count_children(Parent, "complete", loc_data, ReqOpt::OPTIONAL);
+ num_direct = count_children(Parent, "direct", loc_data, ReqOpt::OPTIONAL);
+ num_mux = count_children(Parent, "mux", loc_data, ReqOpt::OPTIONAL);
num_interconnect = num_complete + num_direct + num_mux;
mode->num_interconnect = num_interconnect;
@@ -1819,11 +1819,11 @@
i = 0;
for (L_index = 0; L_index < 3; L_index++) {
if (L_index == 0) {
- Cur = get_first_child(Parent, "complete", loc_data, OPTIONAL);
+ Cur = get_first_child(Parent, "complete", loc_data, ReqOpt::OPTIONAL);
} else if (L_index == 1) {
- Cur = get_first_child(Parent, "direct", loc_data, OPTIONAL);
+ Cur = get_first_child(Parent, "direct", loc_data, ReqOpt::OPTIONAL);
} else {
- Cur = get_first_child(Parent, "mux", loc_data, OPTIONAL);
+ Cur = get_first_child(Parent, "mux", loc_data, ReqOpt::OPTIONAL);
}
while (Cur != nullptr) {
if (0 == strcmp(Cur.name(), "complete")) {
@@ -1850,7 +1850,7 @@
mode->interconnect[i].name = vtr::strdup(Prop);
mode->interconnect[i].meta = ProcessMetadata(Cur, loc_data);
- ret_interc_names = interc_names.insert(pair<string, int>(mode->interconnect[i].name, 0));
+ ret_interc_names = interc_names.insert(std::pair<std::string, int>(mode->interconnect[i].name, 0));
if (!ret_interc_names.second) {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(Cur),
"Duplicate interconnect name: '%s' in mode: '%s'.\n",
@@ -1859,11 +1859,11 @@
/* Process delay and capacitance annotations */
num_annotations = 0;
- num_delay_constant = count_children(Cur, "delay_constant", loc_data, OPTIONAL);
- num_delay_matrix = count_children(Cur, "delay_matrix", loc_data, OPTIONAL);
- num_C_constant = count_children(Cur, "C_constant", loc_data, OPTIONAL);
- num_C_matrix = count_children(Cur, "C_matrix", loc_data, OPTIONAL);
- num_pack_pattern = count_children(Cur, "pack_pattern", loc_data, OPTIONAL);
+ num_delay_constant = count_children(Cur, "delay_constant", loc_data, ReqOpt::OPTIONAL);
+ num_delay_matrix = count_children(Cur, "delay_matrix", loc_data, ReqOpt::OPTIONAL);
+ num_C_constant = count_children(Cur, "C_constant", loc_data, ReqOpt::OPTIONAL);
+ num_C_matrix = count_children(Cur, "C_matrix", loc_data, ReqOpt::OPTIONAL);
+ num_pack_pattern = count_children(Cur, "pack_pattern", loc_data, ReqOpt::OPTIONAL);
num_annotations = num_delay_constant + num_delay_matrix
+ num_C_constant + num_C_matrix + num_pack_pattern;
@@ -1874,15 +1874,15 @@
k = 0;
for (j = 0; j < 5; j++) {
if (j == 0) {
- Cur2 = get_first_child(Cur, "delay_constant", loc_data, OPTIONAL);
+ Cur2 = get_first_child(Cur, "delay_constant", loc_data, ReqOpt::OPTIONAL);
} else if (j == 1) {
- Cur2 = get_first_child(Cur, "delay_matrix", loc_data, OPTIONAL);
+ Cur2 = get_first_child(Cur, "delay_matrix", loc_data, ReqOpt::OPTIONAL);
} else if (j == 2) {
- Cur2 = get_first_child(Cur, "C_constant", loc_data, OPTIONAL);
+ Cur2 = get_first_child(Cur, "C_constant", loc_data, ReqOpt::OPTIONAL);
} else if (j == 3) {
- Cur2 = get_first_child(Cur, "C_matrix", loc_data, OPTIONAL);
+ Cur2 = get_first_child(Cur, "C_matrix", loc_data, ReqOpt::OPTIONAL);
} else if (j == 4) {
- Cur2 = get_first_child(Cur, "pack_pattern", loc_data, OPTIONAL);
+ Cur2 = get_first_child(Cur, "pack_pattern", loc_data, ReqOpt::OPTIONAL);
}
while (Cur2 != nullptr) {
ProcessPinToPinAnnotations(Cur2,
@@ -1914,8 +1914,8 @@
int i;
const char* Prop;
pugi::xml_node Cur;
- map<string, int> pb_type_names;
- pair<map<string, int>::iterator, bool> ret_pb_types;
+ std::map<std::string, int> pb_type_names;
+ std::pair<std::map<std::string, int>::iterator, bool> ret_pb_types;
bool implied_mode = 0 == strcmp(Parent.name(), "pb_type");
if (implied_mode) {
@@ -1925,7 +1925,7 @@
mode->name = vtr::strdup(Prop);
}
- mode->num_pb_type_children = count_children(Parent, "pb_type", loc_data, OPTIONAL);
+ mode->num_pb_type_children = count_children(Parent, "pb_type", loc_data, ReqOpt::OPTIONAL);
if (mode->num_pb_type_children > 0) {
mode->pb_type_children = new t_pb_type[mode->num_pb_type_children];
@@ -1936,7 +1936,7 @@
ProcessPb_Type(Cur, &mode->pb_type_children[i], mode, timing_enabled, arch, loc_data);
ret_pb_types = pb_type_names.insert(
- pair<string, int>(mode->pb_type_children[i].name, 0));
+ std::pair<std::string, int>(mode->pb_type_children[i].name, 0));
if (!ret_pb_types.second) {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(Cur),
"Duplicate pb_type name: '%s' in mode: '%s'.\n",
@@ -1974,7 +1974,7 @@
// <meta>CLBLL_L_</meta>
// </metadata>
t_metadata_dict data;
- auto metadata = get_single_child(Parent, "metadata", loc_data, OPTIONAL);
+ auto metadata = get_single_child(Parent, "metadata", loc_data, ReqOpt::OPTIONAL);
if (metadata) {
auto meta_tag = get_first_child(metadata, "meta", loc_data);
while (meta_tag) {
@@ -2190,7 +2190,7 @@
expect_only_attributes(switchblock_locations, {"pattern", "internal_switch"}, loc_data);
- std::string pattern = get_attribute(switchblock_locations, "pattern", loc_data, OPTIONAL).as_string("external_full_internal_straight");
+ std::string pattern = get_attribute(switchblock_locations, "pattern", loc_data, ReqOpt::OPTIONAL).as_string("external_full_internal_straight");
//Initialize the location specs
size_t width = type->width;
@@ -2214,7 +2214,7 @@
expect_only_attributes(sb_loc, {"type", "xoffset", "yoffset", "switch_override"}, loc_data);
//Determine the type
- std::string sb_type_str = get_attribute(sb_loc, "type", loc_data, OPTIONAL).as_string("full");
+ std::string sb_type_str = get_attribute(sb_loc, "type", loc_data, ReqOpt::OPTIONAL).as_string("full");
e_sb_type sb_type = e_sb_type::FULL;
if (sb_type_str == "none") {
sb_type = e_sb_type::NONE;
@@ -2237,7 +2237,7 @@
//Determine the switch type
int sb_switch_override = DEFAULT_SWITCH;
- auto sb_switch_override_attr = get_attribute(sb_loc, "switch_override", loc_data, OPTIONAL);
+ auto sb_switch_override_attr = get_attribute(sb_loc, "switch_override", loc_data, ReqOpt::OPTIONAL);
if (sb_switch_override_attr) {
std::string sb_switch_override_str = sb_switch_override_attr.as_string();
//Use the specified switch
@@ -2251,7 +2251,7 @@
}
//Get the horizontal offset
- size_t xoffset = get_attribute(sb_loc, "xoffset", loc_data, OPTIONAL).as_uint(0);
+ size_t xoffset = get_attribute(sb_loc, "xoffset", loc_data, ReqOpt::OPTIONAL).as_uint(0);
if (xoffset > width - 1) {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(sb_loc),
"Invalid <sb_loc> 'xoffset' attribute '%zu' (must be in range [%d,%d])\n",
@@ -2259,7 +2259,7 @@
}
//Get the vertical offset
- size_t yoffset = get_attribute(sb_loc, "yoffset", loc_data, OPTIONAL).as_uint(0);
+ size_t yoffset = get_attribute(sb_loc, "yoffset", loc_data, ReqOpt::OPTIONAL).as_uint(0);
if (yoffset > height - 1) {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(sb_loc),
"Invalid <sb_loc> 'yoffset' attribute '%zu' (must be in range [%d,%d])\n",
@@ -2286,7 +2286,7 @@
e_sb_type external_type = e_sb_type::FULL;
//Determine any internal switch override
- auto internal_switch_attr = get_attribute(switchblock_locations, "internal_switch", loc_data, OPTIONAL);
+ auto internal_switch_attr = get_attribute(switchblock_locations, "internal_switch", loc_data, ReqOpt::OPTIONAL);
if (internal_switch_attr) {
std::string internal_switch_name = internal_switch_attr.as_string();
//Use the specified switch
@@ -2353,8 +2353,8 @@
t_model* temp;
int L_index;
/* std::maps for checking duplicates */
- map<string, int> model_name_map;
- pair<map<string, int>::iterator, bool> ret_map_name;
+ std::map<std::string, int> model_name_map;
+ std::pair<std::map<std::string, int>::iterator, bool> ret_map_name;
L_index = NUM_MODELS_IN_LIBRARY;
@@ -2388,7 +2388,7 @@
}
/* Try insert new model, check if already exist at the same time */
- ret_map_name = model_name_map.insert(pair<string, int>(temp->name, 0));
+ ret_map_name = model_name_map.insert(std::pair<std::string, int>(temp->name, 0));
if (!ret_map_name.second) {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(model),
"Duplicate model name: '%s'.\n", temp->name);
@@ -2545,7 +2545,7 @@
grid_def.grid_type = GridDefType::AUTO;
- grid_def.aspect_ratio = get_attribute(layout_type_tag, "aspect_ratio", loc_data, OPTIONAL).as_float(1.);
+ grid_def.aspect_ratio = get_attribute(layout_type_tag, "aspect_ratio", loc_data, ReqOpt::OPTIONAL).as_float(1.);
grid_def.name = "auto";
} else if (layout_type_tag.name() == std::string("fixed_layout")) {
@@ -2815,7 +2815,7 @@
//TODO: eventually remove
try {
expect_child_node_count(Node, "timing", 0, loc_data);
- } catch (XmlError& e) {
+ } catch (pugiutil::XmlError& e) {
std::string msg = e.what();
msg += ". <timing> has been replaced with the <switch_block> tag.";
msg += " Please upgrade your architecture file.";
@@ -2834,11 +2834,11 @@
Cur = get_single_child(Node, "area", loc_data);
expect_only_attributes(Cur, {"grid_logic_tile_area"}, loc_data);
arch->grid_logic_tile_area = get_attribute(Cur, "grid_logic_tile_area",
- loc_data, OPTIONAL)
+ loc_data, ReqOpt::OPTIONAL)
.as_float(0);
//<chan_width_distr> tag
- Cur = get_single_child(Node, "chan_width_distr", loc_data, OPTIONAL);
+ Cur = get_single_child(Node, "chan_width_distr", loc_data, ReqOpt::OPTIONAL);
expect_only_attributes(Cur, {}, loc_data);
if (Cur != nullptr) {
ProcessChanWidthDistr(Cur, arch, loc_data);
@@ -2870,7 +2870,7 @@
ReqOpt CUSTOM_SWITCHBLOCK_REQD = BoolToReqOpt(!custom_switch_block);
arch->Fs = get_attribute(Cur, "fs", loc_data, CUSTOM_SWITCHBLOCK_REQD).as_int(3);
- Cur = get_single_child(Node, "default_fc", loc_data, OPTIONAL);
+ Cur = get_single_child(Node, "default_fc", loc_data, ReqOpt::OPTIONAL);
if (Cur) {
arch_def_fc.specified = true;
expect_only_attributes(Cur, {"in_type", "in_val", "out_type", "out_val"}, loc_data);
@@ -2902,19 +2902,19 @@
const char* Prop;
ReqOpt hasXpeak, hasWidth, hasDc;
- hasXpeak = hasWidth = hasDc = OPTIONAL;
+ hasXpeak = hasWidth = hasDc = ReqOpt::OPTIONAL;
Prop = get_attribute(Node, "distr", loc_data).value();
if (strcmp(Prop, "uniform") == 0) {
chan->type = UNIFORM;
} else if (strcmp(Prop, "gaussian") == 0) {
chan->type = GAUSSIAN;
- hasXpeak = hasWidth = hasDc = REQUIRED;
+ hasXpeak = hasWidth = hasDc = ReqOpt::REQUIRED;
} else if (strcmp(Prop, "pulse") == 0) {
chan->type = PULSE;
- hasXpeak = hasWidth = hasDc = REQUIRED;
+ hasXpeak = hasWidth = hasDc = ReqOpt::REQUIRED;
} else if (strcmp(Prop, "delta") == 0) {
- hasXpeak = hasDc = REQUIRED;
+ hasXpeak = hasDc = ReqOpt::REQUIRED;
chan->type = DELTA;
} else {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(Node),
@@ -2934,7 +2934,7 @@
const pugiutil::loc_data& loc_data) {
pugi::xml_node CurTileType;
pugi::xml_node Cur;
- map<string, int> tile_type_descriptors;
+ std::map<std::string, int> tile_type_descriptors;
/* Alloc the type list. Need one additional t_type_desctiptors:
* 1: empty psuedo-type
@@ -2956,7 +2956,7 @@
/* Parses the properties fields of the type */
ProcessTileProps(CurTileType, &PhysicalTileType, loc_data);
- auto result = tile_type_descriptors.insert(pair<string, int>(PhysicalTileType.name, 0));
+ auto result = tile_type_descriptors.insert(std::pair<std::string, int>(PhysicalTileType.name, 0));
if (!result.second) {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(CurTileType),
"Duplicate tile descriptor name: '%s'.\n", PhysicalTileType.name);
@@ -2975,7 +2975,7 @@
/* Assign Fc, Pin locations ans Switch Block locations to the Physical Tile Type */
/* Load pin names and classes and locations */
- Cur = get_single_child(CurTileType, "pinlocations", loc_data, OPTIONAL);
+ Cur = get_single_child(CurTileType, "pinlocations", loc_data, ReqOpt::OPTIONAL);
SetupPinLocationsAndPinClasses(Cur, &PhysicalTileType, loc_data);
LoadPinLoc(Cur, &PhysicalTileType, loc_data);
@@ -2983,7 +2983,7 @@
//TODO: eventually remove
try {
expect_child_node_count(CurTileType, "gridlocations", 0, loc_data);
- } catch (XmlError& e) {
+ } catch (pugiutil::XmlError& e) {
std::string msg = e.what();
msg += ". <gridlocations> has been replaced by the <auto_layout> and <device_layout> tags in the <layout> section.";
msg += " Please upgrade your architecture file.";
@@ -2991,15 +2991,15 @@
}
/* Load Fc */
- Cur = get_single_child(CurTileType, "fc", loc_data, OPTIONAL);
+ Cur = get_single_child(CurTileType, "fc", loc_data, ReqOpt::OPTIONAL);
Process_Fc(Cur, &PhysicalTileType, arch.Segments, arch_def_fc, loc_data);
//Load switchblock type and location overrides
- Cur = get_single_child(CurTileType, "switchblock_locations", loc_data, OPTIONAL);
+ Cur = get_single_child(CurTileType, "switchblock_locations", loc_data, ReqOpt::OPTIONAL);
ProcessSwitchblockLocations(Cur, &PhysicalTileType, arch, loc_data);
//Load equivalent sites infromation
- Cur = get_single_child(CurTileType, "equivalent_sites", loc_data, REQUIRED);
+ Cur = get_single_child(CurTileType, "equivalent_sites", loc_data, ReqOpt::REQUIRED);
ProcessTileEquivalentSites(Cur, &PhysicalTileType, loc_data);
PhysicalTileType.index = index;
@@ -3026,10 +3026,10 @@
PhysicalTileType->name = vtr::strdup(Prop);
/* Load properties */
- PhysicalTileType->capacity = get_attribute(Node, "capacity", loc_data, OPTIONAL).as_uint(1);
- PhysicalTileType->width = get_attribute(Node, "width", loc_data, OPTIONAL).as_uint(1);
- PhysicalTileType->height = get_attribute(Node, "height", loc_data, OPTIONAL).as_uint(1);
- PhysicalTileType->area = get_attribute(Node, "area", loc_data, OPTIONAL).as_float(UNDEFINED);
+ PhysicalTileType->capacity = get_attribute(Node, "capacity", loc_data, ReqOpt::OPTIONAL).as_uint(1);
+ PhysicalTileType->width = get_attribute(Node, "width", loc_data, ReqOpt::OPTIONAL).as_uint(1);
+ PhysicalTileType->height = get_attribute(Node, "height", loc_data, ReqOpt::OPTIONAL).as_uint(1);
+ PhysicalTileType->area = get_attribute(Node, "area", loc_data, ReqOpt::OPTIONAL).as_float(UNDEFINED);
if (atof(Prop) < 0) {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(Node),
@@ -3047,9 +3047,9 @@
int num_ports, num_in_ports, num_out_ports, num_clock_ports;
num_ports = num_in_ports = num_out_ports = num_clock_ports = 0;
- num_in_ports = count_children(Parent, "input", loc_data, OPTIONAL);
- num_out_ports = count_children(Parent, "output", loc_data, OPTIONAL);
- num_clock_ports = count_children(Parent, "clock", loc_data, OPTIONAL);
+ num_in_ports = count_children(Parent, "input", loc_data, ReqOpt::OPTIONAL);
+ num_out_ports = count_children(Parent, "output", loc_data, ReqOpt::OPTIONAL);
+ num_clock_ports = count_children(Parent, "clock", loc_data, ReqOpt::OPTIONAL);
num_ports = num_in_ports + num_out_ports + num_clock_ports;
int iport = 0;
@@ -3059,13 +3059,13 @@
for (int itype = 0; itype < 3; itype++) {
if (itype == 0) {
k = 0;
- Cur = get_first_child(Parent, "input", loc_data, OPTIONAL);
+ Cur = get_first_child(Parent, "input", loc_data, ReqOpt::OPTIONAL);
} else if (itype == 1) {
k = 0;
- Cur = get_first_child(Parent, "output", loc_data, OPTIONAL);
+ Cur = get_first_child(Parent, "output", loc_data, ReqOpt::OPTIONAL);
} else {
k = 0;
- Cur = get_first_child(Parent, "clock", loc_data, OPTIONAL);
+ Cur = get_first_child(Parent, "clock", loc_data, ReqOpt::OPTIONAL);
}
while (Cur) {
t_physical_tile_port port;
@@ -3078,7 +3078,7 @@
absolute_first_pin_index += port.num_pins;
//Check port name duplicates
- auto result = tile_port_names.insert(pair<std::string, int>(port.name, 0));
+ auto result = tile_port_names.insert(std::pair<std::string, int>(port.name, 0));
if (!result.second) {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(Cur),
"Duplicate port names in tile '%s': port '%s'\n",
@@ -3125,7 +3125,7 @@
Prop = get_attribute(Node, "name", loc_data).value();
port->name = vtr::strdup(Prop);
- Prop = get_attribute(Node, "equivalent", loc_data, OPTIONAL).as_string(nullptr);
+ Prop = get_attribute(Node, "equivalent", loc_data, ReqOpt::OPTIONAL).as_string(nullptr);
if (Prop) {
if (Prop == "none"s) {
port->equivalent = PortEquivalence::NONE;
@@ -3145,7 +3145,7 @@
}
port->num_pins = get_attribute(Node, "num_pins", loc_data).as_int(0);
port->is_non_clock_global = get_attribute(Node,
- "is_non_clock_global", loc_data, OPTIONAL)
+ "is_non_clock_global", loc_data, ReqOpt::OPTIONAL)
.as_bool(false);
if (port->num_pins <= 0) {
@@ -3215,7 +3215,7 @@
const pugiutil::loc_data& loc_data) {
pugi::xml_node CurBlockType;
pugi::xml_node Cur;
- map<string, int> pb_type_descriptors;
+ std::map<std::string, int> pb_type_descriptors;
/* Alloc the type list. Need one additional t_type_desctiptors:
* 1: empty psuedo-type
@@ -3240,7 +3240,7 @@
auto Prop = get_attribute(CurBlockType, "name", loc_data).value();
LogicalBlockType.name = vtr::strdup(Prop);
- auto result = pb_type_descriptors.insert(pair<string, int>(LogicalBlockType.name, 0));
+ auto result = pb_type_descriptors.insert(std::pair<std::string, int>(LogicalBlockType.name, 0));
if (!result.second) {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(CurBlockType),
"Duplicate pb_type descriptor name: '%s'.\n", LogicalBlockType.name);
@@ -3291,7 +3291,7 @@
Node = get_first_child(Parent, "segment", loc_data);
for (i = 0; i < NumSegs; ++i) {
/* Get segment name */
- tmp = get_attribute(Node, "name", loc_data, OPTIONAL).as_string(nullptr);
+ tmp = get_attribute(Node, "name", loc_data, ReqOpt::OPTIONAL).as_string(nullptr);
if (tmp) {
Segs[i].name = std::string(tmp);
} else {
@@ -3301,16 +3301,16 @@
"No name specified for the segment #%d.\n", i);
}
/* set name to default: "unnamed_segment_<segment_index>" */
- stringstream ss;
+ std::stringstream ss;
ss << "unnamed_segment_" << i;
- string dummy = ss.str();
+ std::string dummy = ss.str();
tmp = dummy.c_str();
Segs[i].name = std::string(tmp);
}
/* Get segment length */
length = 1; /* DEFAULT */
- tmp = get_attribute(Node, "length", loc_data, OPTIONAL).as_string(nullptr);
+ tmp = get_attribute(Node, "length", loc_data, ReqOpt::OPTIONAL).as_string(nullptr);
if (tmp) {
if (strcmp(tmp, "longline") == 0) {
Segs[i].longline = true;
@@ -3322,7 +3322,7 @@
/* Get the frequency */
Segs[i].frequency = 1; /* DEFAULT */
- tmp = get_attribute(Node, "freq", loc_data, OPTIONAL).as_string(nullptr);
+ tmp = get_attribute(Node, "freq", loc_data, ReqOpt::OPTIONAL).as_string(nullptr);
if (tmp) {
Segs[i].frequency = (int)(atof(tmp) * MAX_CHANNEL_WIDTH);
}
@@ -3431,7 +3431,7 @@
for (j = 0; j < length; ++j) {
Segs[i].cb[j] = true;
}
- SubElem = get_single_child(Node, "cb", loc_data, OPTIONAL);
+ SubElem = get_single_child(Node, "cb", loc_data, ReqOpt::OPTIONAL);
if (SubElem) {
ProcessCB_SB(SubElem, Segs[i].cb, loc_data);
}
@@ -3441,7 +3441,7 @@
for (j = 0; j < (length + 1); ++j) {
Segs[i].sb[j] = true;
}
- SubElem = get_single_child(Node, "sb", loc_data, OPTIONAL);
+ SubElem = get_single_child(Node, "sb", loc_data, ReqOpt::OPTIONAL);
if (SubElem) {
ProcessCB_SB(SubElem, Segs[i].sb, loc_data);
}
@@ -3658,12 +3658,12 @@
ReqOpt CIN_REQD = TIMING_ENABLE_REQD;
// We have defined the Cinternal parameter as optional, so that the user may specify an
// architecture without Cinternal without breaking the program flow.
- ReqOpt CINTERNAL_REQD = OPTIONAL;
+ ReqOpt CINTERNAL_REQD = ReqOpt::OPTIONAL;
if (arch_switch.type() == SwitchType::SHORT) {
//Cin/Cout are optional on shorts, since they really only have one capacitance
- CIN_REQD = OPTIONAL;
- COUT_REQD = OPTIONAL;
+ CIN_REQD = ReqOpt::OPTIONAL;
+ COUT_REQD = ReqOpt::OPTIONAL;
}
arch_switch.Cin = get_attribute(Node, "Cin", loc_data, CIN_REQD).as_float(0);
arch_switch.Cout = get_attribute(Node, "Cout", loc_data, COUT_REQD).as_float(0);
@@ -3671,7 +3671,7 @@
if (arch_switch.type() == SwitchType::MUX) {
//Only muxes have mux transistors
- arch_switch.mux_trans_size = get_attribute(Node, "mux_trans_size", loc_data, OPTIONAL).as_float(1);
+ arch_switch.mux_trans_size = get_attribute(Node, "mux_trans_size", loc_data, ReqOpt::OPTIONAL).as_float(1);
} else {
arch_switch.mux_trans_size = 0.;
}
@@ -3684,7 +3684,7 @@
arch_switch.power_buffer_type = POWER_BUFFER_TYPE_ABSOLUTE_SIZE;
arch_switch.power_buffer_size = 0.;
} else {
- auto buf_size_attrib = get_attribute(Node, "buf_size", loc_data, OPTIONAL);
+ auto buf_size_attrib = get_attribute(Node, "buf_size", loc_data, ReqOpt::OPTIONAL);
if (!buf_size_attrib || buf_size_attrib.as_string() == std::string("auto")) {
arch_switch.buf_size_type = BufferSize::AUTO;
arch_switch.buf_size = 0.;
@@ -3693,7 +3693,7 @@
arch_switch.buf_size = buf_size_attrib.as_float();
}
- auto power_buf_size = get_attribute(Node, "power_buf_size", loc_data, OPTIONAL).as_string(nullptr);
+ auto power_buf_size = get_attribute(Node, "power_buf_size", loc_data, ReqOpt::OPTIONAL).as_string(nullptr);
if (power_buf_size == nullptr) {
arch_switch.power_buffer_type = POWER_BUFFER_TYPE_AUTO;
} else if (strcmp(power_buf_size, "auto") == 0) {
@@ -3727,14 +3727,14 @@
/* check if switch node has the Tdel property */
bool has_Tdel_prop = false;
- Tdel_prop_value = get_attribute(Node, "Tdel", loc_data, OPTIONAL).as_float(UNDEFINED);
+ Tdel_prop_value = get_attribute(Node, "Tdel", loc_data, ReqOpt::OPTIONAL).as_float(UNDEFINED);
if (Tdel_prop_value != UNDEFINED) {
has_Tdel_prop = true;
}
/* check if switch node has Tdel children */
bool has_Tdel_children = false;
- num_Tdel_children = count_children(Node, "Tdel", loc_data, OPTIONAL);
+ num_Tdel_children = count_children(Node, "Tdel", loc_data, ReqOpt::OPTIONAL);
if (num_Tdel_children != 0) {
has_Tdel_children = true;
}
@@ -3833,13 +3833,13 @@
(*Directs)[i].y_offset = get_attribute(Node, "y_offset", loc_data).as_int(0);
(*Directs)[i].z_offset = get_attribute(Node, "z_offset", loc_data).as_int(0);
- std::string from_side_str = get_attribute(Node, "from_side", loc_data, OPTIONAL).value();
+ std::string from_side_str = get_attribute(Node, "from_side", loc_data, ReqOpt::OPTIONAL).value();
(*Directs)[i].from_side = string_to_side(from_side_str);
- std::string to_side_str = get_attribute(Node, "to_side", loc_data, OPTIONAL).value();
+ std::string to_side_str = get_attribute(Node, "to_side", loc_data, ReqOpt::OPTIONAL).value();
(*Directs)[i].to_side = string_to_side(to_side_str);
//Set the optional switch type
- switch_name = get_attribute(Node, "switch_name", loc_data, OPTIONAL).as_string(nullptr);
+ switch_name = get_attribute(Node, "switch_name", loc_data, ReqOpt::OPTIONAL).as_string(nullptr);
if (switch_name != nullptr) {
//Look-up the user defined switch
for (j = 0; j < NumSwitches; j++) {
@@ -3930,7 +3930,7 @@
pugi::xml_node curr_type;
// Parse spine
- curr_type = get_single_child(curr_network, "spine", loc_data, OPTIONAL);
+ curr_type = get_single_child(curr_network, "spine", loc_data, ReqOpt::OPTIONAL);
if (curr_type) {
expect_only_attributes(curr_network, expected_spine_attributes, loc_data);
@@ -3968,7 +3968,7 @@
}
// Parse rib
- curr_type = get_single_child(curr_network, "rib", loc_data, OPTIONAL);
+ curr_type = get_single_child(curr_network, "rib", loc_data, ReqOpt::OPTIONAL);
if (curr_type) {
expect_only_attributes(curr_network, expected_spine_attributes, loc_data);
@@ -4125,8 +4125,8 @@
const char* from = get_attribute(curr_connection, "from", loc_data).value();
const char* to = get_attribute(curr_connection, "to", loc_data).value();
const char* switch_name = get_attribute(curr_connection, "switch", loc_data).value();
- const char* locationx = get_attribute(curr_connection, "locationx", loc_data, OPTIONAL).value();
- const char* locationy = get_attribute(curr_connection, "locationy", loc_data, OPTIONAL).value();
+ const char* locationx = get_attribute(curr_connection, "locationx", loc_data, ReqOpt::OPTIONAL).value();
+ const char* locationy = get_attribute(curr_connection, "locationy", loc_data, ReqOpt::OPTIONAL).value();
float fc = get_attribute(curr_connection, "fc_val", loc_data).as_float(0.);
int switch_idx;
@@ -4160,15 +4160,15 @@
/* Get the local interconnect capacitances */
power_arch->local_interc_factor = 0.5;
- Cur = get_single_child(parent, "local_interconnect", loc_data, OPTIONAL);
+ Cur = get_single_child(parent, "local_interconnect", loc_data, ReqOpt::OPTIONAL);
if (Cur) {
- power_arch->C_wire_local = get_attribute(Cur, "C_wire", loc_data, OPTIONAL).as_float(0.);
- power_arch->local_interc_factor = get_attribute(Cur, "factor", loc_data, OPTIONAL).as_float(0.5);
+ power_arch->C_wire_local = get_attribute(Cur, "C_wire", loc_data, ReqOpt::OPTIONAL).as_float(0.);
+ power_arch->local_interc_factor = get_attribute(Cur, "factor", loc_data, ReqOpt::OPTIONAL).as_float(0.5);
}
/* Get logical effort factor */
power_arch->logical_effort_factor = 4.0;
- Cur = get_single_child(parent, "buffers", loc_data, OPTIONAL);
+ Cur = get_single_child(parent, "buffers", loc_data, ReqOpt::OPTIONAL);
if (Cur) {
power_arch->logical_effort_factor = get_attribute(Cur,
"logical_effort_factor", loc_data)
@@ -4178,7 +4178,7 @@
/* Get SRAM Size */
power_arch->transistors_per_SRAM_bit = 6.0;
- Cur = get_single_child(parent, "sram", loc_data, OPTIONAL);
+ Cur = get_single_child(parent, "sram", loc_data, ReqOpt::OPTIONAL);
if (Cur) {
power_arch->transistors_per_SRAM_bit = get_attribute(Cur,
"transistors_per_bit", loc_data)
@@ -4187,7 +4187,7 @@
/* Get Mux transistor size */
power_arch->mux_transistor_size = 1.0;
- Cur = get_single_child(parent, "mux_transistor_size", loc_data, OPTIONAL);
+ Cur = get_single_child(parent, "mux_transistor_size", loc_data, ReqOpt::OPTIONAL);
if (Cur) {
power_arch->mux_transistor_size = get_attribute(Cur,
"mux_transistor_size", loc_data)
@@ -4196,14 +4196,14 @@
/* Get FF size */
power_arch->FF_size = 1.0;
- Cur = get_single_child(parent, "FF_size", loc_data, OPTIONAL);
+ Cur = get_single_child(parent, "FF_size", loc_data, ReqOpt::OPTIONAL);
if (Cur) {
power_arch->FF_size = get_attribute(Cur, "FF_size", loc_data).as_float(0);
}
/* Get LUT transistor size */
power_arch->LUT_transistor_size = 1.0;
- Cur = get_single_child(parent, "LUT_transistor_size", loc_data, OPTIONAL);
+ Cur = get_single_child(parent, "LUT_transistor_size", loc_data, ReqOpt::OPTIONAL);
if (Cur) {
power_arch->LUT_transistor_size = get_attribute(Cur,
"LUT_transistor_size", loc_data)
@@ -4217,7 +4217,7 @@
int i;
const char* tmp;
- clocks->num_global_clocks = count_children(Parent, "clock", loc_data, OPTIONAL);
+ clocks->num_global_clocks = count_children(Parent, "clock", loc_data, ReqOpt::OPTIONAL);
/* Alloc the clockdetails */
clocks->clock_inf = nullptr;
diff --git a/libs/libarchfpga/src/read_xml_util.cpp b/libs/libarchfpga/src/read_xml_util.cpp
index 69fc883..784d08a 100644
--- a/libs/libarchfpga/src/read_xml_util.cpp
+++ b/libs/libarchfpga/src/read_xml_util.cpp
@@ -3,14 +3,14 @@
#include "vtr_util.h"
#include "arch_error.h"
-using namespace pugiutil;
+using pugiutil::ReqOpt;
/* Convert bool to ReqOpt enum */
extern ReqOpt BoolToReqOpt(bool b) {
if (b) {
- return REQUIRED;
+ return ReqOpt::REQUIRED;
}
- return OPTIONAL;
+ return ReqOpt::OPTIONAL;
}
InstPort make_inst_port(std::string str, pugi::xml_node node, const pugiutil::loc_data& loc_data) {
diff --git a/libs/librtlnumber/src/include/internal_bits.hpp b/libs/librtlnumber/src/include/internal_bits.hpp
index 108df17..669dd09 100644
--- a/libs/librtlnumber/src/include/internal_bits.hpp
+++ b/libs/librtlnumber/src/include/internal_bits.hpp
@@ -758,19 +758,30 @@
}
/***
- * getters
+ * getters to 64 bit int
*/
int64_t get_value()
{
+ using integer_t = int64_t;
+ size_t bit_size = 8*sizeof(integer_t);
+
assert_Werr( (! this->bitstring.has_unknowns() ) ,
"Invalid Number contains dont care values. number: " + this->bitstring.to_string(false)
);
- int64_t result = 0;
- BitSpace::bit_value_t pad = this->get_padding_bit(); // = this->is_negative();
- for(size_t bit_index = 0; bit_index < this->size(); bit_index++)
+ size_t end = this->size();
+ if(end > bit_size)
{
- int64_t current_bit = static_cast<int64_t>(pad);
+ printf(" === Warning: Returning a 64 bit integer from a larger bitstring (%zu). The bitstring will be truncated\n", bit_size);
+ end = bit_size;
+ }
+
+ integer_t result = 0;
+ BitSpace::bit_value_t pad = this->get_padding_bit(); // = this->is_negative();
+
+ for(size_t bit_index = 0; bit_index < end; bit_index++)
+ {
+ integer_t current_bit = static_cast<integer_t>(pad);
if(bit_index < this->size())
current_bit = this->bitstring.get_bit(bit_index);
diff --git a/libs/libvtrutil/src/vtr_cache.h b/libs/libvtrutil/src/vtr_cache.h
new file mode 100644
index 0000000..d1496d2
--- /dev/null
+++ b/libs/libvtrutil/src/vtr_cache.h
@@ -0,0 +1,44 @@
+#ifndef VTR_CACHE_H_
+#define VTR_CACHE_H_
+
+#include <memory>
+
+namespace vtr {
+
+// Simple cache
+template<typename CacheKey, typename CacheValue>
+class Cache {
+ public:
+ // Clear cache.
+ void clear() {
+ key_ = CacheKey();
+ value_.reset();
+ }
+
+ // Check if the cache is valid, and return the cached value if present and valid.
+ //
+ // Returns nullptr if the cache is invalid.
+ const CacheValue* get(const CacheKey& key) const {
+ if (key == key_ && value_) {
+ return value_.get();
+ } else {
+ return nullptr;
+ }
+ }
+
+ // Update the cache.
+ const CacheValue* set(const CacheKey& key, std::unique_ptr<CacheValue> value) {
+ key_ = key;
+ value_ = std::move(value);
+
+ return value_.get();
+ }
+
+ private:
+ CacheKey key_;
+ std::unique_ptr<CacheValue> value_;
+};
+
+} // namespace vtr
+
+#endif
diff --git a/libs/libvtrutil/src/vtr_geometry.h b/libs/libvtrutil/src/vtr_geometry.h
index e4a5940..533b129 100644
--- a/libs/libvtrutil/src/vtr_geometry.h
+++ b/libs/libvtrutil/src/vtr_geometry.h
@@ -1,6 +1,11 @@
#ifndef VTR_GEOMETRY_H
#define VTR_GEOMETRY_H
#include "vtr_range.h"
+
+#include <vector>
+#include <tuple>
+#include <limits>
+
namespace vtr {
/*
diff --git a/libs/libvtrutil/src/vtr_ndmatrix.h b/libs/libvtrutil/src/vtr_ndmatrix.h
index fe0e848..5f4ab82 100644
--- a/libs/libvtrutil/src/vtr_ndmatrix.h
+++ b/libs/libvtrutil/src/vtr_ndmatrix.h
@@ -28,27 +28,21 @@
// idim: The dimension associated with this proxy
// dim_stride: The stride of this dimension (i.e. how many element in memory between indicies of this dimension)
// start: Pointer to the start of the sub-matrix this proxy represents
- NdMatrixProxy<T, N>(const size_t* dim_sizes, size_t idim, size_t dim_stride, T* start)
+ NdMatrixProxy<T, N>(const size_t* dim_sizes, const size_t* dim_strides, T* start)
: dim_sizes_(dim_sizes)
- , idim_(idim)
- , dim_stride_(dim_stride)
+ , dim_strides_(dim_strides)
, start_(start) {}
const NdMatrixProxy<T, N - 1> operator[](size_t index) const {
VTR_ASSERT_SAFE_MSG(index >= 0, "Index out of range (below dimension minimum)");
- VTR_ASSERT_SAFE_MSG(index < dim_sizes_[idim_], "Index out of range (above dimension maximum)");
-
- size_t next_dim_size = dim_sizes_[idim_ + 1];
- VTR_ASSERT_SAFE_MSG(next_dim_size > 0, "Can not index into zero-sized dimension");
-
- //Determine the stride of the next dimension
- size_t next_dim_stride = dim_stride_ / next_dim_size;
+ VTR_ASSERT_SAFE_MSG(index < dim_sizes_[0], "Index out of range (above dimension maximum)");
+ VTR_ASSERT_SAFE_MSG(dim_sizes_[1] > 0, "Can not index into zero-sized dimension");
//Strip off one dimension
- return NdMatrixProxy<T, N - 1>(dim_sizes_, //Pass the dimension information
- idim_ + 1, //Pass the next dimension
- next_dim_stride, //Pass the stride for the next dimension
- start_ + dim_stride_ * index); //Advance to index in this dimension
+ return NdMatrixProxy<T, N - 1>(
+ dim_sizes_ + 1, //Pass the dimension information
+ dim_strides_ + 1, //Pass the stride for the next dimension
+ start_ + dim_strides_[0] * index); //Advance to index in this dimension
}
NdMatrixProxy<T, N - 1> operator[](size_t index) {
@@ -58,8 +52,7 @@
private:
const size_t* dim_sizes_;
- const size_t idim_;
- const size_t dim_stride_;
+ const size_t* dim_strides_;
T* start_;
};
@@ -67,16 +60,15 @@
template<typename T>
class NdMatrixProxy<T, 1> {
public:
- NdMatrixProxy<T, 1>(const size_t* dim_sizes, size_t idim, size_t dim_stride, T* start)
+ NdMatrixProxy<T, 1>(const size_t* dim_sizes, const size_t* dim_stride, T* start)
: dim_sizes_(dim_sizes)
- , idim_(idim)
- , dim_stride_(dim_stride)
+ , dim_strides_(dim_stride)
, start_(start) {}
const T& operator[](size_t index) const {
- VTR_ASSERT_SAFE_MSG(dim_stride_ == 1, "Final dimension must have stride 1");
+ VTR_ASSERT_SAFE_MSG(dim_strides_[0] == 1, "Final dimension must have stride 1");
VTR_ASSERT_SAFE_MSG(index >= 0, "Index out of range (below dimension minimum)");
- VTR_ASSERT_SAFE_MSG(index < dim_sizes_[idim_], "Index out of range (above dimension maximum)");
+ VTR_ASSERT_SAFE_MSG(index < dim_sizes_[0], "Index out of range (above dimension maximum)");
//Base case
return start_[index];
@@ -103,8 +95,7 @@
private:
const size_t* dim_sizes_;
- const size_t idim_;
- const size_t dim_stride_;
+ const size_t* dim_strides_;
T* start_;
};
@@ -207,12 +198,21 @@
size_ = calc_size();
alloc();
fill(value);
+ if (size_ > 0) {
+ dim_strides_[0] = size_ / dim_sizes_[0];
+ for (size_t dim = 1; dim < N; ++dim) {
+ dim_strides_[dim] = dim_strides_[dim - 1] / dim_sizes_[dim];
+ }
+ } else {
+ dim_strides_.fill(0);
+ }
}
//Reset the matrix to size zero
void clear() {
data_.reset(nullptr);
dim_sizes_.fill(0);
+ dim_strides_.fill(0);
size_ = 0;
}
@@ -242,6 +242,7 @@
using std::swap;
swap(m1.size_, m2.size_);
swap(m1.dim_sizes_, m2.dim_sizes_);
+ swap(m1.dim_strides_, m2.dim_strides_);
swap(m1.data_, m2.data_);
}
@@ -265,6 +266,7 @@
protected:
size_t size_ = 0;
std::array<size_t, N> dim_sizes_;
+ std::array<size_t, N> dim_strides_;
std::unique_ptr<T[]> data_ = nullptr;
};
@@ -316,17 +318,11 @@
VTR_ASSERT_SAFE_MSG(index >= 0, "Index out of range (below dimension minimum)");
VTR_ASSERT_SAFE_MSG(index < this->dim_sizes_[0], "Index out of range (above dimension maximum)");
- //Calculate the stride for the current dimension
- size_t dim_stride = this->size() / this->dim_size(0);
-
- //Calculate the stride for the next dimension
- size_t next_dim_stride = dim_stride / this->dim_size(1);
-
//Peel off the first dimension
- return NdMatrixProxy<T, N - 1>(this->dim_sizes_.data(), //Pass the dimension information
- 1, //Pass the next dimension
- next_dim_stride, //Pass the stride for the next dimension
- this->data_.get() + dim_stride * index); //Advance to index in this dimension
+ return NdMatrixProxy<T, N - 1>(
+ this->dim_sizes_.data() + 1, //Pass the dimension information
+ this->dim_strides_.data() + 1, //Pass the stride for the next dimension
+ this->data_.get() + this->dim_strides_[0] * index); //Advance to index in this dimension
}
//Access an element
diff --git a/libs/libvtrutil/src/vtr_token.cpp b/libs/libvtrutil/src/vtr_token.cpp
index f704f54..0be69eb 100644
--- a/libs/libvtrutil/src/vtr_token.cpp
+++ b/libs/libvtrutil/src/vtr_token.cpp
@@ -5,7 +5,6 @@
*/
#include <cstring>
-using namespace std;
#include "vtr_assert.h"
#include "vtr_log.h"
diff --git a/utils/fasm/src/fasm.cpp b/utils/fasm/src/fasm.cpp
index ca69830..4f1becb 100644
--- a/utils/fasm/src/fasm.cpp
+++ b/utils/fasm/src/fasm.cpp
@@ -57,6 +57,7 @@
blk_type_ = grid_loc.type;
current_blk_has_prefix_ = true;
+ clb_prefix_map_.clear();
std::string grid_prefix;
if(grid_loc.meta != nullptr && grid_loc.meta->has("fasm_prefix")) {
auto* value = grid_loc.meta->get("fasm_prefix");
@@ -106,7 +107,7 @@
auto *interconnect = prev_pin->output_edges[prev_edge]->interconnect;
if(interconnect->meta.has("fasm_mux")) {
- auto* value = interconnect->meta.get("fasm_mux");
+ auto* value = interconnect->meta.get("fasm_mux");
VTR_ASSERT(value != nullptr);
std::string fasm_mux = value->front().as_string();
output_fasm_mux(fasm_mux, interconnect, prev_pin);
@@ -234,10 +235,11 @@
// Check if this PB is `open` and has to be skipped
bool is_parent_pb_null = false;
std::string clb_prefix = build_clb_prefix(pb, pb_graph_node, &is_parent_pb_null);
+ clb_prefix_map_.insert(std::make_pair(pb_graph_node, clb_prefix));
+ clb_prefix_ = clb_prefix;
if (is_parent_pb_null == true) {
return;
}
- clb_prefix_ = clb_prefix;
t_pb_type *pb_type = pb_graph_node->pb_type;
auto *mode = &pb_type->modes[pb->mode];
@@ -619,6 +621,20 @@
walk_routing();
}
+void FasmWriterVisitor::find_clb_prefix(const t_pb_graph_node *node,
+ bool *have_prefix, std::string *clb_prefix) const {
+ while(node != nullptr) {
+ auto clb_prefix_itr = clb_prefix_map_.find(node);
+ *have_prefix = clb_prefix_itr != clb_prefix_map_.end();
+ if(*have_prefix) {
+ *clb_prefix = clb_prefix_itr->second;
+ return;
+ }
+
+ node = node->parent_pb_graph_node;
+ }
+}
+
void FasmWriterVisitor::output_fasm_mux(std::string fasm_mux,
t_interconnect *interconnect,
t_pb_graph_pin *mux_input_pin) {
@@ -627,6 +643,11 @@
auto *port_name = mux_input_pin->port->name;
auto pin_index = mux_input_pin->pin_number;
auto mux_inputs = vtr::split(fasm_mux, "\n");
+
+ bool have_prefix = false;
+ std::string clb_prefix;
+ find_clb_prefix(mux_input_pin->parent_node, &have_prefix, &clb_prefix);
+
for(const auto &mux_input : mux_inputs) {
auto mux_parts = split_fasm_entry(mux_input, "=:", "\t ");
@@ -660,12 +681,13 @@
auto fasm_features = vtr::join(vtr::split(mux_parts[1], ","), "\n");
+
if(root_level_connection) {
// This connection is root level. pb_index selects between
// pb_type_prefixes_, not on the mux input.
if(mux_pb_name == pb_name && mux_port_name == port_name && mux_pin_index == pin_index) {
if(mux_parts[1] != "NULL") {
- output_fasm_features(fasm_features);
+ output_fasm_features(have_prefix, clb_prefix, fasm_features);
}
return;
}
@@ -674,7 +696,7 @@
mux_port_name == port_name &&
mux_pin_index == pin_index) {
if(mux_parts[1] != "NULL") {
- output_fasm_features(fasm_features);
+ output_fasm_features(have_prefix, clb_prefix, fasm_features);
}
return;
}
@@ -686,18 +708,23 @@
}
void FasmWriterVisitor::output_fasm_features(std::string features) const {
+ output_fasm_features(current_blk_has_prefix_, clb_prefix_, features);
+}
+
+void FasmWriterVisitor::output_fasm_features(bool have_clb_prefix, std::string clb_prefix, std::string features) const {
std::stringstream os(features);
while(os) {
std::string feature;
os >> feature;
if(os) {
- if(current_blk_has_prefix_) {
- os_ << blk_prefix_ << clb_prefix_;
+ if(have_clb_prefix) {
+ os_ << blk_prefix_ << clb_prefix;
}
os_ << feature << std::endl;
}
}
+
}
} // namespace fasm
diff --git a/utils/fasm/src/fasm.h b/utils/fasm/src/fasm.h
index 0f0adaa..471a8c2 100644
--- a/utils/fasm/src/fasm.h
+++ b/utils/fasm/src/fasm.h
@@ -67,6 +67,7 @@
private:
void output_fasm_features(std::string features) const;
+ void output_fasm_features(bool have_clb_prefix, std::string clb_prefix, std::string features) const;
void check_features(const t_metadata_dict *meta) const;
void check_interconnect(const t_pb_routes &pb_route, int inode);
void check_for_lut(const t_pb* atom);
@@ -77,6 +78,10 @@
const LutOutputDefinition* find_lut(const t_pb_graph_node* pb_graph_node);
void check_for_param(const t_pb *atom);
+ // Walk from node to parents and search for a CLB prefix.
+ void find_clb_prefix(const t_pb_graph_node *node,
+ bool *have_prefix, std::string *clb_prefix) const;
+
std::ostream& os_;
t_pb_graph_node *root_clb_;
@@ -84,6 +89,7 @@
t_physical_tile_type_ptr blk_type_;
std::string blk_prefix_;
std::string clb_prefix_;
+ std::map<const t_pb_graph_node *, std::string> clb_prefix_map_;
ClusterBlockId current_blk_id_;
std::vector<t_pb_graph_pin**> pb_graph_pin_lookup_from_index_by_type_;
std::map<const t_pb_type*, std::vector<std::pair<std::string, LutOutputDefinition>>> lut_definitions_;
diff --git a/utils/fasm/test/test_fasm.cpp b/utils/fasm/test/test_fasm.cpp
index 1e2c645..9be59ef 100644
--- a/utils/fasm/test/test_fasm.cpp
+++ b/utils/fasm/test/test_fasm.cpp
@@ -83,6 +83,7 @@
bool found_lut6 = false;
bool found_mux1 = false;
bool found_mux2 = false;
+ bool found_mux3 = false;
while(fasm_string) {
// Should see something like:
// CLB.FLE0.N2_LUT5
@@ -104,6 +105,9 @@
if(!found_mux2 && line == "CLB.FLE9.DISABLE_FF") {
found_mux2 = true;
}
+ if(!found_mux3 && line == "CLB.FLE9.IN0") {
+ found_mux3 = true;
+ }
if(line.find("CLB") != std::string::npos) {
auto pos = line.find("LUT[");
@@ -150,6 +154,7 @@
CHECK(found_lut6);
CHECK(found_mux1);
CHECK(found_mux2);
+ CHECK(found_mux3);
vpr_free_all(arch, vpr_setup);
}
diff --git a/utils/fasm/test/test_fasm_arch.xml b/utils/fasm/test/test_fasm_arch.xml
index 4c564fd..dd5ac4b 100644
--- a/utils/fasm/test/test_fasm_arch.xml
+++ b/utils/fasm/test/test_fasm_arch.xml
@@ -150,10 +150,12 @@
<!-- LUT to output is faster than FF to output on a Stratix IV -->
<delay_constant max="25e-12" in_port="lut5.out[0:0]" out_port="ble5.out[0:0]"/>
<delay_constant max="45e-12" in_port="ff[0:0].Q" out_port="ble5.out[0:0]"/>
- <meta name="fasm_mux">
- ff.Q : OUT_MUX.FFQ
- lut5.out : OUT_MUX.LUT,DISABLE_FF
- </meta>
+ <metadata>
+ <meta name="fasm_mux">
+ ff.Q : OUT_MUX.FFQ
+ lut5.out : OUT_MUX.LUT,DISABLE_FF
+ </meta>
+ </metadata>
</mux>
</interconnect>
<metadata>
@@ -189,6 +191,19 @@
<input name="in" num_pins="6"/>
<output name="out" num_pins="1"/>
<clock name="clk" num_pins="1"/>
+ <!-- Define flip-flop -->
+ <pb_type name="ff" blif_model=".latch" num_pb="1" class="flipflop">
+ <input name="D" num_pins="1" port_class="D"/>
+ <output name="Q" num_pins="1" port_class="Q"/>
+ <clock name="clk" num_pins="1" port_class="clock"/>
+ <T_setup value="66e-12" port="ff.D" clock="clk"/>
+ <T_clock_to_Q max="124e-12" port="ff.Q" clock="clk"/>
+ <metadata>
+ <meta name="fasm_prefix">
+ ALUT
+ </meta>
+ </metadata>
+ </pb_type>
<pb_type name="lut6" blif_model=".names" num_pb="1" class="lut">
<input name="in" num_pins="6" port_class="lut_in"/>
<output name="out" num_pins="1" port_class="lut_out"/>
@@ -205,18 +220,24 @@
<meta name="fasm_lut">
LUT6[63:0]
</meta>
+ <meta name="fasm_prefix">
+ ALUT
+ </meta>
</metadata>
</pb_type>
- <!-- Define flip-flop -->
- <pb_type name="ff" blif_model=".latch" num_pb="1" class="flipflop">
- <input name="D" num_pins="1" port_class="D"/>
- <output name="Q" num_pins="1" port_class="Q"/>
- <clock name="clk" num_pins="1" port_class="clock"/>
- <T_setup value="66e-12" port="ff.D" clock="clk"/>
- <T_clock_to_Q max="124e-12" port="ff.Q" clock="clk"/>
- </pb_type>
<interconnect>
- <direct name="direct1" input="ble6.in" output="lut6[0:0].in"/>
+ <direct name="direct1" input="ble6.in" output="lut6[0:0].in">
+ <metadata>
+ <meta name="fasm_mux">
+ ble6.in[0] : IN0
+ ble6.in[1] : IN1
+ ble6.in[2] : IN2
+ ble6.in[3] : IN3
+ ble6.in[4] : IN4
+ ble6.in[5] : IN5
+ </meta>
+ </metadata>
+ </direct>
<direct name="direct2" input="lut6.out" output="ff.D">
<pack_pattern name="ble6" in_port="lut6.out" out_port="ff.D"/>
</direct>
diff --git a/utils/route_diag/src/main.cpp b/utils/route_diag/src/main.cpp
index 1d8e2ea..0c8e095 100644
--- a/utils/route_diag/src/main.cpp
+++ b/utils/route_diag/src/main.cpp
@@ -60,7 +60,8 @@
constexpr int INTERRUPTED_EXIT_CODE = 3; //VPR was interrupted by the user (e.g. SIGINT/ctr-C)
static void do_one_route(int source_node, int sink_node,
- const t_router_opts& router_opts) {
+ const t_router_opts& router_opts,
+ const std::vector<t_segment_inf>& segment_inf) {
/* Returns true as long as found some way to hook up this net, even if that *
* way resulted in overuse of resources (congestion). If there is no way *
* to route this net, even ignoring congestion, it returns false. In this *
@@ -92,7 +93,12 @@
std::vector<int> modified_rr_node_inf;
RouterStats router_stats;
- auto router_lookahead = make_router_lookahead(router_opts.lookahead_type);
+ auto router_lookahead = make_router_lookahead(
+ router_opts.lookahead_type,
+ router_opts.write_router_lookahead,
+ router_opts.read_router_lookahead,
+ segment_inf
+ );
t_heap* cheapest = timing_driven_route_connection_from_route_tree(rt_root, sink_node, cost_params, bounding_box, *router_lookahead, modified_rr_node_inf, router_stats);
bool found_path = (cheapest != nullptr);
@@ -123,11 +129,20 @@
}
static void profile_source(int source_rr_node,
- const t_router_opts& router_opts) {
+ const t_router_opts& router_opts,
+ const std::vector<t_segment_inf>& segment_inf) {
vtr::ScopedStartFinishTimer timer("Profiling source");
const auto& device_ctx = g_vpr_ctx.device();
const auto& grid = device_ctx.grid;
+ auto router_lookahead = make_router_lookahead(
+ router_opts.lookahead_type,
+ router_opts.write_router_lookahead,
+ router_opts.read_router_lookahead,
+ segment_inf
+ );
+ RouterDelayProfiler profiler(router_lookahead.get());
+
int start_x = 0;
int end_x = grid.width() - 1;
int start_y = 0;
@@ -162,7 +177,7 @@
vtr::ScopedStartFinishTimer delay_timer(vtr::string_fmt(
"Routing Src: %d Sink: %d", source_rr_node,
sink_rr_node));
- successfully_routed = calculate_delay(source_rr_node, sink_rr_node,
+ successfully_routed = profiler.calculate_delay(source_rr_node, sink_rr_node,
router_opts,
&delays[sink_x][sink_y]);
}
@@ -284,12 +299,15 @@
if(route_options.profile_source) {
profile_source(
route_options.source_rr_node,
- vpr_setup.RouterOpts
+ vpr_setup.RouterOpts,
+ vpr_setup.Segments
);
} else {
do_one_route(
- route_options.source_rr_node, route_options.sink_rr_node,
- vpr_setup.RouterOpts);
+ route_options.source_rr_node,
+ route_options.sink_rr_node,
+ vpr_setup.RouterOpts,
+ vpr_setup.Segments);
}
free_routing_structs();
diff --git a/vpr/main.ui b/vpr/main.ui
index cf856fe..5b9d651 100644
--- a/vpr/main.ui
+++ b/vpr/main.ui
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.16.1 -->
+<!-- Generated with glade 3.22.1 -->
<interface>
<requires lib="gtk+" version="3.0"/>
<object class="GtkWindow" id="MainWindow">
@@ -9,6 +9,9 @@
<property name="default_width">800</property>
<property name="default_height">600</property>
<child>
+ <placeholder/>
+ </child>
+ <child>
<object class="GtkGrid" id="OuterGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
@@ -22,7 +25,7 @@
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
- <property name="width">7</property>
+ <property name="width">4</property>
<property name="height">3</property>
</packing>
</child>
@@ -39,102 +42,25 @@
</object>
<packing>
<property name="left_attach">0</property>
- <property name="top_attach">0</property>
- <property name="width">2</property>
- <property name="height">1</property>
+ <property name="top_attach">1</property>
</packing>
</child>
<child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
+ <object class="GtkButton" id="ZoomFitButton">
+ <property name="label" translatable="yes">Zoom Fit</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
</child>
</object>
<packing>
- <property name="left_attach">7</property>
+ <property name="left_attach">4</property>
<property name="top_attach">1</property>
- <property name="width">1</property>
- <property name="height">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkButton" id="ZoomFitButton">
- <property name="label">gtk-zoom-fit</property>
- <property name="use_action_appearance">False</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="use_stock">True</property>
- </object>
- <packing>
- <property name="left_attach">7</property>
- <property name="top_attach">0</property>
- <property name="width">1</property>
- <property name="height">1</property>
</packing>
</child>
<child>
@@ -146,8 +72,7 @@
<packing>
<property name="left_attach">0</property>
<property name="top_attach">4</property>
- <property name="width">7</property>
- <property name="height">1</property>
+ <property name="width">4</property>
</packing>
</child>
<child>
@@ -159,8 +84,6 @@
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
- <property name="width">1</property>
- <property name="height">1</property>
</packing>
</child>
<child>
@@ -168,19 +91,17 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="tooltip_text" translatable="yes">search</property>
- <property name="halign">start</property>
<property name="primary_icon_stock">gtk-find</property>
<property name="placeholder_text" translatable="yes">Search...</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
- <property name="width">1</property>
- <property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="Search">
+ <property name="label" translatable="yes">Search</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
@@ -188,40 +109,55 @@
<packing>
<property name="left_attach">2</property>
<property name="top_attach">0</property>
- <property name="width">1</property>
- <property name="height">1</property>
</packing>
</child>
<child>
- <object class="GtkButton" id="SaveGraphics">
- <property name="label">gtk-save</property>
+ <object class="GtkGrid" id="ControlGrid">
<property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="use_stock">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkButton" id="ProceedButton">
+ <property name="label" translatable="yes">Proceed</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="image_position">right</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="SaveGraphics">
+ <property name="label" translatable="yes">Save</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="image_position">right</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="PauseButton">
+ <property name="label" translatable="yes">Pause</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="image_position">right</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
</object>
<packing>
- <property name="left_attach">7</property>
- <property name="top_attach">2</property>
- <property name="width">1</property>
- <property name="height">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkButton" id="ProceedButton">
- <property name="label">Proceed</property>
- <property name="use_action_appearance">False</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="use_stock">True</property>
- <property name="image_position">right</property>
- </object>
- <packing>
- <property name="left_attach">7</property>
+ <property name="left_attach">4</property>
<property name="top_attach">3</property>
- <property name="width">1</property>
- <property name="height">1</property>
</packing>
</child>
<child>
@@ -236,9 +172,6 @@
<child>
<placeholder/>
</child>
- <child>
- <placeholder/>
- </child>
</object>
</child>
</object>
diff --git a/vpr/src/base/SetupGrid.cpp b/vpr/src/base/SetupGrid.cpp
index f92a04a..6712196 100644
--- a/vpr/src/base/SetupGrid.cpp
+++ b/vpr/src/base/SetupGrid.cpp
@@ -11,7 +11,6 @@
#include <algorithm>
#include <regex>
#include <limits>
-using namespace std;
#include "vtr_assert.h"
#include "vtr_math.h"
diff --git a/vpr/src/base/SetupVPR.cpp b/vpr/src/base/SetupVPR.cpp
index 0615c3d..2bd4384 100644
--- a/vpr/src/base/SetupVPR.cpp
+++ b/vpr/src/base/SetupVPR.cpp
@@ -1,7 +1,6 @@
#include <cstring>
#include <vector>
#include <sstream>
-using namespace std;
#include "vtr_assert.h"
#include "vtr_util.h"
@@ -60,7 +59,7 @@
t_router_opts* RouterOpts,
t_analysis_opts* AnalysisOpts,
t_det_routing_arch* RoutingArch,
- vector<t_lb_type_rr_node>** PackerRRGraphs,
+ std::vector<t_lb_type_rr_node>** PackerRRGraphs,
std::vector<t_segment_inf>& Segments,
t_timing_inf* Timing,
bool* ShowGraphics,
@@ -352,6 +351,9 @@
RouterOpts->first_iteration_timing_report_file = Options.router_first_iteration_timing_report_file;
RouterOpts->strict_checks = Options.strict_checks;
+
+ RouterOpts->write_router_lookahead = Options.write_router_lookahead;
+ RouterOpts->read_router_lookahead = Options.read_router_lookahead;
}
static void SetupAnnealSched(const t_options& Options,
@@ -481,6 +483,11 @@
PlacerOpts->move_stats_file = Options.place_move_stats_file;
PlacerOpts->strict_checks = Options.strict_checks;
+
+ PlacerOpts->write_placement_delay_lookup = Options.write_placement_delay_lookup;
+ PlacerOpts->read_placement_delay_lookup = Options.read_placement_delay_lookup;
+
+ PlacerOpts->allowed_tiles_for_delay_model = Options.allowed_tiles_for_delay_model;
}
static void SetupAnalysisOpts(const t_options& Options, t_analysis_opts& analysis_opts) {
diff --git a/vpr/src/base/check_netlist.cpp b/vpr/src/base/check_netlist.cpp
index 2f5bbd8..63fa3cd 100644
--- a/vpr/src/base/check_netlist.cpp
+++ b/vpr/src/base/check_netlist.cpp
@@ -4,7 +4,6 @@
#include <cstdio>
#include <cstring>
-using namespace std;
#include "vtr_assert.h"
#include "vtr_log.h"
diff --git a/vpr/src/base/echo_files.cpp b/vpr/src/base/echo_files.cpp
index f514849..6f8de45 100644
--- a/vpr/src/base/echo_files.cpp
+++ b/vpr/src/base/echo_files.cpp
@@ -1,6 +1,5 @@
#include <cstdio>
#include <cstring>
-using namespace std;
#include "vtr_util.h"
#include "vtr_memory.h"
diff --git a/vpr/src/base/place_and_route.cpp b/vpr/src/base/place_and_route.cpp
index 1db5ed5..d016375 100644
--- a/vpr/src/base/place_and_route.cpp
+++ b/vpr/src/base/place_and_route.cpp
@@ -5,7 +5,6 @@
#include <climits>
#include <cstdlib>
#include <cmath>
-using namespace std;
#include "vtr_util.h"
#include "vtr_memory.h"
@@ -351,7 +350,6 @@
router_opts.trim_empty_channels,
router_opts.trim_obs_channels,
router_opts.clock_modeling,
- router_opts.lookahead_type,
arch->Directs, arch->num_directs,
&warnings);
@@ -394,7 +392,7 @@
for (size_t i = 0; i < grid.height(); ++i) {
float y = float(i) / num_channels;
chan_width.x_list[i] = (int)floor(cfactor * comp_width(&chan_x_dist, y, separation) + 0.5);
- chan_width.x_list[i] = max(chan_width.x_list[i], 1); //Minimum channel width 1
+ chan_width.x_list[i] = std::max(chan_width.x_list[i], 1); //Minimum channel width 1
}
}
@@ -407,7 +405,7 @@
float x = float(i) / num_channels;
chan_width.y_list[i] = (int)floor(cfactor * comp_width(&chan_y_dist, x, separation) + 0.5);
- chan_width.y_list[i] = max(chan_width.y_list[i], 1); //Minimum channel width 1
+ chan_width.y_list[i] = std::max(chan_width.y_list[i], 1); //Minimum channel width 1
}
}
@@ -415,14 +413,14 @@
chan_width.x_max = chan_width.y_max = INT_MIN;
chan_width.x_min = chan_width.y_min = INT_MAX;
for (size_t i = 0; i < grid.height(); ++i) {
- chan_width.max = max(chan_width.max, chan_width.x_list[i]);
- chan_width.x_max = max(chan_width.x_max, chan_width.x_list[i]);
- chan_width.x_min = min(chan_width.x_min, chan_width.x_list[i]);
+ chan_width.max = std::max(chan_width.max, chan_width.x_list[i]);
+ chan_width.x_max = std::max(chan_width.x_max, chan_width.x_list[i]);
+ chan_width.x_min = std::min(chan_width.x_min, chan_width.x_list[i]);
}
for (size_t i = 0; i < grid.width(); ++i) {
- chan_width.max = max(chan_width.max, chan_width.y_list[i]);
- chan_width.y_max = max(chan_width.y_max, chan_width.y_list[i]);
- chan_width.y_min = min(chan_width.y_min, chan_width.y_list[i]);
+ chan_width.max = std::max(chan_width.max, chan_width.y_list[i]);
+ chan_width.y_max = std::max(chan_width.y_max, chan_width.y_list[i]);
+ chan_width.y_min = std::min(chan_width.y_min, chan_width.y_list[i]);
}
#ifdef VERBOSE
diff --git a/vpr/src/base/read_blif.cpp b/vpr/src/base/read_blif.cpp
index 9feb09c..9667945 100644
--- a/vpr/src/base/read_blif.cpp
+++ b/vpr/src/base/read_blif.cpp
@@ -21,7 +21,6 @@
#include <sstream>
#include <unordered_set>
#include <cctype> //std::isdigit
-using namespace std;
#include "blifparse.hpp"
#include "atom_netlist.h"
diff --git a/vpr/src/base/read_netlist.cpp b/vpr/src/base/read_netlist.cpp
index 3e00928..cfbb78c 100644
--- a/vpr/src/base/read_netlist.cpp
+++ b/vpr/src/base/read_netlist.cpp
@@ -9,7 +9,6 @@
#include <cstring>
#include <ctime>
#include <map>
-using namespace std;
#include "pugixml.hpp"
#include "pugixml_loc.hpp"
diff --git a/vpr/src/base/read_options.cpp b/vpr/src/base/read_options.cpp
index 8b66a4d..6166ab1 100644
--- a/vpr/src/base/read_options.cpp
+++ b/vpr/src/base/read_options.cpp
@@ -1010,6 +1010,24 @@
.metavar("RR_GRAPH_FILE")
.show_in(argparse::ShowIn::HELP_ONLY);
+ file_grp.add_argument(args.read_router_lookahead, "--read_router_lookahead")
+ .help(
+ "Reads the lookahead data from the specified file instead of computing it.")
+ .show_in(argparse::ShowIn::HELP_ONLY);
+
+ file_grp.add_argument(args.write_router_lookahead, "--write_router_lookahead")
+ .help("Writes the lookahead data to the specified file.")
+ .show_in(argparse::ShowIn::HELP_ONLY);
+
+ file_grp.add_argument(args.read_placement_delay_lookup, "--read_placement_delay_lookup")
+ .help(
+ "Reads the placement delay lookup from the specified file instead of computing it.")
+ .show_in(argparse::ShowIn::HELP_ONLY);
+
+ file_grp.add_argument(args.write_placement_delay_lookup, "--write_placement_delay_lookup")
+ .help("Writes the placement delay lookup to the specified file.")
+ .show_in(argparse::ShowIn::HELP_ONLY);
+
file_grp.add_argument(args.out_file_prefix, "--outfile_prefix")
.help("Prefix for output files")
.show_in(argparse::ShowIn::HELP_ONLY);
@@ -1366,6 +1384,14 @@
.default_value("")
.show_in(argparse::ShowIn::HELP_ONLY);
+ place_timing_grp.add_argument(args.allowed_tiles_for_delay_model, "--allowed_tiles_for_delay_model")
+ .help(
+ "Names of allowed tile types that can be sampled during delay "
+ "modelling. Default is to allow all tiles. Can be used to "
+ "exclude specialized tiles from placer delay sampling.")
+ .default_value("")
+ .show_in(argparse::ShowIn::HELP_ONLY);
+
auto& route_grp = parser.add_argument_group("routing options");
route_grp.add_argument(args.max_router_iterations, "--max_router_iterations")
diff --git a/vpr/src/base/read_options.h b/vpr/src/base/read_options.h
index 666bfbe..d1f45e5 100644
--- a/vpr/src/base/read_options.h
+++ b/vpr/src/base/read_options.h
@@ -27,6 +27,12 @@
argparse::ArgValue<std::string> write_rr_graph_file;
argparse::ArgValue<std::string> read_rr_graph_file;
+ argparse::ArgValue<std::string> write_placement_delay_lookup;
+ argparse::ArgValue<std::string> read_placement_delay_lookup;
+
+ argparse::ArgValue<std::string> write_router_lookahead;
+ argparse::ArgValue<std::string> read_router_lookahead;
+
/* Stage Options */
argparse::ArgValue<bool> do_packing;
argparse::ArgValue<bool> do_placement;
@@ -109,6 +115,7 @@
argparse::ArgValue<std::string> post_place_timing_report_file;
argparse::ArgValue<PlaceDelayModelType> place_delay_model;
argparse::ArgValue<e_reducer> place_delay_model_reducer;
+ argparse::ArgValue<std::string> allowed_tiles_for_delay_model;
/* Router Options */
argparse::ArgValue<int> max_router_iterations;
diff --git a/vpr/src/base/read_route.cpp b/vpr/src/base/read_route.cpp
index 2957d2e..6bdfeb2 100644
--- a/vpr/src/base/read_route.cpp
+++ b/vpr/src/base/read_route.cpp
@@ -17,7 +17,6 @@
#include <sstream>
#include <string>
#include <unordered_set>
-using namespace std;
#include "atom_netlist.h"
#include "atom_netlist_utils.h"
@@ -43,13 +42,13 @@
#include "read_route.h"
/*************Functions local to this module*************/
-static void process_route(ifstream& fp, const char* filename, int& lineno);
-static void process_nodes(ifstream& fp, ClusterNetId inet, const char* filename, int& lineno);
-static void process_nets(ifstream& fp, ClusterNetId inet, string name, std::vector<std::string> input_tokens, const char* filename, int& lineno);
-static void process_global_blocks(ifstream& fp, ClusterNetId inet, const char* filename, int& lineno);
-static void format_coordinates(int& x, int& y, string coord, ClusterNetId net, const char* filename, const int lineno);
-static void format_pin_info(string& pb_name, string& port_name, int& pb_pin_num, string input);
-static string format_name(string name);
+static void process_route(std::ifstream& fp, const char* filename, int& lineno);
+static void process_nodes(std::ifstream& fp, ClusterNetId inet, const char* filename, int& lineno);
+static void process_nets(std::ifstream& fp, ClusterNetId inet, std::string name, std::vector<std::string> input_tokens, const char* filename, int& lineno);
+static void process_global_blocks(std::ifstream& fp, ClusterNetId inet, const char* filename, int& lineno);
+static void format_coordinates(int& x, int& y, std::string coord, ClusterNetId net, const char* filename, const int lineno);
+static void format_pin_info(std::string& pb_name, std::string& port_name, int& pb_pin_num, std::string input);
+static std::string format_name(std::string name);
/*************Global Functions****************************/
bool read_route(const char* route_file, const t_router_opts& router_opts, bool verify_file_digests) {
@@ -61,9 +60,9 @@
/* Begin parsing the file */
VTR_LOG("Begin loading FPGA routing file.\n");
- string header_str;
+ std::string header_str;
- ifstream fp;
+ std::ifstream fp;
fp.open(route_file);
int lineno = 0;
@@ -73,7 +72,7 @@
"Cannot open %s routing file", route_file);
}
- getline(fp, header_str);
+ std::getline(fp, header_str);
++lineno;
std::vector<std::string> header = vtr::split(header_str);
@@ -94,7 +93,7 @@
init_route_structs(router_opts.bb_factor);
/*Check dimensions*/
- getline(fp, header_str);
+ std::getline(fp, header_str);
++lineno;
header.clear();
header = vtr::split(header_str);
@@ -127,11 +126,11 @@
return is_feasible;
}
-static void process_route(ifstream& fp, const char* filename, int& lineno) {
+static void process_route(std::ifstream& fp, const char* filename, int& lineno) {
/*Walks through every net and add the routing appropriately*/
- string input;
+ std::string input;
std::vector<std::string> tokens;
- while (getline(fp, input)) {
+ while (std::getline(fp, input)) {
++lineno;
tokens.clear();
tokens = vtr::split(input);
@@ -148,7 +147,7 @@
tokens.clear();
}
-static void process_nets(ifstream& fp, ClusterNetId inet, string name, std::vector<std::string> input_tokens, const char* filename, int& lineno) {
+static void process_nets(std::ifstream& fp, ClusterNetId inet, std::string name, std::vector<std::string> input_tokens, const char* filename, int& lineno) {
/* Check if the net is global or not, and process appropriately */
auto& cluster_ctx = g_vpr_ctx.mutable_clustering();
@@ -190,7 +189,7 @@
return;
}
-static void process_nodes(ifstream& fp, ClusterNetId inet, const char* filename, int& lineno) {
+static void process_nodes(std::ifstream& fp, ClusterNetId inet, const char* filename, int& lineno) {
/* Not a global net. Goes through every node and add it into trace.head*/
auto& cluster_ctx = g_vpr_ctx.mutable_clustering();
@@ -201,14 +200,14 @@
t_trace* tptr = route_ctx.trace[inet].head;
/*remember the position of the last line in order to go back*/
- streampos oldpos = fp.tellg();
+ std::streampos oldpos = fp.tellg();
int inode, x, y, x2, y2, ptc, switch_id, offset;
int node_count = 0;
- string input;
+ std::string input;
std::vector<std::string> tokens;
/*Walk through every line that begins with Node:*/
- while (getline(fp, input)) {
+ while (std::getline(fp, input)) {
++lineno;
tokens.clear();
@@ -292,7 +291,7 @@
t_pb_graph_pin* pb_pin = get_pb_graph_node_pin_from_block_pin(iblock, pin_num);
t_pb_type* pb_type = pb_pin->parent_node->pb_type;
- string pb_name, port_name;
+ std::string pb_name, port_name;
int pb_pin_num;
format_pin_info(pb_name, port_name, pb_pin_num, tokens[6 + offset]);
@@ -334,18 +333,18 @@
/*This function goes through all the blocks in a global net and verify it with the
* clustered netlist and the placement */
-static void process_global_blocks(ifstream& fp, ClusterNetId inet, const char* filename, int& lineno) {
+static void process_global_blocks(std::ifstream& fp, ClusterNetId inet, const char* filename, int& lineno) {
auto& cluster_ctx = g_vpr_ctx.mutable_clustering();
auto& place_ctx = g_vpr_ctx.placement();
- string block, bnum_str;
+ std::string block, bnum_str;
int x, y;
std::vector<std::string> tokens;
int pin_counter = 0;
- streampos oldpos = fp.tellg();
+ std::streampos oldpos = fp.tellg();
/*Walk through every block line*/
- while (getline(fp, block)) {
+ while (std::getline(fp, block)) {
++lineno;
tokens.clear();
tokens = vtr::split(block);
@@ -391,10 +390,10 @@
}
}
-static void format_coordinates(int& x, int& y, string coord, ClusterNetId net, const char* filename, const int lineno) {
+static void format_coordinates(int& x, int& y, std::string coord, ClusterNetId net, const char* filename, const int lineno) {
/*Parse coordinates in the form of (x,y) into correct x and y values*/
coord = format_name(coord);
- stringstream coord_stream(coord);
+ std::stringstream coord_stream(coord);
if (!(coord_stream >> x)) {
vpr_throw(VPR_ERROR_ROUTE, filename, lineno,
"Net %lu has coordinates that is not in the form (x,y)", size_t(net));
@@ -406,12 +405,12 @@
}
}
-static void format_pin_info(string& pb_name, string& port_name, int& pb_pin_num, string input) {
+static void format_pin_info(std::string& pb_name, std::string& port_name, int& pb_pin_num, std::string input) {
/*Parse the pin info in the form of pb_name.port_name[pb_pin_num]
*into its appropriate variables*/
- stringstream pb_info(input);
- getline(pb_info, pb_name, '.');
- getline(pb_info, port_name, '[');
+ std::stringstream pb_info(input);
+ std::getline(pb_info, pb_name, '.');
+ std::getline(pb_info, port_name, '[');
pb_info >> pb_pin_num;
if (!pb_info) {
VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
@@ -421,7 +420,7 @@
}
/*Return actual name by extracting it out of the form of (name)*/
-static string format_name(string name) {
+static std::string format_name(std::string name) {
if (name.length() > 2) {
name.erase(name.begin());
name.erase(name.end() - 1);
diff --git a/vpr/src/base/stats.cpp b/vpr/src/base/stats.cpp
index 43b8bdd..28eb70c 100644
--- a/vpr/src/base/stats.cpp
+++ b/vpr/src/base/stats.cpp
@@ -2,7 +2,6 @@
#include <cstring>
#include <cmath>
#include <set>
-using namespace std;
#include "vtr_assert.h"
#include "vtr_log.h"
@@ -122,13 +121,13 @@
get_num_bends_and_length(net_id, &bends, &length, &segments);
total_bends += bends;
- max_bends = max(bends, max_bends);
+ max_bends = std::max(bends, max_bends);
total_length += length;
- max_length = max(length, max_length);
+ max_length = std::max(length, max_length);
total_segments += segments;
- max_segments = max(segments, max_segments);
+ max_segments = std::max(segments, max_segments);
} else if (cluster_ctx.clb_nlist.net_is_ignored(net_id)) {
num_global_nets++;
} else {
@@ -184,7 +183,7 @@
int max_occ = -1;
for (size_t i = 1; i < device_ctx.grid.width(); ++i) {
- max_occ = max(chanx_occ[i][j], max_occ);
+ max_occ = std::max(chanx_occ[i][j], max_occ);
ave_occ += chanx_occ[i][j];
}
ave_occ /= device_ctx.grid.width();
@@ -201,7 +200,7 @@
int max_occ = -1;
for (size_t j = 1; j < device_ctx.grid.height(); ++j) {
- max_occ = max(chany_occ[i][j], max_occ);
+ max_occ = std::max(chany_occ[i][j], max_occ);
ave_occ += chany_occ[i][j];
}
ave_occ /= device_ctx.grid.height();
diff --git a/vpr/src/base/vpr_api.cpp b/vpr/src/base/vpr_api.cpp
index fa1b361..348545f 100644
--- a/vpr/src/base/vpr_api.cpp
+++ b/vpr/src/base/vpr_api.cpp
@@ -13,7 +13,6 @@
#include <chrono>
#include <cmath>
#include <sstream>
-using namespace std;
#include "vtr_assert.h"
#include "vtr_math.h"
@@ -718,6 +717,16 @@
std::shared_ptr<SetupHoldTimingInfo> timing_info,
std::shared_ptr<RoutingDelayCalculator> delay_calc,
vtr::vector<ClusterNetId, float*>& net_delay) {
+ if (router_needs_lookahead(vpr_setup.RouterOpts.router_algorithm)) {
+ // Prime lookahead cache to avoid adding lookahead computation cost to
+ // the routing timer.
+ get_cached_router_lookahead(
+ vpr_setup.RouterOpts.lookahead_type,
+ vpr_setup.RouterOpts.write_router_lookahead,
+ vpr_setup.RouterOpts.read_router_lookahead,
+ vpr_setup.Segments);
+ }
+
vtr::ScopedStartFinishTimer timer("Routing");
if (NO_FIXED_CHANNEL_WIDTH == fixed_channel_width || fixed_channel_width <= 0) {
@@ -744,6 +753,9 @@
std::shared_ptr<SetupHoldTimingInfo> timing_info,
std::shared_ptr<RoutingDelayCalculator> delay_calc,
vtr::vector<ClusterNetId, float*>& net_delay) {
+ // Note that lookahead cache is not primed here because
+ // binary_search_place_and_route will change the channel width, and result
+ // in the lookahead cache being recomputed.
vtr::ScopedStartFinishTimer timer("Routing");
auto& router_opts = vpr_setup.RouterOpts;
@@ -822,7 +834,6 @@
router_opts.trim_empty_channels,
router_opts.trim_obs_channels,
router_opts.clock_modeling,
- router_opts.lookahead_type,
arch.Directs, arch.num_directs,
&warnings);
//Initialize drawing, now that we have an RR graph
@@ -1043,7 +1054,7 @@
t_router_opts* RouterOpts,
t_analysis_opts* AnalysisOpts,
t_det_routing_arch* RoutingArch,
- vector<t_lb_type_rr_node>** PackerRRGraph,
+ std::vector<t_lb_type_rr_node>** PackerRRGraph,
std::vector<t_segment_inf>& Segments,
t_timing_inf* Timing,
bool* ShowGraphics,
@@ -1178,9 +1189,9 @@
}
/* This function performs power estimation. It relies on the
- * placement/routing results, as well as the critical path.
+ * placement/routing results, as well as the critical path.
* Power estimation can be performed as part of a full or
- * partial flow. More information on the power estimation functions of
+ * partial flow. More information on the power estimation functions of
* VPR can be found here:
* http://docs.verilogtorouting.org/en/latest/vtr/power_estimation/
*/
diff --git a/vpr/src/base/vpr_context.h b/vpr/src/base/vpr_context.h
index 50fd7d9..8f61be4 100644
--- a/vpr/src/base/vpr_context.h
+++ b/vpr/src/base/vpr_context.h
@@ -3,7 +3,6 @@
#include <unordered_map>
#include <memory>
#include <vector>
-#include <csignal> //for sig_atomic_t
#include "vpr_types.h"
#include "vtr_ndmatrix.h"
@@ -19,7 +18,9 @@
#include "clock_network_builders.h"
#include "clock_connection_builders.h"
#include "route_traceback.h"
+#include "router_lookahead.h"
#include "place_macro.h"
+#include "compressed_grid.h"
//A Context is collection of state relating to a particular part of VPR
//
@@ -246,6 +247,11 @@
// The pl_macros array stores all the placement macros (usually carry chains).
std::vector<t_pl_macro> pl_macros;
+ //Compressed grid space for each block type
+ //Used to efficiently find logically 'adjacent' blocks of the same block type even though
+ //the may be physically far apart
+ t_compressed_block_grids compressed_block_grids;
+
//SHA256 digest of the .place file (used for unique identification and consistency checking)
std::string placement_id;
};
@@ -275,6 +281,13 @@
//SHA256 digest of the .route file (used for unique identification and consistency checking)
std::string routing_id;
+
+ // Cache of router lookahead object.
+ //
+ // Cache key: (lookahead type, read lookahead (if any), segment definitions).
+ vtr::Cache<std::tuple<e_router_lookahead, std::string, std::vector<t_segment_inf>>,
+ RouterLookahead>
+ cached_router_lookahead_;
};
//This object encapsulates VPR's state. There is typically a single instance which is
@@ -338,10 +351,6 @@
const RoutingContext& routing() const { return routing_; }
RoutingContext& mutable_routing() { return routing_; }
- //Should the program pause at the next convenient time?
- bool forced_pause() const { return force_pause_; }
- void set_forced_pause(bool val) { force_pause_ = val; }
-
private:
DeviceContext device_;
@@ -353,10 +362,6 @@
ClusteringContext clustering_;
PlacementContext placement_;
RoutingContext routing_;
-
- //We use a volatile sig_atomic_t to ensures signals
- //set the value atomicly
- volatile sig_atomic_t force_pause_ = false;
};
#endif
diff --git a/vpr/src/base/vpr_signal_handler.cpp b/vpr/src/base/vpr_signal_handler.cpp
index 297fd28..edcad9e 100644
--- a/vpr/src/base/vpr_signal_handler.cpp
+++ b/vpr/src/base/vpr_signal_handler.cpp
@@ -50,9 +50,7 @@
}
if (uncleared_sigint_count == 1) {
- //Request a pause at the next reasonable point (e.g. to resume the GUI)
- VTR_LOG("Recieved SIGINT: Attempting to pause...\n");
- g_vpr_ctx.set_forced_pause(true);
+ VTR_LOG("Recieved SIGINT: try again to really exit...\n");
} else if (uncleared_sigint_count == 2) {
VTR_LOG("Recieved two uncleared SIGINTs: Attempting to checkpoint and exit...\n");
checkpoint();
diff --git a/vpr/src/base/vpr_types.h b/vpr/src/base/vpr_types.h
index c837f3f..1eb4ffb 100644
--- a/vpr/src/base/vpr_types.h
+++ b/vpr/src/base/vpr_types.h
@@ -38,6 +38,7 @@
#include "vtr_vector.h"
#include "vtr_util.h"
#include "vtr_flat_map.h"
+#include "vtr_cache.h"
/*******************************************************************************
* Global data types and constants
@@ -620,33 +621,6 @@
float cost;
};
-/* Stores the information of the move for a block that is *
- * moved during placement *
- * block_num: the index of the moved block *
- * xold: the x_coord that the block is moved from *
- * xnew: the x_coord that the block is moved to *
- * yold: the y_coord that the block is moved from *
- * xnew: the x_coord that the block is moved to */
-struct t_pl_moved_block {
- ClusterBlockId block_num;
- t_pl_loc old_loc;
- t_pl_loc new_loc;
-};
-
-/* Stores the list of blocks to be moved in a swap during *
- * placement. *
- * num_moved_blocks: total number of blocks moved when *
- * swapping two blocks. *
- * moved blocks: a list of moved blocks data structure with *
- * information on the move. *
- * [0...num_moved_blocks-1] */
-struct t_pl_blocks_to_be_moved {
- int num_moved_blocks;
- std::vector<t_pl_moved_block> moved_blocks;
- std::unordered_set<t_pl_loc> moved_from;
- std::unordered_set<t_pl_loc> moved_to;
-};
-
/* Represents the placement location of a clustered block
* x: x-coordinate
* y: y-coordinate
@@ -831,6 +805,15 @@
std::string post_place_timing_report_file;
bool strict_checks;
+
+ std::string write_placement_delay_lookup;
+ std::string read_placement_delay_lookup;
+
+ // Tile types that should be used during delay sampling.
+ //
+ // Useful for excluding tiles that have abnormal delay behavior, e.g.
+ // clock tree elements like PLL's, global/local clock buffers, etc.
+ std::string allowed_tiles_for_delay_model;
};
/* All the parameters controlling the router's operation are in this *
@@ -962,6 +945,9 @@
float reconvergence_cpd_threshold;
std::string first_iteration_timing_report_file;
bool strict_checks;
+
+ std::string write_router_lookahead;
+ std::string read_router_lookahead;
};
struct t_analysis_opts {
diff --git a/vpr/src/draw/buttons.cpp b/vpr/src/draw/buttons.cpp
index 7822bae..21a2781 100644
--- a/vpr/src/draw/buttons.cpp
+++ b/vpr/src/draw/buttons.cpp
@@ -18,7 +18,6 @@
# include "ezgl/point.hpp"
# include "ezgl/application.hpp"
# include "ezgl/graphics.hpp"
-using namespace std;
//location of spin buttons, combo boxes, and labels on grid
gint box_width = 1;
@@ -370,4 +369,4 @@
return target_button;
}
-#endif /* NO_GRAPHICS */
\ No newline at end of file
+#endif /* NO_GRAPHICS */
diff --git a/vpr/src/draw/draw.cpp b/vpr/src/draw/draw.cpp
index 8ff93ab..1e09950 100644
--- a/vpr/src/draw/draw.cpp
+++ b/vpr/src/draw/draw.cpp
@@ -5,7 +5,7 @@
* whenever the screen needs to be updated. Then, draw_main_canvas() will decide what
* drawing subroutines to call depending on whether PLACEMENT or ROUTING is shown on screen.
* The initial_setup_X() functions link the menu button signals to the corresponding drawing functions.
- * As a note, looks into draw_global.c for understanding the data structures associated with drawing.
+ * As a note, looks into draw_global.c for understanding the data structures associated with drawing->
*
*
* Authors: Vaughn Betz, Long Yu (Mike) Wang, Dingyu (Tina) Yang
@@ -19,7 +19,6 @@
#include <algorithm>
#include <sstream>
#include <array>
-using namespace std;
#include "vtr_assert.h"
#include "vtr_ndoffsetmatrix.h"
@@ -74,34 +73,34 @@
//#define TIME_DRAWSCREEN /* Enable if want to track runtime for drawscreen() */
/********************** Subroutines local to this module ********************/
-static void drawplace(ezgl::renderer& g);
-static void drawnets(ezgl::renderer& g);
-static void drawroute(enum e_draw_net_type draw_net_type, ezgl::renderer& g);
-static void draw_congestion(ezgl::renderer& g);
-static void draw_routing_costs(ezgl::renderer& g);
-static void draw_routing_bb(ezgl::renderer& g);
-static void draw_routing_util(ezgl::renderer& g);
-static void draw_crit_path(ezgl::renderer& g);
-static void draw_placement_macros(ezgl::renderer& g);
+static void drawplace(ezgl::renderer* g);
+static void drawnets(ezgl::renderer* g);
+static void drawroute(enum e_draw_net_type draw_net_type, ezgl::renderer* g);
+static void draw_congestion(ezgl::renderer* g);
+static void draw_routing_costs(ezgl::renderer* g);
+static void draw_routing_bb(ezgl::renderer* g);
+static void draw_routing_util(ezgl::renderer* g);
+static void draw_crit_path(ezgl::renderer* g);
+static void draw_placement_macros(ezgl::renderer* g);
void act_on_key_press(ezgl::application* /*app*/, GdkEventKey* /*event*/, char* key_name);
void act_on_mouse_press(ezgl::application* app, GdkEventButton* event, double x, double y);
void act_on_mouse_move(ezgl::application* app, GdkEventButton* event, double x, double y);
-static void draw_routed_net(ClusterNetId net, ezgl::renderer& g);
-void draw_partial_route(const std::vector<int>& rr_nodes_to_draw, ezgl::renderer& g);
-static void draw_rr(ezgl::renderer& g);
-static void draw_rr_edges(int from_node, ezgl::renderer& g);
-static void draw_rr_pin(int inode, const ezgl::color& color, ezgl::renderer& g);
-static void draw_rr_chan(int inode, const ezgl::color color, ezgl::renderer& g);
-static void draw_rr_src_sink(int inode, ezgl::color color, ezgl::renderer& g);
-static void draw_pin_to_chan_edge(int pin_node, int chan_node, ezgl::renderer& g);
-static void draw_x(float x, float y, float size, ezgl::renderer& g);
-static void draw_pin_to_pin(int opin, int ipin, ezgl::renderer& g);
-static void draw_rr_switch(float from_x, float from_y, float to_x, float to_y, bool buffered, bool switch_configurable, ezgl::renderer& g);
-static void draw_chany_to_chany_edge(int from_node, int to_node, int to_track, short switch_type, ezgl::renderer& g);
-static void draw_chanx_to_chanx_edge(int from_node, int to_node, int to_track, short switch_type, ezgl::renderer& g);
-static void draw_chanx_to_chany_edge(int chanx_node, int chanx_track, int chany_node, int chany_track, enum e_edge_dir edge_dir, short switch_type, ezgl::renderer& g);
+static void draw_routed_net(ClusterNetId net, ezgl::renderer* g);
+void draw_partial_route(const std::vector<int>& rr_nodes_to_draw, ezgl::renderer* g);
+static void draw_rr(ezgl::renderer* g);
+static void draw_rr_edges(int from_node, ezgl::renderer* g);
+static void draw_rr_pin(int inode, const ezgl::color& color, ezgl::renderer* g);
+static void draw_rr_chan(int inode, const ezgl::color color, ezgl::renderer* g);
+static void draw_rr_src_sink(int inode, ezgl::color color, ezgl::renderer* g);
+static void draw_pin_to_chan_edge(int pin_node, int chan_node, ezgl::renderer* g);
+static void draw_x(float x, float y, float size, ezgl::renderer* g);
+static void draw_pin_to_pin(int opin, int ipin, ezgl::renderer* g);
+static void draw_rr_switch(float from_x, float from_y, float to_x, float to_y, bool buffered, bool switch_configurable, ezgl::renderer* g);
+static void draw_chany_to_chany_edge(int from_node, int to_node, int to_track, short switch_type, ezgl::renderer* g);
+static void draw_chanx_to_chanx_edge(int from_node, int to_node, int to_track, short switch_type, ezgl::renderer* g);
+static void draw_chanx_to_chany_edge(int chanx_node, int chanx_track, int chany_node, int chany_track, enum e_edge_dir edge_dir, short switch_type, ezgl::renderer* g);
static int get_track_num(int inode, const vtr::OffsetMatrix<int>& chanx_track, const vtr::OffsetMatrix<int>& chany_track);
static bool draw_if_net_highlighted(ClusterNetId inet);
static int draw_check_rr_node_hit(float click_x, float click_y);
@@ -112,18 +111,18 @@
static void draw_reset_blk_colors();
static void draw_reset_blk_color(ClusterBlockId blk_id);
-static inline void draw_mux_with_size(ezgl::point2d origin, e_side orientation, float height, int size, ezgl::renderer& g);
-static inline ezgl::rectangle draw_mux(ezgl::point2d origin, e_side orientation, float height, ezgl::renderer& g);
-static inline ezgl::rectangle draw_mux(ezgl::point2d origin, e_side orientation, float height, float width, float height_scale, ezgl::renderer& g);
+static inline void draw_mux_with_size(ezgl::point2d origin, e_side orientation, float height, int size, ezgl::renderer* g);
+static inline ezgl::rectangle draw_mux(ezgl::point2d origin, e_side orientation, float height, ezgl::renderer* g);
+static inline ezgl::rectangle draw_mux(ezgl::point2d origin, e_side orientation, float height, float width, float height_scale, ezgl::renderer* g);
-static void draw_flyline_timing_edge(ezgl::point2d start, ezgl::point2d end, float incr_delay, ezgl::renderer& g);
-static void draw_routed_timing_edge(tatum::NodeId start_tnode, tatum::NodeId end_tnode, float incr_delay, ezgl::color color, ezgl::renderer& g);
-static void draw_routed_timing_edge_connection(tatum::NodeId src_tnode, tatum::NodeId sink_tnode, ezgl::color color, ezgl::renderer& g);
+static void draw_flyline_timing_edge(ezgl::point2d start, ezgl::point2d end, float incr_delay, ezgl::renderer* g);
+static void draw_routed_timing_edge(tatum::NodeId start_tnode, tatum::NodeId end_tnode, float incr_delay, ezgl::color color, ezgl::renderer* g);
+static void draw_routed_timing_edge_connection(tatum::NodeId src_tnode, tatum::NodeId sink_tnode, ezgl::color color, ezgl::renderer* g);
static std::vector<int> trace_routed_connection_rr_nodes(const ClusterNetId net_id, const int driver_pin, const int sink_pin);
static bool trace_routed_connection_rr_nodes_recurr(const t_rt_node* rt_node, int sink_rr_node, std::vector<int>& rr_nodes_on_path);
static t_edge_size find_edge(int prev_inode, int inode);
-static void draw_color_map_legend(const vtr::ColorMap& cmap, ezgl::renderer& g);
+static void draw_color_map_legend(const vtr::ColorMap& cmap, ezgl::renderer* g);
ezgl::color get_block_type_color(t_physical_tile_type_ptr type);
ezgl::color lighten_color(ezgl::color color, float amount);
@@ -131,19 +130,20 @@
static void draw_block_pin_util();
static float get_router_rr_cost(const t_rr_node_route_inf node_inf, e_draw_router_rr_cost draw_router_rr_cost);
-static void draw_router_rr_costs(ezgl::renderer& g);
+static void draw_router_rr_costs(ezgl::renderer* g);
-static void draw_rr_costs(ezgl::renderer& g, const std::vector<float>& rr_costs, bool lowest_cost_first = true);
+static void draw_rr_costs(ezgl::renderer* g, const std::vector<float>& rr_costs, bool lowest_cost_first = true);
-void draw_main_canvas(ezgl::renderer& g);
-void initial_setup_NO_PICTURE_to_PLACEMENT(ezgl::application* app);
-void initial_setup_NO_PICTURE_to_PLACEMENT_with_crit_path(ezgl::application* app);
-void initial_setup_PLACEMENT_to_ROUTING(ezgl::application* app);
-void initial_setup_ROUTING_to_PLACEMENT(ezgl::application* app);
-void initial_setup_NO_PICTURE_to_ROUTING(ezgl::application* app);
-void initial_setup_NO_PICTURE_to_ROUTING_with_crit_path(ezgl::application* app);
+void draw_main_canvas(ezgl::renderer* g);
+void initial_setup_NO_PICTURE_to_PLACEMENT(ezgl::application* app, bool is_new_window);
+void initial_setup_NO_PICTURE_to_PLACEMENT_with_crit_path(ezgl::application* app, bool is_new_window);
+void initial_setup_PLACEMENT_to_ROUTING(ezgl::application* app, bool is_new_window);
+void initial_setup_ROUTING_to_PLACEMENT(ezgl::application* app, bool is_new_window);
+void initial_setup_NO_PICTURE_to_ROUTING(ezgl::application* app, bool is_new_window);
+void initial_setup_NO_PICTURE_to_ROUTING_with_crit_path(ezgl::application* app, bool is_new_window);
void toggle_window_mode(GtkWidget* /*widget*/, ezgl::application* /*app*/);
void setup_default_ezgl_callbacks(ezgl::application* app);
+void set_force_pause(GtkWidget* /*widget*/, gint /*response_id*/, gpointer /*data*/);
/************************** File Scope Variables ****************************/
@@ -221,10 +221,10 @@
}
#ifndef NO_GRAPHICS
-void draw_main_canvas(ezgl::renderer& g) {
+void draw_main_canvas(ezgl::renderer* g) {
t_draw_state* draw_state = get_draw_state_vars();
- g.set_font_size(14);
+ g->set_font_size(14);
draw_block_pin_util();
drawplace(g);
@@ -279,7 +279,9 @@
/* function below intializes the interface window with a set of buttons and links
* signals to corresponding functions for situation where the window is opened from
* NO_PICTURE_to_PLACEMENT */
-void initial_setup_NO_PICTURE_to_PLACEMENT(ezgl::application* app) {
+void initial_setup_NO_PICTURE_to_PLACEMENT(ezgl::application* app, bool is_new_window) {
+ if (!is_new_window) return;
+
//button to enter window_mode, created in main.ui
GtkButton* window = (GtkButton*)app->get_object("Window");
gtk_button_set_label(window, "Window");
@@ -312,16 +314,16 @@
/* function below intializes the interface window with a set of buttons and links
* signals to corresponding functions for situation where the window is opened from
* NO_PICTURE_to_PLACEMENT_with_crit_path */
-void initial_setup_NO_PICTURE_to_PLACEMENT_with_crit_path(ezgl::application* app) {
- initial_setup_NO_PICTURE_to_PLACEMENT(app);
+void initial_setup_NO_PICTURE_to_PLACEMENT_with_crit_path(ezgl::application* app, bool is_new_window) {
+ initial_setup_NO_PICTURE_to_PLACEMENT(app, is_new_window);
button_for_toggle_crit_path();
}
/* function below intializes the interface window with a set of buttons and links
* signals to corresponding functions for situation where the window is opened from
* PLACEMENT_to_ROUTING */
-void initial_setup_PLACEMENT_to_ROUTING(ezgl::application* app) {
- initial_setup_NO_PICTURE_to_PLACEMENT_with_crit_path(app);
+void initial_setup_PLACEMENT_to_ROUTING(ezgl::application* app, bool is_new_window) {
+ initial_setup_NO_PICTURE_to_PLACEMENT_with_crit_path(app, is_new_window);
button_for_toggle_rr();
button_for_toggle_congestion();
button_for_toggle_congestion_cost();
@@ -333,8 +335,8 @@
/* function below intializes the interface window with a set of buttons and links
* signals to corresponding functions for situation where the window is opened from
* ROUTING_to_PLACEMENT */
-void initial_setup_ROUTING_to_PLACEMENT(ezgl::application* app) {
- initial_setup_PLACEMENT_to_ROUTING(app);
+void initial_setup_ROUTING_to_PLACEMENT(ezgl::application* app, bool is_new_window) {
+ initial_setup_PLACEMENT_to_ROUTING(app, is_new_window);
std::string toggle_rr = "toggle_rr";
std::string toggle_congestion = "toggle_congestion";
std::string toggle_routing_congestion_cost = "toggle_routing_congestion_cost";
@@ -353,13 +355,15 @@
/* function below intializes the interface window with a set of buttons and links
* signals to corresponding functions for situation where the window is opened from
* NO_PICTURE_to_ROUTING */
-void initial_setup_NO_PICTURE_to_ROUTING(ezgl::application* app) {
+void initial_setup_NO_PICTURE_to_ROUTING(ezgl::application* app, bool is_new_window) {
+ if (!is_new_window) return;
+
GtkButton* window = (GtkButton*)app->get_object("Window");
gtk_button_set_label(window, "Window");
g_signal_connect(window, "clicked", G_CALLBACK(toggle_window_mode), app);
GtkButton* search = (GtkButton*)app->get_object("Search");
- gtk_button_set_label(search, "Search RR Node");
+ gtk_button_set_label(search, "Search");
g_signal_connect(search, "clicked", G_CALLBACK(search_and_highlight), app);
GtkButton* save = (GtkButton*)app->get_object("SaveGraphics");
@@ -387,8 +391,8 @@
/* function below intializes the interface window with a set of buttons and links
* signals to corresponding functions for situation where the window is opened from
* NO_PICTURE_to_ROUTING_with_crit_path */
-void initial_setup_NO_PICTURE_to_ROUTING_with_crit_path(ezgl::application* app) {
- initial_setup_NO_PICTURE_to_ROUTING(app);
+void initial_setup_NO_PICTURE_to_ROUTING_with_crit_path(ezgl::application* app, bool is_new_window) {
+ initial_setup_NO_PICTURE_to_ROUTING(app, is_new_window);
button_for_toggle_crit_path();
}
#endif //NO_GRAPHICS
@@ -408,11 +412,10 @@
ezgl::set_disable_event_loop(false);
//Has the user asked us to pause at the next screen updated?
- bool forced_pause = g_vpr_ctx.forced_pause();
- if (int(priority) >= draw_state->gr_automode || forced_pause) {
- if (forced_pause) {
- VTR_LOG("Starting interactive graphics (due to user interrupt)\n");
- g_vpr_ctx.set_forced_pause(false); //Reset pause flag
+ if (int(priority) >= draw_state->gr_automode || draw_state->forced_pause) {
+ if (draw_state->forced_pause) {
+ VTR_LOG("Pausing in interactive graphics (user pressed 'Pause')\n");
+ draw_state->forced_pause = false; //Reset pause flag
}
vtr::strncpy(draw_state->default_message, msg, vtr::bufsize);
@@ -491,8 +494,18 @@
application.run(initial_setup_NO_PICTURE_to_ROUTING, act_on_mouse_press, act_on_mouse_move, act_on_key_press);
}
}
+ } else {
+ //No change (e.g. paused)
+ application.run(nullptr, act_on_mouse_press, act_on_mouse_move, act_on_key_press);
}
}
+
+ if (draw_state->show_graphics) {
+ application.update_message(msg);
+ application.refresh_drawing();
+ application.flush_drawing();
+ }
+
#else
(void)setup_timing_info;
(void)priority;
@@ -804,7 +817,7 @@
auto& device_ctx = g_vpr_ctx.device();
auto& cluster_ctx = g_vpr_ctx.clustering();
- /* Allocate the structures needed to draw the placement and routing. Set *
+ /* Allocate the structures needed to draw the placement and routing-> Set *
* up the default colors for blocks and nets. */
draw_coords->tile_x = (float*)vtr::malloc(device_ctx.grid.width() * sizeof(float));
draw_coords->tile_y = (float*)vtr::malloc(device_ctx.grid.height() * sizeof(float));
@@ -880,8 +893,8 @@
for (const auto& type : device_ctx.physical_tile_types) {
auto num_pins = type.num_pins;
if (num_pins > 0) {
- draw_coords->pin_size = min(draw_coords->pin_size,
- (draw_coords->get_tile_width() / (4.0F * num_pins)));
+ draw_coords->pin_size = std::min(draw_coords->pin_size,
+ (draw_coords->get_tile_width() / (4.0F * num_pins)));
}
}
@@ -917,7 +930,7 @@
/* Draws the blocks placed on the proper clbs. Occupied blocks are darker colours *
* while empty ones are lighter colours and have a dashed border. */
-static void drawplace(ezgl::renderer& g) {
+static void drawplace(ezgl::renderer* g) {
t_draw_state* draw_state = get_draw_state_vars();
t_draw_coords* draw_coords = get_draw_coords_vars();
auto& device_ctx = g_vpr_ctx.device();
@@ -926,7 +939,7 @@
ClusterBlockId bnum;
int num_sub_tiles;
- g.set_line_width(0);
+ g->set_line_width(0);
for (size_t i = 0; i < device_ctx.grid.width(); i++) {
for (size_t j = 0; j < device_ctx.grid.height(); j++) {
/* Only the first block of a group should control drawing */
@@ -934,7 +947,7 @@
continue;
num_sub_tiles = device_ctx.grid[i][j].type->capacity;
- /* Don't draw if tile capacity is zero. eg. corners. */
+ /* Don't draw if tile capacity is zero. eg-> corners. */
if (num_sub_tiles == 0) {
continue;
}
@@ -954,38 +967,38 @@
block_color = get_block_type_color(device_ctx.grid[i][j].type);
block_color = lighten_color(block_color, EMPTY_BLOCK_LIGHTEN_FACTOR);
}
- g.set_color(block_color);
+ g->set_color(block_color);
/* Get coords of current sub_tile */
ezgl::rectangle abs_clb_bbox = draw_coords->get_absolute_clb_bbox(i, j, k);
ezgl::point2d center = abs_clb_bbox.center();
- g.fill_rectangle(abs_clb_bbox);
+ g->fill_rectangle(abs_clb_bbox);
- g.set_color(ezgl::BLACK);
+ g->set_color(ezgl::BLACK);
- g.set_line_dash((EMPTY_BLOCK_ID == bnum) ? ezgl::line_dash::asymmetric_5_3 : ezgl::line_dash::none);
- g.draw_rectangle(abs_clb_bbox);
+ g->set_line_dash((EMPTY_BLOCK_ID == bnum) ? ezgl::line_dash::asymmetric_5_3 : ezgl::line_dash::none);
+ g->draw_rectangle(abs_clb_bbox);
/* Draw text if the space has parts of the netlist */
if (bnum != EMPTY_BLOCK_ID && bnum != INVALID_BLOCK_ID) {
auto& cluster_ctx = g_vpr_ctx.clustering();
std::string name = cluster_ctx.clb_nlist.block_name(bnum) + vtr::string_fmt(" (#%zu)", size_t(bnum));
- g.draw_text(center, name.c_str(), abs_clb_bbox.width(), abs_clb_bbox.height());
+ g->draw_text(center, name.c_str(), abs_clb_bbox.width(), abs_clb_bbox.height());
}
/* Draw text for block type so that user knows what block */
if (device_ctx.grid[i][j].width_offset == 0 && device_ctx.grid[i][j].height_offset == 0) {
std::string block_type_loc = device_ctx.grid[i][j].type->name;
block_type_loc += vtr::string_fmt(" (%d,%d)", i, j);
- g.draw_text(center - ezgl::point2d(0, abs_clb_bbox.height() / 4),
- block_type_loc.c_str(), abs_clb_bbox.width(), abs_clb_bbox.height());
+ g->draw_text(center - ezgl::point2d(0, abs_clb_bbox.height() / 4),
+ block_type_loc.c_str(), abs_clb_bbox.width(), abs_clb_bbox.height());
}
}
}
}
}
-static void drawnets(ezgl::renderer& g) {
+static void drawnets(ezgl::renderer* g) {
t_draw_state* draw_state = get_draw_state_vars();
t_draw_coords* draw_coords = get_draw_coords_vars();
/* This routine draws the nets on the placement. The nets have not *
@@ -995,8 +1008,8 @@
ClusterBlockId b1, b2;
auto& cluster_ctx = g_vpr_ctx.clustering();
- g.set_line_dash(ezgl::line_dash::none);
- g.set_line_width(0);
+ g->set_line_dash(ezgl::line_dash::none);
+ g->set_line_width(0);
/* Draw the net as a star from the source to each sink. Draw from centers of *
* blocks (or sub blocks in the case of IOs). */
@@ -1005,20 +1018,20 @@
if (cluster_ctx.clb_nlist.net_is_ignored(net_id))
continue; /* Don't draw */
- g.set_color(draw_state->net_color[net_id]);
+ g->set_color(draw_state->net_color[net_id]);
b1 = cluster_ctx.clb_nlist.net_driver_block(net_id);
ezgl::point2d driver_center = draw_coords->get_absolute_clb_bbox(b1, cluster_ctx.clb_nlist.block_type(b1)).center();
for (auto pin_id : cluster_ctx.clb_nlist.net_sinks(net_id)) {
b2 = cluster_ctx.clb_nlist.pin_block(pin_id);
ezgl::point2d sink_center = draw_coords->get_absolute_clb_bbox(b2, cluster_ctx.clb_nlist.block_type(b2)).center();
- g.draw_line(driver_center, sink_center);
+ g->draw_line(driver_center, sink_center);
/* Uncomment to draw a chain instead of a star. */
/* driver_center = sink_center; */
}
}
}
-static void draw_congestion(ezgl::renderer& g) {
+static void draw_congestion(ezgl::renderer* g) {
/* Draws all the overused routing resources (i.e. congestion) in various contrasting colors showing congestion ratio. */
t_draw_state* draw_state = get_draw_state_vars();
@@ -1054,7 +1067,7 @@
std::unique_ptr<vtr::ColorMap> cmap = std::make_unique<vtr::PlasmaColorMap>(min_congestion_ratio, max_congestion_ratio);
//Sort the nodes in ascending order of value for drawing, this ensures high
- //valued nodes are not overdrawn by lower value ones (e.g. when zoomed-out far)
+ //valued nodes are not overdrawn by lower value ones (e.g-> when zoomed-out far)
auto cmp_ascending_acc_cost = [&](int lhs_node, int rhs_node) {
short lhs_occ = route_ctx.rr_node_route_inf[lhs_node].occ();
short lhs_capacity = device_ctx.rr_nodes[lhs_node].capacity();
@@ -1078,7 +1091,7 @@
draw_state->net_color[net] = color;
}
}
- g.set_line_width(0);
+ g->set_line_width(0);
drawroute(HIGHLIGHTED, g);
//Reset colors
@@ -1088,7 +1101,7 @@
}
}
} else {
- g.set_line_width(2);
+ g->set_line_width(2);
}
//Draw each congested node
@@ -1121,7 +1134,7 @@
draw_state->color_map = std::move(cmap);
}
-static void draw_routing_costs(ezgl::renderer& g) {
+static void draw_routing_costs(ezgl::renderer* g) {
/* Draws routing resource nodes colored according to their congestion costs */
t_draw_state* draw_state = get_draw_state_vars();
@@ -1136,7 +1149,7 @@
auto& device_ctx = g_vpr_ctx.device();
auto& route_ctx = g_vpr_ctx.routing();
- g.set_line_width(0);
+ g->set_line_width(0);
VTR_ASSERT(!route_ctx.rr_node_route_inf.empty());
@@ -1205,7 +1218,7 @@
draw_rr_costs(g, rr_node_costs, true);
}
-static void draw_routing_bb(ezgl::renderer& g) {
+static void draw_routing_bb(ezgl::renderer* g) {
t_draw_state* draw_state = get_draw_state_vars();
if (draw_state->show_routing_bb == OPEN) {
@@ -1242,13 +1255,13 @@
double draw_xhigh = draw_coords->tile_x[bb->xmax] + 2 * draw_coords->get_tile_width();
double draw_yhigh = draw_coords->tile_y[bb->ymax] + 2 * draw_coords->get_tile_height();
- g.set_color(blk_RED);
- g.draw_rectangle({draw_xlow, draw_ylow}, {draw_xhigh, draw_yhigh});
+ g->set_color(blk_RED);
+ g->draw_rectangle({draw_xlow, draw_ylow}, {draw_xhigh, draw_yhigh});
ezgl::color fill = blk_SKYBLUE;
fill.alpha *= 0.3;
- g.set_color(fill);
- g.fill_rectangle({draw_xlow, draw_ylow}, {draw_xhigh, draw_yhigh});
+ g->set_color(fill);
+ g->fill_rectangle({draw_xlow, draw_ylow}, {draw_xhigh, draw_yhigh});
draw_routed_net(net_id, g);
@@ -1260,20 +1273,20 @@
application.update_message(msg.c_str());
}
-void draw_rr(ezgl::renderer& g) {
+void draw_rr(ezgl::renderer* g) {
/* Draws the routing resources that exist in the FPGA, if the user wants *
* them drawn. */
t_draw_state* draw_state = get_draw_state_vars();
auto& device_ctx = g_vpr_ctx.device();
if (draw_state->draw_rr_toggle == DRAW_NO_RR) {
- g.set_line_width(3);
+ g->set_line_width(3);
drawroute(HIGHLIGHTED, g);
- g.set_line_width(0);
+ g->set_line_width(0);
return;
}
- g.set_line_dash(ezgl::line_dash::none);
+ g->set_line_dash(ezgl::line_dash::none);
for (size_t inode = 0; inode < device_ctx.rr_nodes.size(); inode++) {
if (!draw_state->draw_rr_node[inode].node_highlighted) {
@@ -1328,7 +1341,7 @@
drawroute(HIGHLIGHTED, g);
}
-static void draw_rr_chan(int inode, const ezgl::color color, ezgl::renderer& g) {
+static void draw_rr_chan(int inode, const ezgl::color color, ezgl::renderer* g) {
auto& device_ctx = g_vpr_ctx.device();
t_rr_type type = device_ctx.rr_nodes[inode].type();
@@ -1345,17 +1358,17 @@
std::swap(start, end);
}
- g.set_color(color);
+ g->set_color(color);
if (color != DEFAULT_RR_NODE_COLOR) {
// If wire is highlighted, then draw with thicker linewidth.
- g.set_line_width(3);
+ g->set_line_width(3);
}
- g.draw_line(start, end);
+ g->draw_line(start, end);
if (color != DEFAULT_RR_NODE_COLOR) {
// Revert width change
- g.set_line_width(0);
+ g->set_line_width(0);
}
e_side mux_dir = TOP;
@@ -1425,14 +1438,14 @@
std::swap(arrow_color, text_color);
}
- g.set_color(arrow_color);
+ g->set_color(arrow_color);
draw_triangle_along_line(g, arrow_loc_min, start, end);
- g.set_color(text_color);
+ g->set_color(text_color);
ezgl::rectangle bbox(ezgl::point2d(arrow_loc_min.x - DEFAULT_ARROW_SIZE / 2, arrow_loc_min.y - DEFAULT_ARROW_SIZE / 4),
ezgl::point2d(arrow_loc_min.x + DEFAULT_ARROW_SIZE / 2, arrow_loc_min.y + DEFAULT_ARROW_SIZE / 4));
ezgl::point2d center = bbox.center();
- g.draw_text(center, std::to_string(switchpoint_min), bbox.width(), bbox.height());
+ g->draw_text(center, std::to_string(switchpoint_min), bbox.width(), bbox.height());
if (k == coord_min) {
//Revert
@@ -1451,14 +1464,14 @@
std::swap(arrow_color, text_color);
}
- g.set_color(arrow_color);
+ g->set_color(arrow_color);
draw_triangle_along_line(g, arrow_loc_max, start, end);
- g.set_color(text_color);
+ g->set_color(text_color);
ezgl::rectangle bbox(ezgl::point2d(arrow_loc_max.x - DEFAULT_ARROW_SIZE / 2, arrow_loc_max.y - DEFAULT_ARROW_SIZE / 4),
ezgl::point2d(arrow_loc_max.x + DEFAULT_ARROW_SIZE / 2, arrow_loc_max.y + DEFAULT_ARROW_SIZE / 4));
ezgl::point2d center = bbox.center();
- g.draw_text(center, std::to_string(switchpoint_max), bbox.width(), bbox.height());
+ g->draw_text(center, std::to_string(switchpoint_max), bbox.width(), bbox.height());
if (k == coord_max) {
//Revert
@@ -1466,10 +1479,10 @@
}
}
}
- g.set_color(color); //Ensure color is still set correctly if we drew any arrows/text
+ g->set_color(color); //Ensure color is still set correctly if we drew any arrows/text
}
-static void draw_rr_edges(int inode, ezgl::renderer& g) {
+static void draw_rr_edges(int inode, ezgl::renderer* g) {
/* Draws all the edges that the user wants shown between inode and what it *
* connects to. inode is assumed to be a CHANX, CHANY, or IPIN. */
t_draw_state* draw_state = get_draw_state_vars();
@@ -1502,25 +1515,25 @@
if (draw_state->draw_rr_node[inode].color == ezgl::MAGENTA) {
// If OPIN was clicked on, set color to fan-out
ezgl::color color = draw_state->draw_rr_node[to_node].color;
- g.set_color(color);
+ g->set_color(color);
} else if (draw_state->draw_rr_node[to_node].color == ezgl::MAGENTA) {
// If CHANX or CHANY got clicked, set color to fan-in
ezgl::color color = draw_state->draw_rr_node[inode].color;
- g.set_color(color);
+ g->set_color(color);
} else {
- g.set_color(ezgl::PINK);
+ g->set_color(ezgl::PINK);
}
draw_pin_to_chan_edge(inode, to_node, g);
break;
case IPIN:
if (draw_state->draw_rr_node[inode].color == ezgl::MAGENTA) {
ezgl::color color = draw_state->draw_rr_node[to_node].color;
- g.set_color(color);
+ g->set_color(color);
} else if (draw_state->draw_rr_node[to_node].color == ezgl::MAGENTA) {
ezgl::color color = draw_state->draw_rr_node[inode].color;
- g.set_color(color);
+ g->set_color(color);
} else {
- g.set_color(ezgl::MEDIUM_PURPLE);
+ g->set_color(ezgl::MEDIUM_PURPLE);
}
draw_pin_to_pin(inode, to_node, g);
break;
@@ -1549,12 +1562,12 @@
if (draw_state->draw_rr_node[inode].color == ezgl::MAGENTA) {
ezgl::color color = draw_state->draw_rr_node[to_node].color;
- g.set_color(color);
+ g->set_color(color);
} else if (draw_state->draw_rr_node[to_node].color == ezgl::MAGENTA) {
ezgl::color color = draw_state->draw_rr_node[inode].color;
- g.set_color(color);
+ g->set_color(color);
} else {
- g.set_color(blk_LIGHTSKYBLUE);
+ g->set_color(blk_LIGHTSKYBLUE);
}
draw_pin_to_chan_edge(to_node, inode, g);
break;
@@ -1562,15 +1575,15 @@
case CHANX:
if (draw_state->draw_rr_node[inode].color == ezgl::MAGENTA) {
ezgl::color color = draw_state->draw_rr_node[to_node].color;
- g.set_color(color);
+ g->set_color(color);
} else if (draw_state->draw_rr_node[to_node].color == ezgl::MAGENTA) {
ezgl::color color = draw_state->draw_rr_node[inode].color;
- g.set_color(color);
+ g->set_color(color);
} else if (!edge_configurable) {
ezgl::color color = blk_DARKGREY;
- g.set_color(color);
+ g->set_color(color);
} else {
- g.set_color(blk_DARKGREEN);
+ g->set_color(blk_DARKGREEN);
}
switch_type = device_ctx.rr_nodes[inode].edge_switch(iedge);
draw_chanx_to_chanx_edge(inode, to_node,
@@ -1580,14 +1593,14 @@
case CHANY:
if (draw_state->draw_rr_node[inode].color == ezgl::MAGENTA) {
ezgl::color color = draw_state->draw_rr_node[to_node].color;
- g.set_color(color);
+ g->set_color(color);
} else if (draw_state->draw_rr_node[to_node].color == ezgl::MAGENTA) {
ezgl::color color = draw_state->draw_rr_node[inode].color;
- g.set_color(color);
+ g->set_color(color);
} else if (!edge_configurable) {
- g.set_color(blk_DARKGREY);
+ g->set_color(blk_DARKGREY);
} else {
- g.set_color(blk_DARKGREEN);
+ g->set_color(blk_DARKGREEN);
}
switch_type = device_ctx.rr_nodes[inode].edge_switch(iedge);
draw_chanx_to_chany_edge(inode, from_ptc_num, to_node,
@@ -1619,12 +1632,12 @@
if (draw_state->draw_rr_node[inode].color == ezgl::MAGENTA) {
ezgl::color color = draw_state->draw_rr_node[to_node].color;
- g.set_color(color);
+ g->set_color(color);
} else if (draw_state->draw_rr_node[to_node].color == ezgl::MAGENTA) {
ezgl::color color = draw_state->draw_rr_node[inode].color;
- g.set_color(color);
+ g->set_color(color);
} else {
- g.set_color(blk_LIGHTSKYBLUE);
+ g->set_color(blk_LIGHTSKYBLUE);
}
draw_pin_to_chan_edge(to_node, inode, g);
break;
@@ -1632,15 +1645,15 @@
case CHANX:
if (draw_state->draw_rr_node[inode].color == ezgl::MAGENTA) {
ezgl::color color = draw_state->draw_rr_node[to_node].color;
- g.set_color(color);
+ g->set_color(color);
} else if (draw_state->draw_rr_node[to_node].color == ezgl::MAGENTA) {
ezgl::color color = draw_state->draw_rr_node[inode].color;
- g.set_color(color);
+ g->set_color(color);
} else if (!edge_configurable) {
ezgl::color color = blk_DARKGREY;
- g.set_color(color);
+ g->set_color(color);
} else {
- g.set_color(blk_DARKGREEN);
+ g->set_color(blk_DARKGREEN);
}
switch_type = device_ctx.rr_nodes[inode].edge_switch(iedge);
draw_chanx_to_chany_edge(to_node, to_ptc_num, inode,
@@ -1650,15 +1663,15 @@
case CHANY:
if (draw_state->draw_rr_node[inode].color == ezgl::MAGENTA) {
ezgl::color color = draw_state->draw_rr_node[to_node].color;
- g.set_color(color);
+ g->set_color(color);
} else if (draw_state->draw_rr_node[to_node].color == ezgl::MAGENTA) {
ezgl::color color = draw_state->draw_rr_node[inode].color;
- g.set_color(color);
+ g->set_color(color);
} else if (!edge_configurable) {
ezgl::color color = blk_DARKGREY;
- g.set_color(color);
+ g->set_color(color);
} else {
- g.set_color(blk_DARKGREEN);
+ g->set_color(blk_DARKGREEN);
}
switch_type = device_ctx.rr_nodes[inode].edge_switch(iedge);
draw_chany_to_chany_edge(inode, to_node,
@@ -1682,14 +1695,14 @@
} /* End of for each edge loop */
}
-static void draw_x(float x, float y, float size, ezgl::renderer& g) {
+static void draw_x(float x, float y, float size, ezgl::renderer* g) {
/* Draws an X centered at (x,y). The width and height of the X are each *
* 2 * size. */
- g.draw_line({x - size, y + size}, {x + size, y - size});
- g.draw_line({x - size, y - size}, {x + size, y + size});
+ g->draw_line({x - size, y + size}, {x + size, y - size});
+ g->draw_line({x - size, y - size}, {x + size, y + size});
}
-static void draw_chanx_to_chany_edge(int chanx_node, int chanx_track, int chany_node, int chany_track, enum e_edge_dir edge_dir, short switch_type, ezgl::renderer& g) {
+static void draw_chanx_to_chany_edge(int chanx_node, int chanx_track, int chany_node, int chany_track, enum e_edge_dir edge_dir, short switch_type, ezgl::renderer* g) {
t_draw_state* draw_state = get_draw_state_vars();
t_draw_coords* draw_coords = get_draw_coords_vars();
auto& device_ctx = g_vpr_ctx.device();
@@ -1748,7 +1761,7 @@
y2 = chany_bbox.bottom();
}
- g.draw_line({x1, y1}, {x2, y2});
+ g->draw_line({x1, y1}, {x2, y2});
if (draw_state->draw_rr_toggle == DRAW_ALL_RR || draw_state->draw_rr_node[chanx_node].node_highlighted) {
if (edge_dir == FROM_X_TO_Y) {
@@ -1759,10 +1772,10 @@
}
}
-static void draw_chanx_to_chanx_edge(int from_node, int to_node, int to_track, short switch_type, ezgl::renderer& g) {
+static void draw_chanx_to_chanx_edge(int from_node, int to_node, int to_track, short switch_type, ezgl::renderer* g) {
/* Draws a connection between two x-channel segments. Passing in the track *
* numbers allows this routine to be used for both rr_graph and routing *
- * drawing. */
+ * drawing-> */
t_draw_state* draw_state = get_draw_state_vars();
t_draw_coords* draw_coords = get_draw_coords_vars();
@@ -1837,21 +1850,21 @@
}
}
- g.draw_line({x1, y1}, {x2, y2});
+ g->draw_line({x1, y1}, {x2, y2});
if (draw_state->draw_rr_toggle == DRAW_ALL_RR || draw_state->draw_rr_node[from_node].node_highlighted) {
draw_rr_switch(x1, y1, x2, y2, device_ctx.rr_switch_inf[switch_type].buffered(), device_ctx.rr_switch_inf[switch_type].configurable(), g);
}
}
-static void draw_chany_to_chany_edge(int from_node, int to_node, int to_track, short switch_type, ezgl::renderer& g) {
+static void draw_chany_to_chany_edge(int from_node, int to_node, int to_track, short switch_type, ezgl::renderer* g) {
t_draw_state* draw_state = get_draw_state_vars();
t_draw_coords* draw_coords = get_draw_coords_vars();
auto& device_ctx = g_vpr_ctx.device();
/* Draws a connection between two y-channel segments. Passing in the track *
* numbers allows this routine to be used for both rr_graph and routing *
- * drawing. */
+ * drawing-> */
float x1, x2, y1, y2;
ezgl::rectangle from_chan;
@@ -1920,7 +1933,7 @@
}
/* UDSD Modification by WMF End */
- g.draw_line({x1, y1}, {x2, y2});
+ g->draw_line({x1, y1}, {x2, y2});
if (draw_state->draw_rr_toggle == DRAW_ALL_RR || draw_state->draw_rr_node[from_node].node_highlighted) {
draw_rr_switch(x1, y1, x2, y2, device_ctx.rr_switch_inf[switch_type].buffered(), device_ctx.rr_switch_inf[switch_type].configurable(), g);
@@ -1969,7 +1982,7 @@
return bound_box;
}
-static void draw_rr_switch(float from_x, float from_y, float to_x, float to_y, bool buffered, bool configurable, ezgl::renderer& g) {
+static void draw_rr_switch(float from_x, float from_y, float to_x, float to_y, bool buffered, bool configurable, ezgl::renderer* g) {
/* Draws a buffer (triangle) or pass transistor (circle) on the edge *
* connecting from to to, depending on the status of buffered. The drawing *
* is closest to the from_node, since it reflects the switch type of from. */
@@ -1979,7 +1992,7 @@
float xcen = from_x + (to_x - from_x) / 10.;
float ycen = from_y + (to_y - from_y) / 10.;
const float switch_rad = 0.15;
- g.draw_arc({xcen, ycen}, switch_rad, 0., 360.);
+ g->draw_arc({xcen, ycen}, switch_rad, 0., 360.);
} else {
//Pass, nothing to draw
}
@@ -1994,7 +2007,7 @@
}
}
-static void draw_rr_pin(int inode, const ezgl::color& color, ezgl::renderer& g) {
+static void draw_rr_pin(int inode, const ezgl::color& color, ezgl::renderer* g) {
/* Draws an IPIN or OPIN rr_node. Note that the pin can appear on more *
* than one side of a clb. Also note that this routine can change the *
* current color to BLACK. */
@@ -2007,16 +2020,16 @@
int ipin = device_ctx.rr_nodes[inode].ptc_num();
- g.set_color(color);
+ g->set_color(color);
/* TODO: This is where we can hide fringe physical pins and also identify globals (hide, color, show) */
draw_get_rr_pin_coords(inode, &xcen, &ycen);
- g.fill_rectangle({xcen - draw_coords->pin_size, ycen - draw_coords->pin_size},
- {xcen + draw_coords->pin_size, ycen + draw_coords->pin_size});
+ g->fill_rectangle({xcen - draw_coords->pin_size, ycen - draw_coords->pin_size},
+ {xcen + draw_coords->pin_size, ycen + draw_coords->pin_size});
sprintf(str, "%d", ipin);
- g.set_color(ezgl::BLACK);
- g.draw_text({xcen, ycen}, str, 2 * draw_coords->pin_size, 2 * draw_coords->pin_size);
- g.set_color(color);
+ g->set_color(ezgl::BLACK);
+ g->draw_text({xcen, ycen}, str, 2 * draw_coords->pin_size, 2 * draw_coords->pin_size);
+ g->set_color(color);
}
/* Returns the coordinates at which the center of this pin should be drawn. *
@@ -2082,7 +2095,7 @@
*ycen = yc;
}
-static void draw_rr_src_sink(int inode, ezgl::color color, ezgl::renderer& g) {
+static void draw_rr_src_sink(int inode, ezgl::color color, ezgl::renderer* g) {
t_draw_coords* draw_coords = get_draw_coords_vars();
auto& device_ctx = g_vpr_ctx.device();
@@ -2092,24 +2105,24 @@
int xhigh = device_ctx.rr_nodes[inode].xhigh();
int yhigh = device_ctx.rr_nodes[inode].yhigh();
- g.set_color(color);
+ g->set_color(color);
- g.fill_rectangle({draw_coords->get_tile_width() * xlow, draw_coords->get_tile_height() * ylow},
- {draw_coords->get_tile_width() * xhigh, draw_coords->get_tile_height() * yhigh});
+ g->fill_rectangle({draw_coords->get_tile_width() * xlow, draw_coords->get_tile_height() * ylow},
+ {draw_coords->get_tile_width() * xhigh, draw_coords->get_tile_height() * yhigh});
}
/* Draws the nets in the positions fixed by the router. If draw_net_type is *
* ALL_NETS, draw all the nets. If it is HIGHLIGHTED, draw only the nets *
* that are not coloured black (useful for drawing over the rr_graph). */
-static void drawroute(enum e_draw_net_type draw_net_type, ezgl::renderer& g) {
+static void drawroute(enum e_draw_net_type draw_net_type, ezgl::renderer* g) {
/* Next free track in each channel segment if routing is GLOBAL */
auto& cluster_ctx = g_vpr_ctx.clustering();
t_draw_state* draw_state = get_draw_state_vars();
- g.set_line_dash(ezgl::line_dash::none);
+ g->set_line_dash(ezgl::line_dash::none);
/* Now draw each net, one by one. */
@@ -2121,7 +2134,7 @@
} /* End for (each net) */
}
-static void draw_routed_net(ClusterNetId net_id, ezgl::renderer& g) {
+static void draw_routed_net(ClusterNetId net_id, ezgl::renderer* g) {
auto& route_ctx = g_vpr_ctx.routing();
auto& cluster_ctx = g_vpr_ctx.clustering();
@@ -2130,7 +2143,7 @@
if (cluster_ctx.clb_nlist.net_is_ignored(net_id)) /* Don't draw. */
return;
- if (route_ctx.trace[net_id].head == nullptr) /* No routing. Skip. (Allows me to draw */
+ if (route_ctx.trace[net_id].head == nullptr) /* No routing-> Skip. (Allows me to draw */
return; /* partially complete routes). */
t_trace* tptr = route_ctx.trace[net_id].head; /* SOURCE to start */
@@ -2172,7 +2185,7 @@
}
//Draws the set of rr_nodes specified, using the colors set in draw_state
-void draw_partial_route(const std::vector<int>& rr_nodes_to_draw, ezgl::renderer& g) {
+void draw_partial_route(const std::vector<int>& rr_nodes_to_draw, ezgl::renderer* g) {
t_draw_state* draw_state = get_draw_state_vars();
auto& device_ctx = g_vpr_ctx.device();
@@ -2603,11 +2616,11 @@
if (window_point_1_collected) {
// draw a grey, dashed-line box to indicate the zoom-in region
app->refresh_drawing();
- ezgl::renderer g = app->get_renderer();
- g.set_line_dash(ezgl::line_dash::asymmetric_5_3);
- g.set_color(blk_GREY);
- g.set_line_width(2);
- g.draw_rectangle(point_1, {x, y});
+ ezgl::renderer* g = app->get_renderer();
+ g->set_line_dash(ezgl::line_dash::asymmetric_5_3);
+ g->set_color(blk_GREY);
+ g->set_line_width(2);
+ g->draw_rectangle(point_1, {x, y});
return;
}
@@ -2727,7 +2740,7 @@
* A 'relative_position' of 1. draws the triangle centered at 'end'.
* Fractional values draw the triangle along the line
*/
-void draw_triangle_along_line(ezgl::renderer& g, ezgl::point2d start, ezgl::point2d end, float relative_position, float arrow_size) {
+void draw_triangle_along_line(ezgl::renderer* g, ezgl::point2d start, ezgl::point2d end, float relative_position, float arrow_size) {
VTR_ASSERT(relative_position >= 0. && relative_position <= 1.);
float xdelta = end.x - start.x;
float ydelta = end.y - start.y;
@@ -2742,7 +2755,7 @@
* arrow_size, rotated such that it points in the direction
* of the directed line segment start -> end.
*/
-void draw_triangle_along_line(ezgl::renderer& g, ezgl::point2d loc, ezgl::point2d start, ezgl::point2d end, float arrow_size) {
+void draw_triangle_along_line(ezgl::renderer* g, ezgl::point2d loc, ezgl::point2d start, ezgl::point2d end, float arrow_size) {
draw_triangle_along_line(g, loc.x, loc.y, start.x, end.x, start.y, end.y, arrow_size);
}
@@ -2754,7 +2767,7 @@
* Note that the parameters are in a strange order
*/
-void draw_triangle_along_line(ezgl::renderer& g, float xend, float yend, float x1, float x2, float y1, float y2, float arrow_size) {
+void draw_triangle_along_line(ezgl::renderer* g, float xend, float yend, float x1, float x2, float y1, float y2, float arrow_size) {
float switch_rad = arrow_size / 2;
float xdelta, ydelta;
float magnitude;
@@ -2776,10 +2789,10 @@
poly.push_back({xbaseline + yunit * switch_rad, ybaseline - xunit * switch_rad});
poly.push_back({xbaseline - yunit * switch_rad, ybaseline + xunit * switch_rad});
- g.fill_poly(poly);
+ g->fill_poly(poly);
}
-static void draw_pin_to_chan_edge(int pin_node, int chan_node, ezgl::renderer& g) {
+static void draw_pin_to_chan_edge(int pin_node, int chan_node, ezgl::renderer* g) {
/* This routine draws an edge from the pin_node to the chan_node (CHANX or *
* CHANY). The connection is made to the nearest end of the track instead *
* of perpendicular to the track to symbolize a single-drive connection. */
@@ -2843,7 +2856,7 @@
"in draw_pin_to_chan_edge: Invalid channel node %d.\n", chan_node);
}
}
- g.draw_line({x1, y1}, {x2, y2});
+ g->draw_line({x1, y1}, {x2, y2});
//don't draw the ex, or triangle unless zoomed in really far
if (chan_rr.direction() == BI_DIRECTION || !is_opin(pin_rr.pin_num(), grid_type)) {
@@ -2855,7 +2868,7 @@
}
}
-static void draw_pin_to_pin(int opin_node, int ipin_node, ezgl::renderer& g) {
+static void draw_pin_to_pin(int opin_node, int ipin_node, ezgl::renderer* g) {
/* This routine draws an edge from the opin rr node to the ipin rr node */
auto& device_ctx = g_vpr_ctx.device();
VTR_ASSERT(device_ctx.rr_nodes[opin_node].type() == OPIN);
@@ -2867,28 +2880,28 @@
float x2 = 0, y2 = 0;
draw_get_rr_pin_coords(ipin_node, &x2, &y2);
- g.draw_line({x1, y1}, {x2, y2});
+ g->draw_line({x1, y1}, {x2, y2});
float xend = x2 + (x1 - x2) / 10.;
float yend = y2 + (y1 - y2) / 10.;
draw_triangle_along_line(g, xend, yend, x1, x2, y1, y2);
}
-static inline void draw_mux_with_size(ezgl::point2d origin, e_side orientation, float height, int size, ezgl::renderer& g) {
- g.set_color(ezgl::YELLOW);
+static inline void draw_mux_with_size(ezgl::point2d origin, e_side orientation, float height, int size, ezgl::renderer* g) {
+ g->set_color(ezgl::YELLOW);
auto bounds = draw_mux(origin, orientation, height, g);
- g.set_color(ezgl::BLACK);
- g.draw_text(bounds.center(), std::to_string(size), bounds.width(), bounds.height());
+ g->set_color(ezgl::BLACK);
+ g->draw_text(bounds.center(), std::to_string(size), bounds.width(), bounds.height());
}
//Draws a mux
-static inline ezgl::rectangle draw_mux(ezgl::point2d origin, e_side orientation, float height, ezgl::renderer& g) {
+static inline ezgl::rectangle draw_mux(ezgl::point2d origin, e_side orientation, float height, ezgl::renderer* g) {
return draw_mux(origin, orientation, height, 0.4 * height, 0.6, g);
}
//Draws a mux, height/width define the bounding box, scale [0.,1.] controls the slope of the muxes sides
-static inline ezgl::rectangle draw_mux(ezgl::point2d origin, e_side orientation, float height, float width, float scale, ezgl::renderer& g) {
+static inline ezgl::rectangle draw_mux(ezgl::point2d origin, e_side orientation, float height, float width, float scale, ezgl::renderer* g) {
std::vector<ezgl::point2d> mux_polygon;
switch (orientation) {
@@ -2924,7 +2937,7 @@
default:
VTR_ASSERT_MSG(false, "Unrecognized orientation");
}
- g.fill_poly(mux_polygon);
+ g->fill_poly(mux_polygon);
ezgl::point2d min((float)mux_polygon[0].x, (float)mux_polygon[0].y);
ezgl::point2d max((float)mux_polygon[0].x, (float)mux_polygon[0].y);
@@ -2972,7 +2985,7 @@
return point;
}
-static void draw_crit_path(ezgl::renderer& g) {
+static void draw_crit_path(ezgl::renderer* g) {
tatum::TimingPathCollector path_collector;
t_draw_state* draw_state = get_draw_state_vars();
@@ -3006,8 +3019,8 @@
float delay = arr_time - prev_arr_time;
if (draw_state->show_crit_path == DRAW_CRIT_PATH_FLYLINES || draw_state->show_crit_path == DRAW_CRIT_PATH_FLYLINES_DELAYS) {
- g.set_color(color);
- g.set_line_dash(ezgl::line_dash::none);
+ g->set_color(color);
+ g->set_line_dash(ezgl::line_dash::none);
draw_flyline_timing_edge(tnode_draw_coord(prev_node), tnode_draw_coord(node), delay, g);
} else {
VTR_ASSERT(draw_state->show_crit_path != DRAW_NO_CRIT_PATH);
@@ -3021,8 +3034,8 @@
}
}
-static void draw_flyline_timing_edge(ezgl::point2d start, ezgl::point2d end, float incr_delay, ezgl::renderer& g) {
- g.draw_line(start, end);
+static void draw_flyline_timing_edge(ezgl::point2d start, ezgl::point2d end, float incr_delay, ezgl::renderer* g) {
+ g->draw_line(start, end);
draw_triangle_along_line(g, start, end, 0.95, 40 * DEFAULT_ARROW_SIZE);
draw_triangle_along_line(g, start, end, 0.05, 40 * DEFAULT_ARROW_SIZE);
@@ -3058,25 +3071,25 @@
ss << 1e9 * incr_delay; //In nanoseconds
std::string incr_delay_str = ss.str();
- g.draw_text(text_bbox.center(), incr_delay_str.c_str(), text_bbox.width(), text_bbox.height());
+ g->draw_text(text_bbox.center(), incr_delay_str.c_str(), text_bbox.width(), text_bbox.height());
}
}
-static void draw_routed_timing_edge(tatum::NodeId start_tnode, tatum::NodeId end_tnode, float incr_delay, ezgl::color color, ezgl::renderer& g) {
+static void draw_routed_timing_edge(tatum::NodeId start_tnode, tatum::NodeId end_tnode, float incr_delay, ezgl::color color, ezgl::renderer* g) {
draw_routed_timing_edge_connection(start_tnode, end_tnode, color, g);
- g.set_line_dash(ezgl::line_dash::asymmetric_5_3);
- g.set_line_width(3);
- g.set_color(color);
+ g->set_line_dash(ezgl::line_dash::asymmetric_5_3);
+ g->set_line_width(3);
+ g->set_color(color);
- draw_flyline_timing_edge((ezgl::point2d)tnode_draw_coord(start_tnode), (ezgl::point2d)tnode_draw_coord(end_tnode), (float)incr_delay, (ezgl::renderer&)g);
+ draw_flyline_timing_edge((ezgl::point2d)tnode_draw_coord(start_tnode), (ezgl::point2d)tnode_draw_coord(end_tnode), (float)incr_delay, (ezgl::renderer*)g);
- g.set_line_width(0);
- g.set_line_dash(ezgl::line_dash::none);
+ g->set_line_width(0);
+ g->set_line_dash(ezgl::line_dash::none);
}
//Collect all the drawing locations associated with the timing edge between start and end
-static void draw_routed_timing_edge_connection(tatum::NodeId src_tnode, tatum::NodeId sink_tnode, ezgl::color color, ezgl::renderer& g) {
+static void draw_routed_timing_edge_connection(tatum::NodeId src_tnode, tatum::NodeId sink_tnode, ezgl::color color, ezgl::renderer* g) {
auto& atom_ctx = g_vpr_ctx.atom();
auto& cluster_ctx = g_vpr_ctx.clustering();
auto& timing_ctx = g_vpr_ctx.timing();
@@ -3130,7 +3143,7 @@
draw_state->draw_rr_node[inode].color = color;
}
- draw_partial_route((std::vector<int>)routed_rr_nodes, (ezgl::renderer&)g);
+ draw_partial_route((std::vector<int>)routed_rr_nodes, (ezgl::renderer*)g);
} else {
//Connection entirely within the CLB, we don't draw the internal routing so treat it as a fly-line
VTR_ASSERT(clb_src_block == clb_sink_block);
@@ -3211,13 +3224,13 @@
return ezgl::color(color.r * 255, color.g * 255, color.b * 255);
}
-static void draw_color_map_legend(const vtr::ColorMap& cmap, ezgl::renderer& g) {
+static void draw_color_map_legend(const vtr::ColorMap& cmap, ezgl::renderer* g) {
constexpr float LEGEND_WIDTH_FAC = 0.075;
constexpr float LEGEND_VERT_OFFSET_FAC = 0.05;
constexpr float TEXT_OFFSET = 10;
constexpr size_t NUM_COLOR_POINTS = 1000;
- g.set_coordinate_system(ezgl::SCREEN);
+ g->set_coordinate_system(ezgl::SCREEN);
float screen_width = application.get_canvas(application.get_main_canvas_id())->width();
float screen_height = application.get_canvas(application.get_main_canvas_id())->height();
@@ -3233,30 +3246,30 @@
float val = cmap.min() + (float(i) / NUM_COLOR_POINTS) * range;
ezgl::color color = to_ezgl_color(cmap.color(val));
- g.set_color(color);
- g.fill_rectangle({legend.left(), legend.top() - i * height_incr},
- {legend.right(), legend.top() - (i + 1) * height_incr});
+ g->set_color(color);
+ g->fill_rectangle({legend.left(), legend.top() - i * height_incr},
+ {legend.right(), legend.top() - (i + 1) * height_incr});
}
//Min mark
- g.set_color(blk_SKYBLUE); // set to skyblue so its easier to see
+ g->set_color(blk_SKYBLUE); // set to skyblue so its easier to see
std::string str = vtr::string_fmt("%.3g", cmap.min());
- g.draw_text({legend.center_x(), legend.top() - TEXT_OFFSET}, str.c_str());
+ g->draw_text({legend.center_x(), legend.top() - TEXT_OFFSET}, str.c_str());
//Mid marker
- g.set_color(ezgl::BLACK);
+ g->set_color(ezgl::BLACK);
str = vtr::string_fmt("%.3g", cmap.min() + (cmap.range() / 2.));
- g.draw_text({legend.center_x(), legend.center_y()}, str.c_str());
+ g->draw_text({legend.center_x(), legend.center_y()}, str.c_str());
//Max marker
- g.set_color(ezgl::BLACK);
+ g->set_color(ezgl::BLACK);
str = vtr::string_fmt("%.3g", cmap.max());
- g.draw_text({legend.center_x(), legend.bottom() + TEXT_OFFSET}, str.c_str());
+ g->draw_text({legend.center_x(), legend.bottom() + TEXT_OFFSET}, str.c_str());
- g.set_color(ezgl::BLACK);
- g.draw_rectangle(legend);
+ g->set_color(ezgl::BLACK);
+ g->draw_rectangle(legend);
- g.set_coordinate_system(ezgl::WORLD);
+ g->set_coordinate_system(ezgl::WORLD);
}
ezgl::color get_block_type_color(t_physical_tile_type_ptr type) {
@@ -3343,7 +3356,7 @@
}
}
-static void draw_routing_util(ezgl::renderer& g) {
+static void draw_routing_util(ezgl::renderer* g) {
t_draw_state* draw_state = get_draw_state_vars();
if (draw_state->show_routing_util == DRAW_NO_ROUTING_UTIL) {
return;
@@ -3388,16 +3401,16 @@
chanx_util = routing_util(chanx_usage[x][y], chanx_avail[x][y]);
ezgl::color chanx_color = to_ezgl_color(cmap->color(chanx_util));
chanx_color.alpha *= ALPHA;
- g.set_color(chanx_color);
+ g->set_color(chanx_color);
ezgl::rectangle bb({draw_coords->tile_x[x], draw_coords->tile_y[y] + 1 * tile_height},
{draw_coords->tile_x[x] + 1 * tile_width, draw_coords->tile_y[y + 1]});
- g.fill_rectangle(bb);
+ g->fill_rectangle(bb);
- g.set_color(ezgl::BLACK);
+ g->set_color(ezgl::BLACK);
if (draw_state->show_routing_util == DRAW_ROUTING_UTIL_WITH_VALUE) {
- g.draw_text(bb.center(), vtr::string_fmt("%.2f", chanx_util).c_str(), bb.width(), bb.height());
+ g->draw_text(bb.center(), vtr::string_fmt("%.2f", chanx_util).c_str(), bb.width(), bb.height());
} else if (draw_state->show_routing_util == DRAW_ROUTING_UTIL_WITH_FORMULA) {
- g.draw_text(bb.center(), vtr::string_fmt("%.2f = %.0f / %.0f", chanx_util, chanx_usage[x][y], chanx_avail[x][y]).c_str(), bb.width(), bb.height());
+ g->draw_text(bb.center(), vtr::string_fmt("%.2f = %.0f / %.0f", chanx_util, chanx_usage[x][y], chanx_avail[x][y]).c_str(), bb.width(), bb.height());
}
sb_util += chanx_util;
@@ -3408,16 +3421,16 @@
chany_util = routing_util(chany_usage[x][y], chany_avail[x][y]);
ezgl::color chany_color = to_ezgl_color(cmap->color(chany_util));
chany_color.alpha *= ALPHA;
- g.set_color(chany_color);
+ g->set_color(chany_color);
ezgl::rectangle bb({draw_coords->tile_x[x] + 1 * tile_width, draw_coords->tile_y[y]},
{draw_coords->tile_x[x + 1], draw_coords->tile_y[y] + 1 * tile_height});
- g.fill_rectangle(bb);
+ g->fill_rectangle(bb);
- g.set_color(ezgl::BLACK);
+ g->set_color(ezgl::BLACK);
if (draw_state->show_routing_util == DRAW_ROUTING_UTIL_WITH_VALUE) {
- g.draw_text(bb.center(), vtr::string_fmt("%.2f", chany_util).c_str(), bb.width(), bb.height());
+ g->draw_text(bb.center(), vtr::string_fmt("%.2f", chany_util).c_str(), bb.width(), bb.height());
} else if (draw_state->show_routing_util == DRAW_ROUTING_UTIL_WITH_FORMULA) {
- g.draw_text(bb.center(), vtr::string_fmt("%.2f = %.0f / %.0f", chany_util, chany_usage[x][y], chany_avail[x][y]).c_str(), bb.width(), bb.height());
+ g->draw_text(bb.center(), vtr::string_fmt("%.2f = %.0f / %.0f", chany_util, chany_usage[x][y], chany_avail[x][y]).c_str(), bb.width(), bb.height());
}
sb_util += chany_util;
@@ -3435,23 +3448,23 @@
sb_util /= chan_count;
ezgl::color sb_color = to_ezgl_color(cmap->color(sb_util));
sb_color.alpha *= ALPHA;
- g.set_color(sb_color);
+ g->set_color(sb_color);
ezgl::rectangle bb({draw_coords->tile_x[x] + 1 * tile_width, draw_coords->tile_y[y] + 1 * tile_height},
{draw_coords->tile_x[x + 1], draw_coords->tile_y[y + 1]});
- g.fill_rectangle(bb);
+ g->fill_rectangle(bb);
//Draw over blocks
if (draw_state->show_routing_util == DRAW_ROUTING_UTIL_OVER_BLOCKS) {
if (x < device_ctx.grid.width() - 2 && y < device_ctx.grid.height() - 2) {
ezgl::rectangle bb2({draw_coords->tile_x[x + 1], draw_coords->tile_y[y + 1]},
{draw_coords->tile_x[x + 1] + 1 * tile_width, draw_coords->tile_y[y + 1] + 1 * tile_width});
- g.fill_rectangle(bb2);
+ g->fill_rectangle(bb2);
}
}
- g.set_color(ezgl::BLACK);
+ g->set_color(ezgl::BLACK);
if (draw_state->show_routing_util == DRAW_ROUTING_UTIL_WITH_VALUE
|| draw_state->show_routing_util == DRAW_ROUTING_UTIL_WITH_FORMULA) {
- g.draw_text(bb.center(), vtr::string_fmt("%.2f", sb_util).c_str(), bb.width(), bb.height());
+ g->draw_text(bb.center(), vtr::string_fmt("%.2f", sb_util).c_str(), bb.width(), bb.height());
}
}
}
@@ -3471,7 +3484,7 @@
VPR_THROW(VPR_ERROR_DRAW, "Invalid Router RR cost drawing type");
}
-static void draw_router_rr_costs(ezgl::renderer& g) {
+static void draw_router_rr_costs(ezgl::renderer* g) {
t_draw_state* draw_state = get_draw_state_vars();
if (draw_state->show_router_rr_cost == DRAW_NO_ROUTER_RR_COST) {
return;
@@ -3509,14 +3522,14 @@
}
}
-static void draw_rr_costs(ezgl::renderer& g, const std::vector<float>& rr_costs, bool lowest_cost_first) {
+static void draw_rr_costs(ezgl::renderer* g, const std::vector<float>& rr_costs, bool lowest_cost_first) {
t_draw_state* draw_state = get_draw_state_vars();
/* Draws routing costs */
auto& device_ctx = g_vpr_ctx.device();
- g.set_line_width(0);
+ g->set_line_width(0);
VTR_ASSERT(rr_costs.size() == device_ctx.rr_nodes.size());
@@ -3533,7 +3546,7 @@
std::unique_ptr<vtr::ColorMap> cmap = std::make_unique<vtr::PlasmaColorMap>(min_cost, max_cost);
//Draw the nodes in ascending order of value, this ensures high valued nodes
- //are not overdrawn by lower value ones (e.g. when zoomed-out far)
+ //are not overdrawn by lower value ones (e.g-> when zoomed-out far)
std::vector<int> nodes(device_ctx.rr_nodes.size());
std::iota(nodes.begin(), nodes.end(), 0);
auto cmp_ascending_cost = [&](int lhs_node, int rhs_node) {
@@ -3577,7 +3590,7 @@
draw_state->color_map = std::move(cmap);
}
-static void draw_placement_macros(ezgl::renderer& g) {
+static void draw_placement_macros(ezgl::renderer* g) {
t_draw_state* draw_state = get_draw_state_vars();
if (draw_state->show_placement_macros == DRAW_NO_PLACEMENT_MACROS) {
@@ -3621,13 +3634,13 @@
double draw_xhigh = draw_coords->tile_x[xhigh];
double draw_yhigh = draw_coords->tile_y[yhigh];
- g.set_color(blk_RED);
- g.draw_rectangle({draw_xlow, draw_ylow}, {draw_xhigh, draw_yhigh});
+ g->set_color(blk_RED);
+ g->draw_rectangle({draw_xlow, draw_ylow}, {draw_xhigh, draw_yhigh});
ezgl::color fill = blk_SKYBLUE;
fill.alpha *= 0.3;
- g.set_color(fill);
- g.fill_rectangle({draw_xlow, draw_ylow}, {draw_xhigh, draw_yhigh});
+ g->set_color(fill);
+ g->fill_rectangle({draw_xlow, draw_ylow}, {draw_xhigh, draw_yhigh});
}
}
@@ -3710,6 +3723,16 @@
// Connect press_zoom_fit function to the Zoom-fit button
GObject* zoom_fit_button = app->get_object("ZoomFitButton");
g_signal_connect(zoom_fit_button, "clicked", G_CALLBACK(ezgl::press_zoom_fit), app);
+
+ // Connect Pause button
+ GObject* pause_button = app->get_object("PauseButton");
+ g_signal_connect(pause_button, "clicked", G_CALLBACK(set_force_pause), app);
+}
+
+void set_force_pause(GtkWidget* /*widget*/, gint /*response_id*/, gpointer /*data*/) {
+ t_draw_state* draw_state = get_draw_state_vars();
+
+ draw_state->forced_pause = true;
}
#endif /* NO_GRAPHICS */
diff --git a/vpr/src/draw/draw.h b/vpr/src/draw/draw.h
index e161f50..eb8dd4c 100644
--- a/vpr/src/draw/draw.h
+++ b/vpr/src/draw/draw.h
@@ -34,9 +34,9 @@
void draw_get_rr_pin_coords(int inode, float* xcen, float* ycen);
void draw_get_rr_pin_coords(const t_rr_node* node, float* xcen, float* ycen);
-void draw_triangle_along_line(ezgl::renderer& g, ezgl::point2d start, ezgl::point2d end, float relative_position = 1., float arrow_size = DEFAULT_ARROW_SIZE);
-void draw_triangle_along_line(ezgl::renderer& g, ezgl::point2d loc, ezgl::point2d start, ezgl::point2d end, float arrow_size = DEFAULT_ARROW_SIZE);
-void draw_triangle_along_line(ezgl::renderer& g, float xend, float yend, float x1, float x2, float y1, float y2, float arrow_size = DEFAULT_ARROW_SIZE);
+void draw_triangle_along_line(ezgl::renderer* g, ezgl::point2d start, ezgl::point2d end, float relative_position = 1., float arrow_size = DEFAULT_ARROW_SIZE);
+void draw_triangle_along_line(ezgl::renderer* g, ezgl::point2d loc, ezgl::point2d start, ezgl::point2d end, float arrow_size = DEFAULT_ARROW_SIZE);
+void draw_triangle_along_line(ezgl::renderer* g, float xend, float yend, float x1, float x2, float y1, float y2, float arrow_size = DEFAULT_ARROW_SIZE);
const ezgl::color SELECTED_COLOR = ezgl::GREEN;
const ezgl::color DRIVES_IT_COLOR = ezgl::RED;
diff --git a/vpr/src/draw/draw_types.h b/vpr/src/draw/draw_types.h
index 522c63d..f6e507a 100644
--- a/vpr/src/draw/draw_types.h
+++ b/vpr/src/draw/draw_types.h
@@ -178,6 +178,7 @@
const t_arch* arch_info = nullptr;
std::unique_ptr<const vtr::ColorMap> color_map = nullptr;
bool save_graphics = false;
+ bool forced_pause = false;
t_draw_state() = default;
diff --git a/vpr/src/draw/intra_logic_block.cpp b/vpr/src/draw/intra_logic_block.cpp
index 62a5999..40eb8aa 100644
--- a/vpr/src/draw/intra_logic_block.cpp
+++ b/vpr/src/draw/intra_logic_block.cpp
@@ -2,10 +2,10 @@
* The four main subroutines defined here are draw_internal_alloc_blk(),
* draw_internal_init_blk(), draw_internal_draw_subblk(), and toggle_blk_internal().
* When VPR graphics initially sets up, draw_internal_alloc_blk() will be called from
- * draw.c to allocate space for the structures needed for internal blks drawing.
+ * draw.c to allocate space for the structures needed for internal blks drawing->
* Before any drawing, draw_internal_init_blk() will pre-compute a bounding box
* for each sub-block in the pb_graph of every physical block type. When the menu button
- * "Blk Internal" is pressed, toggle_blk_internal() will enable internal blocks drawing.
+ * "Blk Internal" is pressed, toggle_blk_internal() will enable internal blocks drawing->
* Then, with each subsequent click on the button, toggle_blk_internal() will propel one
* more level of pbs to be drawn. Draw_internal_draw_subblk() will be called whenever
* new blocks need to be drawn, and this function is responsible for drawing sub-blocks
@@ -27,8 +27,6 @@
# include "vtr_assert.h"
# include "vtr_memory.h"
-using namespace std;
-
# include "intra_logic_block.h"
# include "globals.h"
# include "atom_netlist.h"
@@ -48,10 +46,10 @@
t_pb* highlight_sub_block_helper(const ClusterBlockId clb_index, t_pb* pb, const ezgl::point2d& local_pt, int max_depth);
# ifndef NO_GRAPHICS
-static void draw_internal_pb(const ClusterBlockId clb_index, t_pb* pb, const ezgl::rectangle& parent_bbox, const t_logical_block_type_ptr type, ezgl::renderer& g);
-void draw_atoms_fanin_fanout_flylines(const std::vector<AtomBlockId>& atoms, ezgl::renderer& g);
-void draw_selected_pb_flylines(ezgl::renderer& g);
-void draw_one_logical_connection(const AtomPinId src_pin, const AtomPinId sink_pin, ezgl::renderer& g);
+static void draw_internal_pb(const ClusterBlockId clb_index, t_pb* pb, const ezgl::rectangle& parent_bbox, const t_logical_block_type_ptr type, ezgl::renderer* g);
+void draw_atoms_fanin_fanout_flylines(const std::vector<AtomBlockId>& atoms, ezgl::renderer* g);
+void draw_selected_pb_flylines(ezgl::renderer* g);
+void draw_one_logical_connection(const AtomPinId src_pin, const AtomPinId sink_pin, ezgl::renderer* g);
# endif /* NO_GRAPHICS */
/************************* Subroutine definitions begin *********************************/
@@ -131,13 +129,13 @@
clb_bbox.width(), clb_bbox.height());
/* Determine the max number of sub_block levels in the FPGA */
- draw_state->max_sub_blk_lvl = max(draw_internal_find_max_lvl(*logical_block_type(&type)->pb_type),
- draw_state->max_sub_blk_lvl);
+ draw_state->max_sub_blk_lvl = std::max(draw_internal_find_max_lvl(*logical_block_type(&type)->pb_type),
+ draw_state->max_sub_blk_lvl);
}
}
# ifndef NO_GRAPHICS
-void draw_internal_draw_subblk(ezgl::renderer& g) {
+void draw_internal_draw_subblk(ezgl::renderer* g) {
t_draw_state* draw_state = get_draw_state_vars();
if (!draw_state->show_blk_internal) {
return;
@@ -193,7 +191,7 @@
mode = pb_type.modes[i];
for (j = 0; j < mode.num_pb_type_children; ++j) {
- max_levels = max(draw_internal_find_max_lvl(mode.pb_type_children[j]), max_levels);
+ max_levels = std::max(draw_internal_find_max_lvl(mode.pb_type_children[j]), max_levels);
}
}
return max_levels;
@@ -318,7 +316,7 @@
* which a netlist block can map to, and draws each sub-block inside its parent block. With
* each click on the "Blk Internal" button, a new level is shown.
*/
-static void draw_internal_pb(const ClusterBlockId clb_index, t_pb* pb, const ezgl::rectangle& parent_bbox, const t_logical_block_type_ptr type, ezgl::renderer& g) {
+static void draw_internal_pb(const ClusterBlockId clb_index, t_pb* pb, const ezgl::rectangle& parent_bbox, const t_logical_block_type_ptr type, ezgl::renderer* g) {
t_draw_coords* draw_coords = get_draw_coords_vars();
t_draw_state* draw_state = get_draw_state_vars();
t_selected_sub_block_info& sel_sub_info = get_selected_sub_block_info();
@@ -338,52 +336,52 @@
// if this is a top level pb, and only if it isn't selected (ie. a funny colour),
// overwrite it. (but stil draw the text)
- g.set_color(ezgl::WHITE);
- g.fill_rectangle(abs_bbox);
- g.set_color(ezgl::BLACK);
- g.set_line_dash(ezgl::line_dash::none);
- g.draw_rectangle(abs_bbox);
+ g->set_color(ezgl::WHITE);
+ g->fill_rectangle(abs_bbox);
+ g->set_color(ezgl::BLACK);
+ g->set_line_dash(ezgl::line_dash::none);
+ g->draw_rectangle(abs_bbox);
}
} else {
if (pb->name != nullptr) {
// If block is used, draw it in colour with solid border.
- g.set_line_dash(ezgl::line_dash::none);
+ g->set_line_dash(ezgl::line_dash::none);
// type_index indicates what type of block.
const int type_index = type->index;
// determine default background color
if (sel_sub_info.is_selected(pb->pb_graph_node, clb_index)) {
- g.set_color(SELECTED_COLOR);
+ g->set_color(SELECTED_COLOR);
} else if (sel_sub_info.is_sink_of_selected(pb->pb_graph_node, clb_index)) {
- g.set_color(DRIVES_IT_COLOR);
+ g->set_color(DRIVES_IT_COLOR);
} else if (sel_sub_info.is_source_of_selected(pb->pb_graph_node, clb_index)) {
- g.set_color(DRIVEN_BY_IT_COLOR);
+ g->set_color(DRIVEN_BY_IT_COLOR);
} else if (pb_type->depth != draw_state->show_blk_internal && pb->child_pbs != nullptr) {
- g.set_color(ezgl::WHITE); // draw anything else that will have a child as white
+ g->set_color(ezgl::WHITE); // draw anything else that will have a child as white
} else if (type_index < 3) {
- g.set_color(blk_LIGHTGREY);
+ g->set_color(blk_LIGHTGREY);
} else if (type_index < 3 + MAX_BLOCK_COLOURS) {
- g.set_color((block_colors[MAX_BLOCK_COLOURS + type_index - 3]));
+ g->set_color((block_colors[MAX_BLOCK_COLOURS + type_index - 3]));
} else {
- g.set_color((block_colors[2 * MAX_BLOCK_COLOURS - 1]));
+ g->set_color((block_colors[2 * MAX_BLOCK_COLOURS - 1]));
}
} else {
// If block is not used, draw as empty block (ie. white
// background with dashed border).
- g.set_line_dash(ezgl::line_dash::asymmetric_5_3);
- g.set_color(ezgl::WHITE);
+ g->set_line_dash(ezgl::line_dash::asymmetric_5_3);
+ g->set_color(ezgl::WHITE);
}
- g.fill_rectangle(abs_bbox);
- g.set_color(ezgl::BLACK);
- g.draw_rectangle(abs_bbox);
+ g->fill_rectangle(abs_bbox);
+ g->set_color(ezgl::BLACK);
+ g->draw_rectangle(abs_bbox);
}
/// then draw text ///
if (pb->name != nullptr) {
- g.set_font_size(16); // note: calc_text_xbound(...) assumes this is 16
+ g->set_font_size(16); // note: calc_text_xbound(...) assumes this is 16
if (pb_type->depth == draw_state->show_blk_internal || pb->child_pbs == nullptr) {
// If this pb is at the lowest displayed level, or has no more children, then
// label it in the center with its type and name
@@ -395,7 +393,7 @@
sprintf(blk_tag, "%s(%s)", pb_type->name, pb->name);
- g.draw_text(
+ g->draw_text(
abs_bbox.center(),
blk_tag,
abs_bbox.width(),
@@ -405,7 +403,7 @@
} else {
// else (ie. has chilren, and isn't at the lowest displayed level)
// just label its type, and put it up at the top so we can see it
- g.draw_text(
+ g->draw_text(
ezgl::point2d(abs_bbox.center_x(),
abs_bbox.top() - (abs_bbox.height()) / 15.0),
pb_type->name,
@@ -414,7 +412,7 @@
}
} else {
// If child block is not used, label it only by its type
- g.draw_text(
+ g->draw_text(
abs_bbox.center(),
pb_type->name,
abs_bbox.width(),
@@ -454,7 +452,7 @@
}
}
-void draw_selected_pb_flylines(ezgl::renderer& g) {
+void draw_selected_pb_flylines(ezgl::renderer* g) {
t_selected_sub_block_info& sel_sub_info = get_selected_sub_block_info();
const t_pb* pb = sel_sub_info.get_selected_pb();
@@ -465,13 +463,13 @@
}
}
-void draw_atoms_fanin_fanout_flylines(const std::vector<AtomBlockId>& atoms, ezgl::renderer& g) {
+void draw_atoms_fanin_fanout_flylines(const std::vector<AtomBlockId>& atoms, ezgl::renderer* g) {
std::set<AtomBlockId> atoms_set(atoms.begin(), atoms.end());
auto& atom_nl = g_vpr_ctx.atom().nlist;
- g.set_line_dash(ezgl::line_dash::none);
- g.set_line_width(2);
+ g->set_line_dash(ezgl::line_dash::none);
+ g->set_line_width(2);
for (AtomBlockId blk : atoms) {
for (AtomPinId ipin : atom_nl.block_input_pins(blk)) {
@@ -481,14 +479,14 @@
AtomBlockId net_driver_blk = atom_nl.pin_block(net_driver);
if (atoms_set.count(net_driver_blk)) {
- g.set_color(ezgl::ORANGE); //Internal
+ g->set_color(ezgl::ORANGE); //Internal
} else {
- g.set_color(ezgl::BLUE); //External input
+ g->set_color(ezgl::BLUE); //External input
}
ezgl::point2d start = atom_pin_draw_coord(net_driver);
ezgl::point2d end = atom_pin_draw_coord(ipin);
- g.draw_line(start, end);
+ g->draw_line(start, end);
draw_triangle_along_line(g, start, end, 0.95, 40 * DEFAULT_ARROW_SIZE);
draw_triangle_along_line(g, start, end, 0.05, 40 * DEFAULT_ARROW_SIZE);
}
@@ -500,14 +498,14 @@
AtomBlockId net_sink_blk = atom_nl.pin_block(net_sink);
if (atoms_set.count(net_sink_blk)) {
- g.set_color(ezgl::ORANGE); //Internal
+ g->set_color(ezgl::ORANGE); //Internal
} else {
- g.set_color(ezgl::RED); //External output
+ g->set_color(ezgl::RED); //External output
}
ezgl::point2d start = atom_pin_draw_coord(opin);
ezgl::point2d end = atom_pin_draw_coord(net_sink);
- g.draw_line(start, end);
+ g->draw_line(start, end);
draw_triangle_along_line(g, start, end, 0.95, 40 * DEFAULT_ARROW_SIZE);
draw_triangle_along_line(g, start, end, 0.05, 40 * DEFAULT_ARROW_SIZE);
}
@@ -544,13 +542,13 @@
}
# ifndef NO_GRAPHICS
-void draw_logical_connections(ezgl::renderer& g) {
+void draw_logical_connections(ezgl::renderer* g) {
const t_selected_sub_block_info& sel_subblk_info = get_selected_sub_block_info();
t_draw_state* draw_state = get_draw_state_vars();
auto& atom_ctx = g_vpr_ctx.atom();
- g.set_line_dash(ezgl::line_dash::none);
+ g->set_line_dash(ezgl::line_dash::none);
// iterate over all the atom nets
for (auto net_id : atom_ctx.nlist.nets()) {
@@ -568,11 +566,11 @@
ClusterBlockId sink_clb = atom_ctx.lookup.atom_clb(sink_blk_id);
if (src_is_selected && sel_subblk_info.is_sink_of_selected(sink_pb_gnode, sink_clb)) {
- g.set_color(DRIVES_IT_COLOR);
+ g->set_color(DRIVES_IT_COLOR);
} else if (src_is_src_of_selected && sel_subblk_info.is_in_selected_subtree(sink_pb_gnode, sink_clb)) {
- g.set_color(DRIVEN_BY_IT_COLOR);
+ g->set_color(DRIVEN_BY_IT_COLOR);
} else if (draw_state->show_nets == DRAW_LOGICAL_CONNECTIONS && (draw_state->showing_sub_blocks() || src_clb != sink_clb)) {
- g.set_color(ezgl::BLACK); // if showing all, draw the other ones in black
+ g->set_color(ezgl::BLACK); // if showing all, draw the other ones in black
} else {
continue; // not showing all, and not the sperified block, so skip
}
@@ -637,12 +635,12 @@
* The *_abs_bbox parameters are for mild optmization, as the absolute bbox can be calculated
* more effeciently elsewhere.
*/
-void draw_one_logical_connection(const AtomPinId src_pin, const AtomPinId sink_pin, ezgl::renderer& g) {
+void draw_one_logical_connection(const AtomPinId src_pin, const AtomPinId sink_pin, ezgl::renderer* g) {
ezgl::point2d src_point = atom_pin_draw_coord(src_pin);
ezgl::point2d sink_point = atom_pin_draw_coord(sink_pin);
// draw a link connecting the pins.
- g.draw_line(src_point, sink_point);
+ g->draw_line(src_point, sink_point);
auto& atom_ctx = g_vpr_ctx.atom();
if (atom_ctx.lookup.atom_clb(atom_ctx.nlist.pin_block(src_pin)) == atom_ctx.lookup.atom_clb(atom_ctx.nlist.pin_block(sink_pin))) {
diff --git a/vpr/src/draw/intra_logic_block.h b/vpr/src/draw/intra_logic_block.h
index dff491e..0cc0788 100644
--- a/vpr/src/draw/intra_logic_block.h
+++ b/vpr/src/draw/intra_logic_block.h
@@ -114,7 +114,7 @@
* grid tiles and calls helper function to draw inside each block.
*/
# ifndef NO_GRAPHICS
-void draw_internal_draw_subblk(ezgl::renderer& g);
+void draw_internal_draw_subblk(ezgl::renderer* g);
# endif /* NO_GRAPHICS */
/* Determines which part of a block to highlight, and stores it,
@@ -134,7 +134,7 @@
* and if there is a selected sub-block, it will highlight it's conections
*/
-void draw_logical_connections(ezgl::renderer& g);
+void draw_logical_connections(ezgl::renderer* g);
void find_pin_index_at_model_scope(const AtomPinId the_pin, const AtomBlockId lblk, int* pin_index, int* total_pins);
diff --git a/vpr/src/draw/save_graphics.cpp b/vpr/src/draw/save_graphics.cpp
index 0cbfe30..f8c91e8 100644
--- a/vpr/src/draw/save_graphics.cpp
+++ b/vpr/src/draw/save_graphics.cpp
@@ -2,7 +2,6 @@
# include <cstdio>
# include <sstream>
-using namespace std;
# include "globals.h"
# include "draw.h"
@@ -130,4 +129,4 @@
return;
}
-#endif /* NO_GRAPHICS */
\ No newline at end of file
+#endif /* NO_GRAPHICS */
diff --git a/vpr/src/draw/search_bar.cpp b/vpr/src/draw/search_bar.cpp
index c6fbaf7..aaa591c 100644
--- a/vpr/src/draw/search_bar.cpp
+++ b/vpr/src/draw/search_bar.cpp
@@ -2,7 +2,6 @@
# include <cstdio>
# include <sstream>
-using namespace std;
# include "vtr_assert.h"
# include "vtr_ndoffsetmatrix.h"
diff --git a/vpr/src/main.cpp b/vpr/src/main.cpp
index 57b56a0..4ab2fed 100644
--- a/vpr/src/main.cpp
+++ b/vpr/src/main.cpp
@@ -13,7 +13,6 @@
#include <cstdio>
#include <cstring>
#include <ctime>
-using namespace std;
#include "vtr_error.h"
#include "vtr_memory.h"
diff --git a/vpr/src/pack/cluster.cpp b/vpr/src/pack/cluster.cpp
index 7235243..2008635 100644
--- a/vpr/src/pack/cluster.cpp
+++ b/vpr/src/pack/cluster.cpp
@@ -40,7 +40,6 @@
#include <map>
#include <algorithm>
#include <fstream>
-using namespace std;
#include "vtr_assert.h"
#include "vtr_log.h"
@@ -152,7 +151,7 @@
static bool is_atom_blk_in_pb(const AtomBlockId blk_id, const t_pb* pb);
static void add_molecule_to_pb_stats_candidates(t_pack_molecule* molecule,
- map<AtomBlockId, float>& gain,
+ std::map<AtomBlockId, float>& gain,
t_pb* pb,
int max_queue_size);
@@ -254,7 +253,7 @@
const int max_cluster_size,
const t_arch* arch,
std::string device_layout_name,
- vector<t_lb_type_rr_node>* lb_type_rr_graphs,
+ std::vector<t_lb_type_rr_node>* lb_type_rr_graphs,
t_lb_router_data** router_data,
const int detailed_routing_stage,
ClusteredNetlist* clb_nlist,
@@ -323,7 +322,7 @@
static t_pack_molecule* get_highest_gain_seed_molecule(int* seedindex, const std::multimap<AtomBlockId, t_pack_molecule*>& atom_molecules, const std::vector<AtomBlockId> seed_atoms);
-static float get_molecule_gain(t_pack_molecule* molecule, map<AtomBlockId, float>& blk_gain);
+static float get_molecule_gain(t_pack_molecule* molecule, std::map<AtomBlockId, float>& blk_gain);
static int compare_molecule_gain(const void* a, const void* b);
int net_sinks_reachable_in_cluster(const t_pb_graph_pin* driver_pb_gpin, const int depth, const AtomNetId net_id);
@@ -811,7 +810,7 @@
/* Add blk to list of feasible blocks sorted according to gain */
static void add_molecule_to_pb_stats_candidates(t_pack_molecule* molecule,
- map<AtomBlockId, float>& gain,
+ std::map<AtomBlockId, float>& gain,
t_pb* pb,
int max_queue_size) {
int i, j;
@@ -1932,7 +1931,7 @@
const int max_cluster_size,
const t_arch* arch,
std::string device_layout_name,
- vector<t_lb_type_rr_node>* lb_type_rr_graphs,
+ std::vector<t_lb_type_rr_node>* lb_type_rr_graphs,
t_lb_router_data** router_data,
const int detailed_routing_stage,
ClusteredNetlist* clb_nlist,
@@ -2213,7 +2212,7 @@
}
if (success) {
add_molecule_to_pb_stats_candidates(molecule,
- cur_pb->pb_stats->gain, cur_pb, min(feasible_block_array_size, AAPACK_MAX_HIGH_FANOUT_EXPLORE));
+ cur_pb->pb_stats->gain, cur_pb, std::min(feasible_block_array_size, AAPACK_MAX_HIGH_FANOUT_EXPLORE));
count++;
}
}
@@ -2261,7 +2260,7 @@
}
if (success) {
add_molecule_to_pb_stats_candidates(molecule,
- cur_pb->pb_stats->gain, cur_pb, min(feasible_block_array_size, AAPACK_MAX_TRANSITIVE_EXPLORE));
+ cur_pb->pb_stats->gain, cur_pb, std::min(feasible_block_array_size, AAPACK_MAX_TRANSITIVE_EXPLORE));
}
}
}
@@ -2723,7 +2722,7 @@
* + molecule_base_gain*some_factor
* - introduced_input_nets_of_unrelated_blocks_pulled_in_by_molecule*some_other_factor
*/
-static float get_molecule_gain(t_pack_molecule* molecule, map<AtomBlockId, float>& blk_gain) {
+static float get_molecule_gain(t_pack_molecule* molecule, std::map<AtomBlockId, float>& blk_gain) {
float gain;
int i;
int num_introduced_inputs_of_indirectly_related_block;
diff --git a/vpr/src/pack/cluster_placement.cpp b/vpr/src/pack/cluster_placement.cpp
index 8958251..807908f 100644
--- a/vpr/src/pack/cluster_placement.cpp
+++ b/vpr/src/pack/cluster_placement.cpp
@@ -14,7 +14,6 @@
#include <cstdio>
#include <cstring>
-using namespace std;
#include "vtr_assert.h"
#include "vtr_memory.h"
diff --git a/vpr/src/pack/cluster_router.cpp b/vpr/src/pack/cluster_router.cpp
index 94f84ef..d946910 100644
--- a/vpr/src/pack/cluster_router.cpp
+++ b/vpr/src/pack/cluster_router.cpp
@@ -18,7 +18,6 @@
#include <map>
#include <queue>
#include <cmath>
-using namespace std;
#include "vtr_assert.h"
#include "vtr_log.h"
@@ -50,9 +49,9 @@
* allows me to use a priority queue where I can pre-allocate the # of elements in the underlying container
* for efficiency reasons. Note: Must use vector with this */
template<class T, class U, class V>
-class reservable_pq : public priority_queue<T, U, V> {
+class reservable_pq : public std::priority_queue<T, U, V> {
public:
- typedef typename priority_queue<T>::size_type size_type;
+ typedef typename std::priority_queue<T>::size_type size_type;
reservable_pq(size_type capacity = 0) {
reserve(capacity);
cur_cap = capacity;
@@ -83,12 +82,12 @@
static void commit_remove_rt(t_lb_trace* rt, t_lb_router_data* router_data, e_commit_remove op, std::unordered_map<const t_pb_graph_node*, const t_mode*>* mode_map, t_mode_selection_status* mode_status);
static bool is_skip_route_net(t_lb_trace* rt, t_lb_router_data* router_data);
static void add_source_to_rt(t_lb_router_data* router_data, int inet);
-static void expand_rt(t_lb_router_data* router_data, int inet, reservable_pq<t_expansion_node, vector<t_expansion_node>, compare_expansion_node>& pq, int irt_net);
-static void expand_rt_rec(t_lb_trace* rt, int prev_index, t_explored_node_tb* explored_node_tb, reservable_pq<t_expansion_node, vector<t_expansion_node>, compare_expansion_node>& pq, int irt_net, int explore_id_index);
+static void expand_rt(t_lb_router_data* router_data, int inet, reservable_pq<t_expansion_node, std::vector<t_expansion_node>, compare_expansion_node>& pq, int irt_net);
+static void expand_rt_rec(t_lb_trace* rt, int prev_index, t_explored_node_tb* explored_node_tb, reservable_pq<t_expansion_node, std::vector<t_expansion_node>, compare_expansion_node>& pq, int irt_net, int explore_id_index);
static bool try_expand_nodes(t_lb_router_data* router_data,
t_intra_lb_net* lb_net,
t_expansion_node* exp_node,
- reservable_pq<t_expansion_node, vector<t_expansion_node>, compare_expansion_node>& pq,
+ reservable_pq<t_expansion_node, std::vector<t_expansion_node>, compare_expansion_node>& pq,
int itarget,
bool try_other_modes,
int verbosity);
@@ -98,10 +97,10 @@
int cur_inode,
float cur_cost,
int net_fanout,
- reservable_pq<t_expansion_node, vector<t_expansion_node>, compare_expansion_node>& pq);
+ reservable_pq<t_expansion_node, std::vector<t_expansion_node>, compare_expansion_node>& pq);
-static void expand_node(t_lb_router_data* router_data, t_expansion_node exp_node, reservable_pq<t_expansion_node, vector<t_expansion_node>, compare_expansion_node>& pq, int net_fanout);
-static void expand_node_all_modes(t_lb_router_data* router_data, t_expansion_node exp_node, reservable_pq<t_expansion_node, vector<t_expansion_node>, compare_expansion_node>& pq, int net_fanout);
+static void expand_node(t_lb_router_data* router_data, t_expansion_node exp_node, reservable_pq<t_expansion_node, std::vector<t_expansion_node>, compare_expansion_node>& pq, int net_fanout);
+static void expand_node_all_modes(t_lb_router_data* router_data, t_expansion_node exp_node, reservable_pq<t_expansion_node, std::vector<t_expansion_node>, compare_expansion_node>& pq, int net_fanout);
static bool add_to_rt(t_lb_trace* rt, int node_index, t_lb_router_data* router_data, int irt_net);
static bool is_route_success(t_lb_router_data* router_data);
@@ -134,7 +133,7 @@
/**
* Build data structures used by intra-logic block router
*/
-t_lb_router_data* alloc_and_load_router_data(vector<t_lb_type_rr_node>* lb_type_graph, t_logical_block_type_ptr type) {
+t_lb_router_data* alloc_and_load_router_data(std::vector<t_lb_type_rr_node>* lb_type_graph, t_logical_block_type_ptr type) {
t_lb_router_data* router_data = new t_lb_router_data;
int size;
@@ -142,8 +141,8 @@
size = router_data->lb_type_graph->size();
router_data->lb_rr_node_stats = new t_lb_rr_node_stats[size];
router_data->explored_node_tb = new t_explored_node_tb[size];
- router_data->intra_lb_nets = new vector<t_intra_lb_net>;
- router_data->atoms_added = new map<AtomBlockId, bool>;
+ router_data->intra_lb_nets = new std::vector<t_intra_lb_net>;
+ router_data->atoms_added = new std::map<AtomBlockId, bool>;
router_data->lb_type = type;
return router_data;
@@ -167,7 +166,7 @@
}
static bool route_has_conflict(t_lb_trace* rt, t_lb_router_data* router_data) {
- vector<t_lb_type_rr_node>& lb_type_graph = *router_data->lb_type_graph;
+ std::vector<t_lb_type_rr_node>& lb_type_graph = *router_data->lb_type_graph;
int cur_mode = -1;
for (unsigned int i = 0; i < rt->next_nodes.size(); i++) {
@@ -269,7 +268,7 @@
void remove_atom_from_target(t_lb_router_data* router_data, const AtomBlockId blk_id) {
auto& atom_ctx = g_vpr_ctx.atom();
- map<AtomBlockId, bool>& atoms_added = *router_data->atoms_added;
+ std::map<AtomBlockId, bool>& atoms_added = *router_data->atoms_added;
const t_pb* pb = atom_ctx.lookup.atom_pb(blk_id);
@@ -335,7 +334,7 @@
static bool try_expand_nodes(t_lb_router_data* router_data,
t_intra_lb_net* lb_net,
t_expansion_node* exp_node,
- reservable_pq<t_expansion_node, vector<t_expansion_node>, compare_expansion_node>& pq,
+ reservable_pq<t_expansion_node, std::vector<t_expansion_node>, compare_expansion_node>& pq,
int itarget,
bool try_other_modes,
int verbosity) {
@@ -395,8 +394,8 @@
bool try_intra_lb_route(t_lb_router_data* router_data,
int verbosity,
t_mode_selection_status* mode_status) {
- vector<t_intra_lb_net>& lb_nets = *router_data->intra_lb_nets;
- vector<t_lb_type_rr_node>& lb_type_graph = *router_data->lb_type_graph;
+ std::vector<t_intra_lb_net>& lb_nets = *router_data->intra_lb_nets;
+ std::vector<t_lb_type_rr_node>& lb_type_graph = *router_data->lb_type_graph;
bool is_routed = false;
bool is_impossible = false;
@@ -406,7 +405,7 @@
t_expansion_node exp_node;
/* Stores state info during route */
- reservable_pq<t_expansion_node, vector<t_expansion_node>, compare_expansion_node> pq;
+ reservable_pq<t_expansion_node, std::vector<t_expansion_node>, compare_expansion_node> pq;
reset_explored_node_tb(router_data);
@@ -536,8 +535,8 @@
/* Creates an array [0..num_pb_graph_pins-1] lookup for intra-logic block routing. Given pb_graph_pin id for clb, lookup atom net that uses that pin.
* If pin is not used, stores OPEN at that pin location */
-t_pb_routes alloc_and_load_pb_route(const vector<t_intra_lb_net>* intra_lb_nets, t_pb_graph_node* pb_graph_head) {
- const vector<t_intra_lb_net>& lb_nets = *intra_lb_nets;
+t_pb_routes alloc_and_load_pb_route(const std::vector<t_intra_lb_net>* intra_lb_nets, t_pb_graph_node* pb_graph_head) {
+ const std::vector<t_intra_lb_net>& lb_nets = *intra_lb_nets;
int total_pins = pb_graph_head->total_pb_pins;
t_pb_routes pb_route;
@@ -555,11 +554,11 @@
}
}
-void free_intra_lb_nets(vector<t_intra_lb_net>* intra_lb_nets) {
+void free_intra_lb_nets(std::vector<t_intra_lb_net>* intra_lb_nets) {
if (intra_lb_nets == nullptr) {
return;
}
- vector<t_intra_lb_net>& lb_nets = *intra_lb_nets;
+ std::vector<t_intra_lb_net>& lb_nets = *intra_lb_nets;
for (unsigned int i = 0; i < lb_nets.size(); i++) {
lb_nets[i].terminals.clear();
free_lb_net_rt(lb_nets[i].rt_tree);
@@ -618,8 +617,8 @@
* Assumes that pin is not already assigned
*/
static void add_pin_to_rt_terminals(t_lb_router_data* router_data, const AtomPinId pin_id) {
- vector<t_intra_lb_net>& lb_nets = *router_data->intra_lb_nets;
- vector<t_lb_type_rr_node>& lb_type_graph = *router_data->lb_type_graph;
+ std::vector<t_intra_lb_net>& lb_nets = *router_data->intra_lb_nets;
+ std::vector<t_lb_type_rr_node>& lb_type_graph = *router_data->lb_type_graph;
t_logical_block_type_ptr lb_type = router_data->lb_type;
bool found = false;
unsigned int ipos;
@@ -785,8 +784,8 @@
/* Given a pin of a net, remove route tree terminals from it
*/
static void remove_pin_from_rt_terminals(t_lb_router_data* router_data, const AtomPinId pin_id) {
- vector<t_intra_lb_net>& lb_nets = *router_data->intra_lb_nets;
- vector<t_lb_type_rr_node>& lb_type_graph = *router_data->lb_type_graph;
+ std::vector<t_intra_lb_net>& lb_nets = *router_data->intra_lb_nets;
+ std::vector<t_lb_type_rr_node>& lb_type_graph = *router_data->lb_type_graph;
t_logical_block_type_ptr lb_type = router_data->lb_type;
bool found = false;
unsigned int ipos;
@@ -912,8 +911,8 @@
static void fix_duplicate_equivalent_pins(t_lb_router_data* router_data) {
auto& atom_ctx = g_vpr_ctx.atom();
- vector<t_lb_type_rr_node>& lb_type_graph = *router_data->lb_type_graph;
- vector<t_intra_lb_net>& lb_nets = *router_data->intra_lb_nets;
+ std::vector<t_lb_type_rr_node>& lb_type_graph = *router_data->lb_type_graph;
+ std::vector<t_intra_lb_net>& lb_nets = *router_data->intra_lb_nets;
for (size_t ilb_net = 0; ilb_net < lb_nets.size(); ++ilb_net) {
//Collect all the sink terminals indicies which target a particular node
@@ -967,7 +966,7 @@
static void commit_remove_rt(t_lb_trace* rt, t_lb_router_data* router_data, e_commit_remove op, std::unordered_map<const t_pb_graph_node*, const t_mode*>* mode_map, t_mode_selection_status* mode_status) {
t_lb_rr_node_stats* lb_rr_node_stats;
t_explored_node_tb* explored_node_tb;
- vector<t_lb_type_rr_node>& lb_type_graph = *router_data->lb_type_graph;
+ std::vector<t_lb_type_rr_node>& lb_type_graph = *router_data->lb_type_graph;
int inode;
int incr;
@@ -1018,7 +1017,7 @@
/* Should net be skipped? If the net does not conflict with another net, then skip routing this net */
static bool is_skip_route_net(t_lb_trace* rt, t_lb_router_data* router_data) {
t_lb_rr_node_stats* lb_rr_node_stats;
- vector<t_lb_type_rr_node>& lb_type_graph = *router_data->lb_type_graph;
+ std::vector<t_lb_type_rr_node>& lb_type_graph = *router_data->lb_type_graph;
int inode;
lb_rr_node_stats = router_data->lb_rr_node_stats;
@@ -1054,8 +1053,8 @@
}
/* Expand all nodes found in route tree into priority queue */
-static void expand_rt(t_lb_router_data* router_data, int inet, reservable_pq<t_expansion_node, vector<t_expansion_node>, compare_expansion_node>& pq, int irt_net) {
- vector<t_intra_lb_net>& lb_nets = *router_data->intra_lb_nets;
+static void expand_rt(t_lb_router_data* router_data, int inet, reservable_pq<t_expansion_node, std::vector<t_expansion_node>, compare_expansion_node>& pq, int irt_net) {
+ std::vector<t_intra_lb_net>& lb_nets = *router_data->intra_lb_nets;
VTR_ASSERT(pq.empty());
@@ -1063,7 +1062,7 @@
}
/* Expand all nodes found in route tree into priority queue recursively */
-static void expand_rt_rec(t_lb_trace* rt, int prev_index, t_explored_node_tb* explored_node_tb, reservable_pq<t_expansion_node, vector<t_expansion_node>, compare_expansion_node>& pq, int irt_net, int explore_id_index) {
+static void expand_rt_rec(t_lb_trace* rt, int prev_index, t_explored_node_tb* explored_node_tb, reservable_pq<t_expansion_node, std::vector<t_expansion_node>, compare_expansion_node>& pq, int irt_net, int explore_id_index) {
t_expansion_node enode;
/* Perhaps should use a cost other than zero */
@@ -1088,8 +1087,8 @@
int cur_inode,
float cur_cost,
int net_fanout,
- reservable_pq<t_expansion_node, vector<t_expansion_node>, compare_expansion_node>& pq) {
- vector<t_lb_type_rr_node>& lb_type_graph = *router_data->lb_type_graph;
+ reservable_pq<t_expansion_node, std::vector<t_expansion_node>, compare_expansion_node>& pq) {
+ std::vector<t_lb_type_rr_node>& lb_type_graph = *router_data->lb_type_graph;
t_lb_rr_node_stats* lb_rr_node_stats = router_data->lb_rr_node_stats;
t_lb_router_params params = router_data->params;
t_expansion_node enode;
@@ -1141,7 +1140,7 @@
}
/* Expand all nodes found in route tree into priority queue */
-static void expand_node(t_lb_router_data* router_data, t_expansion_node exp_node, reservable_pq<t_expansion_node, vector<t_expansion_node>, compare_expansion_node>& pq, int net_fanout) {
+static void expand_node(t_lb_router_data* router_data, t_expansion_node exp_node, reservable_pq<t_expansion_node, std::vector<t_expansion_node>, compare_expansion_node>& pq, int net_fanout) {
int cur_node;
float cur_cost;
int mode;
@@ -1159,8 +1158,8 @@
}
/* Expand all nodes using all possible modes found in route tree into priority queue */
-static void expand_node_all_modes(t_lb_router_data* router_data, t_expansion_node exp_node, reservable_pq<t_expansion_node, vector<t_expansion_node>, compare_expansion_node>& pq, int net_fanout) {
- vector<t_lb_type_rr_node>& lb_type_graph = *router_data->lb_type_graph;
+static void expand_node_all_modes(t_lb_router_data* router_data, t_expansion_node exp_node, reservable_pq<t_expansion_node, std::vector<t_expansion_node>, compare_expansion_node>& pq, int net_fanout) {
+ std::vector<t_lb_type_rr_node>& lb_type_graph = *router_data->lb_type_graph;
t_lb_rr_node_stats* lb_rr_node_stats = router_data->lb_rr_node_stats;
int cur_inode = exp_node.node_index;
@@ -1198,7 +1197,7 @@
/* Add new path from existing route tree to target sink */
static bool add_to_rt(t_lb_trace* rt, int node_index, t_lb_router_data* router_data, int irt_net) {
t_explored_node_tb* explored_node_tb = router_data->explored_node_tb;
- vector<int> trace_forward;
+ std::vector<int> trace_forward;
int rt_index, trace_index;
t_lb_trace* link_node;
t_lb_trace curr_node;
@@ -1232,7 +1231,7 @@
/* Determine if a completed route is valid. A successful route has no congestion (ie. no routing resource is used by two nets). */
static bool is_route_success(t_lb_router_data* router_data) {
- vector<t_lb_type_rr_node>& lb_type_graph = *router_data->lb_type_graph;
+ std::vector<t_lb_type_rr_node>& lb_type_graph = *router_data->lb_type_graph;
for (unsigned int inode = 0; inode < lb_type_graph.size(); inode++) {
if (router_data->lb_rr_node_stats[inode].occ > lb_type_graph[inode].capacity) {
@@ -1263,7 +1262,7 @@
/* Debug routine, print out current intra logic block route */
static void print_route(const char* filename, t_lb_router_data* router_data) {
FILE* fp;
- vector<t_lb_type_rr_node>& lb_type_graph = *router_data->lb_type_graph;
+ std::vector<t_lb_type_rr_node>& lb_type_graph = *router_data->lb_type_graph;
fp = fopen(filename, "w");
for (unsigned int inode = 0; inode < lb_type_graph.size(); inode++) {
@@ -1275,7 +1274,7 @@
}
static void print_route(FILE* fp, t_lb_router_data* router_data) {
- vector<t_intra_lb_net>& lb_nets = *router_data->intra_lb_nets;
+ std::vector<t_intra_lb_net>& lb_nets = *router_data->intra_lb_nets;
fprintf(fp, "\n\n----------------------------------------------------\n\n");
auto& atom_ctx = g_vpr_ctx.atom();
@@ -1310,7 +1309,7 @@
}
static void reset_explored_node_tb(t_lb_router_data* router_data) {
- vector<t_lb_type_rr_node>& lb_type_graph = *router_data->lb_type_graph;
+ std::vector<t_lb_type_rr_node>& lb_type_graph = *router_data->lb_type_graph;
for (unsigned int inode = 0; inode < lb_type_graph.size(); inode++) {
router_data->explored_node_tb[inode].prev_index = OPEN;
router_data->explored_node_tb[inode].explored_id = OPEN;
@@ -1322,7 +1321,7 @@
/* Save last successful intra-logic block route and reset current traceback */
static void save_and_reset_lb_route(t_lb_router_data* router_data) {
- vector<t_intra_lb_net>& lb_nets = *router_data->intra_lb_nets;
+ std::vector<t_intra_lb_net>& lb_nets = *router_data->intra_lb_nets;
/* Free old saved lb nets if exist */
if (router_data->saved_lb_nets != nullptr) {
@@ -1331,8 +1330,8 @@
}
/* Save current routed solution */
- router_data->saved_lb_nets = new vector<t_intra_lb_net>(lb_nets.size());
- vector<t_intra_lb_net>& saved_lb_nets = *router_data->saved_lb_nets;
+ router_data->saved_lb_nets = new std::vector<t_intra_lb_net>(lb_nets.size());
+ std::vector<t_intra_lb_net>& saved_lb_nets = *router_data->saved_lb_nets;
for (int inet = 0; inet < (int)saved_lb_nets.size(); inet++) {
/*
diff --git a/vpr/src/pack/cluster_router.h b/vpr/src/pack/cluster_router.h
index 8e2a1f0..4f88f1c 100644
--- a/vpr/src/pack/cluster_router.h
+++ b/vpr/src/pack/cluster_router.h
@@ -11,9 +11,9 @@
#include "pack_types.h"
/* Constructors/Destructors */
-t_lb_router_data* alloc_and_load_router_data(vector<t_lb_type_rr_node>* lb_type_graph, t_logical_block_type_ptr type);
+t_lb_router_data* alloc_and_load_router_data(std::vector<t_lb_type_rr_node>* lb_type_graph, t_logical_block_type_ptr type);
void free_router_data(t_lb_router_data* router_data);
-void free_intra_lb_nets(vector<t_intra_lb_net>* intra_lb_nets);
+void free_intra_lb_nets(std::vector<t_intra_lb_net>* intra_lb_nets);
/* Routing Functions */
void add_atom_as_target(t_lb_router_data* router_data, const AtomBlockId blk_id);
@@ -23,7 +23,7 @@
void reset_intra_lb_route(t_lb_router_data* router_data);
/* Accessor Functions */
-t_pb_routes alloc_and_load_pb_route(const vector<t_intra_lb_net>* intra_lb_nets, t_pb_graph_node* pb_graph_head);
+t_pb_routes alloc_and_load_pb_route(const std::vector<t_intra_lb_net>* intra_lb_nets, t_pb_graph_node* pb_graph_head);
void free_pb_route(t_pb_route* free_pb_route);
#endif
diff --git a/vpr/src/pack/lb_type_rr_graph.cpp b/vpr/src/pack/lb_type_rr_graph.cpp
index d0a895f..8f2763d 100644
--- a/vpr/src/pack/lb_type_rr_graph.cpp
+++ b/vpr/src/pack/lb_type_rr_graph.cpp
@@ -33,8 +33,6 @@
#include "pack_types.h"
#include "lb_type_rr_graph.h"
-using namespace std;
-
/*****************************************************************************************
* Internal functions declarations
******************************************************************************************/
diff --git a/vpr/src/pack/output_clustering.cpp b/vpr/src/pack/output_clustering.cpp
index 630894c..9987be6 100644
--- a/vpr/src/pack/output_clustering.cpp
+++ b/vpr/src/pack/output_clustering.cpp
@@ -7,7 +7,6 @@
#include <cstdlib>
#include <cstring>
#include <vector>
-using namespace std;
#include "vtr_assert.h"
#include "vtr_log.h"
diff --git a/vpr/src/pack/pack.cpp b/vpr/src/pack/pack.cpp
index cf8b10f..0dfd434 100644
--- a/vpr/src/pack/pack.cpp
+++ b/vpr/src/pack/pack.cpp
@@ -5,7 +5,6 @@
#include <fstream>
#include <stdlib.h>
#include <sstream>
-using namespace std;
#include "vtr_assert.h"
#include "vtr_log.h"
@@ -42,7 +41,7 @@
const t_model* user_models,
const t_model* library_models,
float interc_delay,
- vector<t_lb_type_rr_node>* lb_type_rr_graphs) {
+ std::vector<t_lb_type_rr_node>* lb_type_rr_graphs) {
std::unordered_set<AtomNetId> is_clock;
std::multimap<AtomBlockId, t_pack_molecule*> atom_molecules; //The molecules associated with each atom block
std::unordered_map<AtomBlockId, t_pb_graph_node*> expected_lowest_cost_pb_gnode; //The molecules associated with each atom block
diff --git a/vpr/src/pack/pack.h b/vpr/src/pack/pack.h
index a9d6211..f8ff31a 100644
--- a/vpr/src/pack/pack.h
+++ b/vpr/src/pack/pack.h
@@ -1,5 +1,7 @@
#ifndef PACK_H
#define PACK_H
+#include <vector>
+#include "vpr_types.h"
bool try_pack(t_packer_opts* packer_opts,
const t_analysis_opts* analysis_opts,
@@ -7,7 +9,7 @@
const t_model* user_models,
const t_model* library_models,
float interc_delay,
- vector<t_lb_type_rr_node>* lb_type_rr_graphs);
+ std::vector<t_lb_type_rr_node>* lb_type_rr_graphs);
float get_arch_switch_info(short switch_index, int switch_fanin, float& Tdel_switch, float& R_switch, float& Cout_switch);
diff --git a/vpr/src/pack/pb_type_graph.cpp b/vpr/src/pack/pb_type_graph.cpp
index 31a7800..d5c7324 100644
--- a/vpr/src/pack/pb_type_graph.cpp
+++ b/vpr/src/pack/pb_type_graph.cpp
@@ -14,7 +14,6 @@
#include <cstdio>
#include <cstring>
#include <cinttypes>
-using namespace std;
#include "vtr_util.h"
#include "vtr_assert.h"
@@ -112,7 +111,7 @@
const t_pb_graph_edge_comparator& edge2);
static bool check_input_pins_equivalence(const t_pb_graph_pin* cur_pin,
const int i_pin,
- map<int, int>& edges_map,
+ std::map<int, int>& edges_map,
int* line_num);
/**
@@ -1434,7 +1433,7 @@
static void check_pb_node_rec(const t_pb_graph_node* pb_graph_node) {
int i, j, k;
int line_num = 0;
- map<int, int> logic_equivalent_pins_map;
+ std::map<int, int> logic_equivalent_pins_map;
for (i = 0; i < pb_graph_node->num_input_ports; i++) {
for (j = 0; j < pb_graph_node->num_input_pins[i]; j++) {
@@ -1487,8 +1486,8 @@
int i_edge, i_pin;
t_pb_graph_edge* cur_edge;
t_pb_graph_edge_comparator edges_info;
- map<t_pb_graph_edge_comparator, int> edges_map;
- pair<map<t_pb_graph_edge_comparator, int>::iterator, bool> ret_edges_map;
+ std::map<t_pb_graph_edge_comparator, int> edges_map;
+ std::pair<std::map<t_pb_graph_edge_comparator, int>::iterator, bool> ret_edges_map;
// First check the incoming edges into cur_pin
for (i_edge = 0; i_edge < cur_pin->num_input_edges; i_edge++) {
@@ -1500,7 +1499,7 @@
edges_info.output_pin = cur_pin;
edges_info.input_pin_id_in_cluster = cur_edge->input_pins[i_pin]->pin_count_in_cluster;
edges_info.output_pin_id_in_cluster = cur_pin->pin_count_in_cluster;
- ret_edges_map = edges_map.insert(pair<t_pb_graph_edge_comparator, int>(edges_info, 0));
+ ret_edges_map = edges_map.insert(std::pair<t_pb_graph_edge_comparator, int>(edges_info, 0));
if (!ret_edges_map.second) {
// Print out the connection that already exists in the map and then the new one
// we are trying to insert into the map.
@@ -1546,7 +1545,7 @@
*/
static bool check_input_pins_equivalence(const t_pb_graph_pin* cur_pin,
const int i_pin,
- map<int, int>& logic_equivalent_pins_map,
+ std::map<int, int>& logic_equivalent_pins_map,
int* line_num) {
int i, j, edge_count;
t_pb_graph_edge* cur_edge;
@@ -1562,7 +1561,7 @@
for (j = 0; j < cur_edge->num_output_pins; j++) {
if (i_pin == 0) {
// First pin of an equivalent port, populate edges_map first
- logic_equivalent_pins_map.insert(pair<int, int>(cur_edge->output_pins[j]->pin_count_in_cluster, 0));
+ logic_equivalent_pins_map.insert(std::pair<int, int>(cur_edge->output_pins[j]->pin_count_in_cluster, 0));
} else {
// Rest of the pins of an equivalent port, they should connect to the
// same set of pins
diff --git a/vpr/src/pack/pb_type_graph_annotations.cpp b/vpr/src/pack/pb_type_graph_annotations.cpp
index df852dd..e66da08 100644
--- a/vpr/src/pack/pb_type_graph_annotations.cpp
+++ b/vpr/src/pack/pb_type_graph_annotations.cpp
@@ -5,7 +5,6 @@
#include <cstdio>
#include <cstdlib>
#include <cstring>
-using namespace std;
#include "vtr_assert.h"
#include "vtr_util.h"
diff --git a/vpr/src/pack/prepack.cpp b/vpr/src/pack/prepack.cpp
index ab6ff28..28e8c2b 100644
--- a/vpr/src/pack/prepack.cpp
+++ b/vpr/src/pack/prepack.cpp
@@ -15,7 +15,6 @@
#include <map>
#include <queue>
#include <utility>
-using namespace std;
#include "vtr_util.h"
#include "vtr_assert.h"
diff --git a/vpr/src/place/compressed_grid.cpp b/vpr/src/place/compressed_grid.cpp
new file mode 100644
index 0000000..b0f5ba3
--- /dev/null
+++ b/vpr/src/place/compressed_grid.cpp
@@ -0,0 +1,99 @@
+#include "compressed_grid.h"
+#include "globals.h"
+
+std::vector<t_compressed_block_grid> create_compressed_block_grids() {
+ auto& device_ctx = g_vpr_ctx.device();
+ auto& grid = device_ctx.grid;
+
+ //Collect the set of x/y locations for each instace of a block type
+ std::vector<std::vector<vtr::Point<int>>> block_locations(device_ctx.physical_tile_types.size());
+ for (size_t x = 0; x < grid.width(); ++x) {
+ for (size_t y = 0; y < grid.height(); ++y) {
+ const t_grid_tile& tile = grid[x][y];
+ if (tile.width_offset == 0 && tile.height_offset == 0) {
+ //Only record at block root location
+ block_locations[tile.type->index].emplace_back(x, y);
+ }
+ }
+ }
+
+ std::vector<t_compressed_block_grid> compressed_type_grids(device_ctx.physical_tile_types.size());
+ for (const auto& type : device_ctx.physical_tile_types) {
+ compressed_type_grids[type.index] = create_compressed_block_grid(block_locations[type.index]);
+ }
+
+ return compressed_type_grids;
+}
+
+//Given a set of locations, returns a 2D matrix in a compressed space
+t_compressed_block_grid create_compressed_block_grid(const std::vector<vtr::Point<int>>& locations) {
+ t_compressed_block_grid compressed_grid;
+
+ if (locations.empty()) {
+ return compressed_grid;
+ }
+
+ {
+ std::vector<int> x_locs;
+ std::vector<int> y_locs;
+
+ //Record all the x/y locations seperately
+ for (auto point : locations) {
+ x_locs.emplace_back(point.x());
+ y_locs.emplace_back(point.y());
+ }
+
+ //Uniquify x/y locations
+ std::sort(x_locs.begin(), x_locs.end());
+ x_locs.erase(unique(x_locs.begin(), x_locs.end()), x_locs.end());
+
+ std::sort(y_locs.begin(), y_locs.end());
+ y_locs.erase(unique(y_locs.begin(), y_locs.end()), y_locs.end());
+
+ //The index of an x-position in x_locs corresponds to it's compressed
+ //x-coordinate (similarly for y)
+ compressed_grid.compressed_to_grid_x = x_locs;
+ compressed_grid.compressed_to_grid_y = y_locs;
+ }
+
+ //
+ //Build the compressed grid
+ //
+
+ //Create a full/dense x-dimension (since there must be at least one
+ //block per x location)
+ compressed_grid.grid.resize(compressed_grid.compressed_to_grid_x.size());
+
+ //Fill-in the y-dimensions
+ //
+ //Note that we build the y-dimension sparsely (using a flat map), since
+ //there may not be full columns of blocks at each x location, this makes
+ //it efficient to find the non-empty blocks in the y dimension
+ for (auto point : locations) {
+ //Determine the compressed indices in the x & y dimensions
+ auto x_itr = std::lower_bound(compressed_grid.compressed_to_grid_x.begin(), compressed_grid.compressed_to_grid_x.end(), point.x());
+ int cx = std::distance(compressed_grid.compressed_to_grid_x.begin(), x_itr);
+
+ auto y_itr = std::lower_bound(compressed_grid.compressed_to_grid_y.begin(), compressed_grid.compressed_to_grid_y.end(), point.y());
+ int cy = std::distance(compressed_grid.compressed_to_grid_y.begin(), y_itr);
+
+ VTR_ASSERT(cx >= 0 && cx < (int)compressed_grid.compressed_to_grid_x.size());
+ VTR_ASSERT(cy >= 0 && cy < (int)compressed_grid.compressed_to_grid_y.size());
+
+ VTR_ASSERT(compressed_grid.compressed_to_grid_x[cx] == point.x());
+ VTR_ASSERT(compressed_grid.compressed_to_grid_y[cy] == point.y());
+
+ auto result = compressed_grid.grid[cx].insert(std::make_pair(cy, t_type_loc(point.x(), point.y())));
+
+ VTR_ASSERT_MSG(result.second, "Duplicates should not exist in compressed grid space");
+ }
+
+ return compressed_grid;
+}
+
+int grid_to_compressed(const std::vector<int>& coords, int point) {
+ auto itr = std::lower_bound(coords.begin(), coords.end(), point);
+ VTR_ASSERT(*itr == point);
+
+ return std::distance(coords.begin(), itr);
+}
diff --git a/vpr/src/place/compressed_grid.h b/vpr/src/place/compressed_grid.h
new file mode 100644
index 0000000..64d99b9
--- /dev/null
+++ b/vpr/src/place/compressed_grid.h
@@ -0,0 +1,47 @@
+#ifndef VPR_COMPRESSED_GRID_H
+#define VPR_COMPRESSED_GRID_H
+
+#include "physical_types.h"
+
+#include "vtr_geometry.h"
+#include "vtr_flat_map.h"
+
+struct t_type_loc {
+ int x = OPEN;
+ int y = OPEN;
+
+ t_type_loc(int x_val, int y_val)
+ : x(x_val)
+ , y(y_val) {}
+
+ //Returns true if this type location has valid x/y values
+ operator bool() const {
+ return !(x == OPEN || y == OPEN);
+ }
+};
+
+struct t_compressed_block_grid {
+ //If 'cx' is an index in the compressed grid space, then
+ //'compressed_to_grid_x[cx]' is the corresponding location in the
+ //full (uncompressed) device grid.
+ std::vector<int> compressed_to_grid_x;
+ std::vector<int> compressed_to_grid_y;
+
+ //The grid is stored with a full/dense x-dimension (since only
+ //x values which exist are considered), while the y-dimension is
+ //stored sparsely, since we may not have full columns of blocks.
+ //This makes it easy to check whether there exist
+ std::vector<vtr::flat_map2<int, t_type_loc>> grid;
+};
+
+//Compressed grid space for each block type
+//Used to efficiently find logically 'adjacent' blocks of the same block type even though
+//the may be physically far apart
+typedef std::vector<t_compressed_block_grid> t_compressed_block_grids;
+
+std::vector<t_compressed_block_grid> create_compressed_block_grids();
+
+t_compressed_block_grid create_compressed_block_grid(const std::vector<vtr::Point<int>>& locations);
+
+int grid_to_compressed(const std::vector<int>& coords, int point);
+#endif
diff --git a/vpr/src/place/move_generator.h b/vpr/src/place/move_generator.h
index 963ef2b..c664423 100644
--- a/vpr/src/place/move_generator.h
+++ b/vpr/src/place/move_generator.h
@@ -1,10 +1,20 @@
#ifndef VPR_MOVE_GENERATOR_H
#define VPR_MOVE_GENERATOR_H
#include "vpr_types.h"
+#include "move_utils.h"
-enum class e_propose_move {
- VALID, //Move successful and legal
- ABORT, //Unable to perform move
+#include <limits>
+
+struct MoveOutcomeStats {
+ float delta_cost_norm = std::numeric_limits<float>::quiet_NaN();
+ float delta_bb_cost_norm = std::numeric_limits<float>::quiet_NaN();
+ float delta_timing_cost_norm = std::numeric_limits<float>::quiet_NaN();
+
+ float delta_bb_cost_abs = std::numeric_limits<float>::quiet_NaN();
+ float delta_timing_cost_abs = std::numeric_limits<float>::quiet_NaN();
+
+ e_move_result outcome = ABORTED;
+ float elapsed_time = std::numeric_limits<float>::quiet_NaN();
};
class MoveGenerator {
@@ -12,7 +22,10 @@
virtual ~MoveGenerator() {}
//Updates affected_blocks with the proposed move, while respecting the current rlim
- virtual e_propose_move propose_move(t_pl_blocks_to_be_moved& affected_blocks, float rlim) = 0;
+ virtual e_create_move propose_move(t_pl_blocks_to_be_moved& affected_blocks, float rlim) = 0;
+
+ //Recieves feedback about the outcome of the previously proposed move
+ virtual void process_outcome(const MoveOutcomeStats& /*move_outcome*/){};
};
#endif
diff --git a/vpr/src/place/move_transactions.cpp b/vpr/src/place/move_transactions.cpp
new file mode 100644
index 0000000..5e8900d
--- /dev/null
+++ b/vpr/src/place/move_transactions.cpp
@@ -0,0 +1,105 @@
+#include "move_utils.h"
+
+#include "globals.h"
+#include "place_util.h"
+
+//Records that block 'blk' should be moved to the specified 'to' location
+e_block_move_result record_block_move(t_pl_blocks_to_be_moved& blocks_affected, ClusterBlockId blk, t_pl_loc to) {
+ auto res = blocks_affected.moved_to.emplace(to);
+ if (!res.second) {
+ log_move_abort("duplicate block move to location");
+ return e_block_move_result::ABORT;
+ }
+
+ auto& place_ctx = g_vpr_ctx.mutable_placement();
+
+ t_pl_loc from = place_ctx.block_locs[blk].loc;
+
+ auto res2 = blocks_affected.moved_from.emplace(from);
+ if (!res2.second) {
+ log_move_abort("duplicate block move from location");
+ return e_block_move_result::ABORT;
+ }
+
+ VTR_ASSERT_SAFE(to.z < int(place_ctx.grid_blocks[to.x][to.y].blocks.size()));
+
+ // Sets up the blocks moved
+ int imoved_blk = blocks_affected.num_moved_blocks;
+ blocks_affected.moved_blocks[imoved_blk].block_num = blk;
+ blocks_affected.moved_blocks[imoved_blk].old_loc = from;
+ blocks_affected.moved_blocks[imoved_blk].new_loc = to;
+ blocks_affected.num_moved_blocks++;
+
+ return e_block_move_result::VALID;
+}
+
+//Moves the blocks in blocks_affected to their new locations
+void apply_move_blocks(const t_pl_blocks_to_be_moved& blocks_affected) {
+ auto& place_ctx = g_vpr_ctx.mutable_placement();
+
+ //Swap the blocks, but don't swap the nets or update place_ctx.grid_blocks
+ //yet since we don't know whether the swap will be accepted
+ for (int iblk = 0; iblk < blocks_affected.num_moved_blocks; ++iblk) {
+ ClusterBlockId blk = blocks_affected.moved_blocks[iblk].block_num;
+
+ place_ctx.block_locs[blk].loc = blocks_affected.moved_blocks[iblk].new_loc;
+ }
+}
+
+//Commits the blocks in blocks_affected to their new locations (updates inverse
+//lookups via place_ctx.grid_blocks)
+void commit_move_blocks(const t_pl_blocks_to_be_moved& blocks_affected) {
+ auto& place_ctx = g_vpr_ctx.mutable_placement();
+
+ /* Swap physical location */
+ for (int iblk = 0; iblk < blocks_affected.num_moved_blocks; ++iblk) {
+ ClusterBlockId blk = blocks_affected.moved_blocks[iblk].block_num;
+
+ t_pl_loc to = blocks_affected.moved_blocks[iblk].new_loc;
+
+ t_pl_loc from = blocks_affected.moved_blocks[iblk].old_loc;
+
+ //Remove from old location only if it hasn't already been updated by a previous block update
+ if (place_ctx.grid_blocks[from.x][from.y].blocks[from.z] == blk) {
+ ;
+ place_ctx.grid_blocks[from.x][from.y].blocks[from.z] = EMPTY_BLOCK_ID;
+ --place_ctx.grid_blocks[from.x][from.y].usage;
+ }
+
+ //Add to new location
+ if (place_ctx.grid_blocks[to.x][to.y].blocks[to.z] == EMPTY_BLOCK_ID) {
+ ;
+ //Only need to increase usage if previously unused
+ ++place_ctx.grid_blocks[to.x][to.y].usage;
+ }
+ place_ctx.grid_blocks[to.x][to.y].blocks[to.z] = blk;
+
+ } // Finish updating clb for all blocks
+}
+
+//Moves the blocks in blocks_affected to their old locations
+void revert_move_blocks(t_pl_blocks_to_be_moved& blocks_affected) {
+ auto& place_ctx = g_vpr_ctx.mutable_placement();
+
+ // Swap the blocks back, nets not yet swapped they don't need to be changed
+ for (int iblk = 0; iblk < blocks_affected.num_moved_blocks; ++iblk) {
+ ClusterBlockId blk = blocks_affected.moved_blocks[iblk].block_num;
+
+ t_pl_loc old = blocks_affected.moved_blocks[iblk].old_loc;
+
+ place_ctx.block_locs[blk].loc = old;
+
+ VTR_ASSERT_SAFE_MSG(place_ctx.grid_blocks[old.x][old.y].blocks[old.z] = blk, "Grid blocks should only have been updated if swap commited (not reverted)");
+ }
+}
+
+//Clears the current move so a new move can be proposed
+void clear_move_blocks(t_pl_blocks_to_be_moved& blocks_affected) {
+ //Reset moved flags
+ blocks_affected.moved_to.clear();
+ blocks_affected.moved_from.clear();
+
+ //For run-time we just reset num_moved_blocks to zero, but do not free the blocks_affected
+ //array to avoid memory allocation
+ blocks_affected.num_moved_blocks = 0;
+}
diff --git a/vpr/src/place/move_transactions.h b/vpr/src/place/move_transactions.h
new file mode 100644
index 0000000..8c17f7e
--- /dev/null
+++ b/vpr/src/place/move_transactions.h
@@ -0,0 +1,56 @@
+#ifndef VPR_MOVE_TRANSACTIONS_H
+#define VPR_MOVE_TRANSACTIONS_H
+#include "vpr_types.h"
+
+/* Stores the information of the move for a block that is *
+ * moved during placement *
+ * block_num: the index of the moved block *
+ * xold: the x_coord that the block is moved from *
+ * xnew: the x_coord that the block is moved to *
+ * yold: the y_coord that the block is moved from *
+ * xnew: the x_coord that the block is moved to */
+struct t_pl_moved_block {
+ ClusterBlockId block_num;
+ t_pl_loc old_loc;
+ t_pl_loc new_loc;
+};
+
+/* Stores the list of blocks to be moved in a swap during *
+ * placement. *
+ * Store the information on the blocks to be moved in a swap during *
+ * placement, in the form of array of structs instead of struct with *
+ * arrays for cache effifiency *
+ *
+ * num_moved_blocks: total number of blocks moved when *
+ * swapping two blocks. *
+ * moved blocks: a list of moved blocks data structure with *
+ * information on the move. *
+ * [0...num_moved_blocks-1] */
+struct t_pl_blocks_to_be_moved {
+ t_pl_blocks_to_be_moved(size_t max_blocks)
+ : moved_blocks(max_blocks) {}
+
+ int num_moved_blocks = 0;
+ std::vector<t_pl_moved_block> moved_blocks;
+ std::unordered_set<t_pl_loc> moved_from;
+ std::unordered_set<t_pl_loc> moved_to;
+};
+
+enum class e_block_move_result {
+ VALID, //Move successful
+ ABORT, //Unable to perform move
+ INVERT, //Try move again but with from/to inverted
+ INVERT_VALID //Completed inverted move
+};
+
+e_block_move_result record_block_move(t_pl_blocks_to_be_moved& blocks_affected, ClusterBlockId blk, t_pl_loc to);
+
+void apply_move_blocks(const t_pl_blocks_to_be_moved& blocks_affected);
+
+void commit_move_blocks(const t_pl_blocks_to_be_moved& blocks_affected);
+
+void revert_move_blocks(t_pl_blocks_to_be_moved& blocks_affected);
+
+void clear_move_blocks(t_pl_blocks_to_be_moved& blocks_affected);
+
+#endif
diff --git a/vpr/src/place/move_utils.cpp b/vpr/src/place/move_utils.cpp
new file mode 100644
index 0000000..e9751f6
--- /dev/null
+++ b/vpr/src/place/move_utils.cpp
@@ -0,0 +1,618 @@
+#include "move_utils.h"
+
+#include "place_util.h"
+#include "globals.h"
+
+#include "vtr_random.h"
+
+//Records counts of reasons for aborted moves
+static std::map<std::string, size_t> f_move_abort_reasons;
+
+void log_move_abort(std::string reason) {
+ ++f_move_abort_reasons[reason];
+}
+
+void report_aborted_moves() {
+ VTR_LOG("\n");
+ VTR_LOG("Aborted Move Reasons:\n");
+ for (auto kv : f_move_abort_reasons) {
+ VTR_LOG(" %s: %zu\n", kv.first.c_str(), kv.second);
+ }
+}
+
+e_create_move create_move(t_pl_blocks_to_be_moved& blocks_affected, ClusterBlockId b_from, t_pl_loc to) {
+ e_block_move_result outcome = find_affected_blocks(blocks_affected, b_from, to);
+
+ if (outcome == e_block_move_result::INVERT) {
+ //Try inverting the swap direction
+
+ auto& place_ctx = g_vpr_ctx.placement();
+ ClusterBlockId b_to = place_ctx.grid_blocks[to.x][to.y].blocks[to.z];
+
+ if (!b_to) {
+ log_move_abort("inverted move no to block");
+ outcome = e_block_move_result::ABORT;
+ } else {
+ t_pl_loc from = place_ctx.block_locs[b_from].loc;
+
+ outcome = find_affected_blocks(blocks_affected, b_to, from);
+
+ if (outcome == e_block_move_result::INVERT) {
+ log_move_abort("inverted move recurrsion");
+ outcome = e_block_move_result::ABORT;
+ }
+ }
+ }
+
+ if (outcome == e_block_move_result::VALID
+ || outcome == e_block_move_result::INVERT_VALID) {
+ return e_create_move::VALID;
+ } else {
+ VTR_ASSERT_SAFE(outcome == e_block_move_result::ABORT);
+ return e_create_move::ABORT;
+ }
+}
+
+e_block_move_result find_affected_blocks(t_pl_blocks_to_be_moved& blocks_affected, ClusterBlockId b_from, t_pl_loc to) {
+ /* Finds and set ups the affected_blocks array.
+ * Returns abort_swap. */
+ VTR_ASSERT_SAFE(b_from);
+
+ int imacro_from;
+ ClusterBlockId curr_b_from;
+ e_block_move_result outcome = e_block_move_result::VALID;
+
+ auto& place_ctx = g_vpr_ctx.placement();
+
+ t_pl_loc from = place_ctx.block_locs[b_from].loc;
+
+ auto& pl_macros = place_ctx.pl_macros;
+
+ get_imacro_from_iblk(&imacro_from, b_from, pl_macros);
+ if (imacro_from != -1) {
+ // b_from is part of a macro, I need to swap the whole macro
+
+ // Record down the relative position of the swap
+ t_pl_offset swap_offset = to - from;
+
+ int imember_from = 0;
+ outcome = record_macro_swaps(blocks_affected, imacro_from, imember_from, swap_offset);
+
+ VTR_ASSERT_SAFE(outcome != e_block_move_result::VALID || imember_from == int(pl_macros[imacro_from].members.size()));
+
+ } else {
+ ClusterBlockId b_to = place_ctx.grid_blocks[to.x][to.y].blocks[to.z];
+ int imacro_to = -1;
+ get_imacro_from_iblk(&imacro_to, b_to, pl_macros);
+
+ if (imacro_to != -1) {
+ //To block is a macro but from is a single block.
+ //
+ //Since we support swapping a macro as 'from' to a single 'to' block,
+ //just invert the swap direction (which is equivalent)
+ outcome = e_block_move_result::INVERT;
+ } else {
+ // This is not a macro - I could use the from and to info from before
+ outcome = record_single_block_swap(blocks_affected, b_from, to);
+ }
+
+ } // Finish handling cases for blocks in macro and otherwise
+
+ return outcome;
+}
+
+e_block_move_result record_single_block_swap(t_pl_blocks_to_be_moved& blocks_affected, ClusterBlockId b_from, t_pl_loc to) {
+ /* Find all the blocks affected when b_from is swapped with b_to.
+ * Returns abort_swap. */
+
+ VTR_ASSERT_SAFE(b_from);
+
+ auto& place_ctx = g_vpr_ctx.mutable_placement();
+
+ VTR_ASSERT_SAFE(to.z < int(place_ctx.grid_blocks[to.x][to.y].blocks.size()));
+
+ ClusterBlockId b_to = place_ctx.grid_blocks[to.x][to.y].blocks[to.z];
+
+ e_block_move_result outcome = e_block_move_result::VALID;
+
+ // Check whether the to_location is empty
+ if (b_to == EMPTY_BLOCK_ID) {
+ // Sets up the blocks moved
+ outcome = record_block_move(blocks_affected, b_from, to);
+
+ } else if (b_to != INVALID_BLOCK_ID) {
+ // Sets up the blocks moved
+ outcome = record_block_move(blocks_affected, b_from, to);
+
+ if (outcome != e_block_move_result::VALID) {
+ return outcome;
+ }
+
+ t_pl_loc from = place_ctx.block_locs[b_from].loc;
+ outcome = record_block_move(blocks_affected, b_to, from);
+
+ } // Finish swapping the blocks and setting up blocks_affected
+
+ return outcome;
+}
+
+//Records all the block movements required to move the macro imacro_from starting at member imember_from
+//to a new position offset from its current position by swap_offset. The new location may be a
+//single (non-macro) block, or another macro.
+e_block_move_result record_macro_swaps(t_pl_blocks_to_be_moved& blocks_affected, const int imacro_from, int& imember_from, t_pl_offset swap_offset) {
+ auto& place_ctx = g_vpr_ctx.placement();
+ auto& pl_macros = place_ctx.pl_macros;
+
+ e_block_move_result outcome = e_block_move_result::VALID;
+
+ for (; imember_from < int(pl_macros[imacro_from].members.size()) && outcome == e_block_move_result::VALID; imember_from++) {
+ // Gets the new from and to info for every block in the macro
+ // cannot use the old from and to info
+ ClusterBlockId curr_b_from = pl_macros[imacro_from].members[imember_from].blk_index;
+
+ t_pl_loc curr_from = place_ctx.block_locs[curr_b_from].loc;
+
+ t_pl_loc curr_to = curr_from + swap_offset;
+
+ //Make sure that the swap_to location is valid
+ //It must be:
+ // * on chip, and
+ // * match the correct block type
+ //
+ //Note that we need to explicitly check that the types match, since the device floorplan is not
+ //(neccessarily) translationally invariant for an arbitrary macro
+ if (!is_legal_swap_to_location(curr_b_from, curr_to)) {
+ log_move_abort("macro_from swap to location illegal");
+ outcome = e_block_move_result::ABORT;
+ } else {
+ ClusterBlockId b_to = place_ctx.grid_blocks[curr_to.x][curr_to.y].blocks[curr_to.z];
+ int imacro_to = -1;
+ get_imacro_from_iblk(&imacro_to, b_to, pl_macros);
+
+ if (imacro_to != -1) {
+ //To block is a macro
+
+ if (imacro_from == imacro_to) {
+ outcome = record_macro_self_swaps(blocks_affected, imacro_from, swap_offset);
+ imember_from = pl_macros[imacro_from].members.size();
+ break; //record_macro_self_swaps() handles this case completely, so we don't need to continue the loop
+ } else {
+ outcome = record_macro_macro_swaps(blocks_affected, imacro_from, imember_from, imacro_to, b_to, swap_offset);
+ if (outcome == e_block_move_result::INVERT_VALID) {
+ break; //The move was inverted and successfully proposed, don't need to continue the loop
+ }
+ imember_from -= 1; //record_macro_macro_swaps() will have already advanced the original imember_from
+ }
+ } else {
+ //To block is not a macro
+ outcome = record_single_block_swap(blocks_affected, curr_b_from, curr_to);
+ }
+ }
+ } // Finish going through all the blocks in the macro
+ return outcome;
+}
+
+//Records all the block movements required to move the macro imacro_from starting at member imember_from
+//to a new position offset from its current position by swap_offset. The new location must be where
+//blk_to is located and blk_to must be part of imacro_to.
+e_block_move_result record_macro_macro_swaps(t_pl_blocks_to_be_moved& blocks_affected, const int imacro_from, int& imember_from, const int imacro_to, ClusterBlockId blk_to, t_pl_offset swap_offset) {
+ //Adds the macro imacro_to to the set of affected block caused by swapping 'blk_to' to it's
+ //new position.
+ //
+ //This function is only called when both the main swap's from/to blocks are placement macros.
+ //The position in the from macro ('imacro_from') is specified by 'imember_from', and the relevant
+ //macro fro the to block is 'imacro_to'.
+
+ auto& place_ctx = g_vpr_ctx.placement();
+
+ //At the moment, we only support blk_to being the first element of the 'to' macro.
+ //
+ //For instance, this means that we can swap two carry chains so long as one starts
+ //below the other (not a big limitation since swapping in the oppostie direction would
+ //allow these blocks to swap)
+ if (place_ctx.pl_macros[imacro_to].members[0].blk_index != blk_to) {
+ int imember_to = 0;
+ auto outcome = record_macro_swaps(blocks_affected, imacro_to, imember_to, -swap_offset);
+ if (outcome == e_block_move_result::INVERT) {
+ log_move_abort("invert recursion2");
+ outcome = e_block_move_result::ABORT;
+ } else if (outcome == e_block_move_result::VALID) {
+ outcome = e_block_move_result::INVERT_VALID;
+ }
+ return outcome;
+ }
+
+ //From/To blocks should be exactly the swap offset appart
+ ClusterBlockId blk_from = place_ctx.pl_macros[imacro_from].members[imember_from].blk_index;
+ VTR_ASSERT_SAFE(place_ctx.block_locs[blk_from].loc + swap_offset == place_ctx.block_locs[blk_to].loc);
+
+ //Continue walking along the overlapping parts of the from and to macros, recording
+ //each block swap.
+ //
+ //At the momemnt we only support swapping the two macros if they have the same shape.
+ //This will be the case with the common cases we care about (i.e. carry-chains), so
+ //we just abort in any other cases (if these types of macros become more common in
+ //the future this could be updated).
+ //
+ //Unless the two macros have thier root blocks aligned (i.e. the mutual overlap starts
+ //at imember_from == 0), then theree will be a fixed offset between the macros' relative
+ //position. We record this as from_to_macro_*_offset which is used to verify the shape
+ //of the macros is consistent.
+ //
+ //NOTE: We mutate imember_from so the outer from macro walking loop moves in lock-step
+ int imember_to = 0;
+ t_pl_offset from_to_macro_offset = place_ctx.pl_macros[imacro_from].members[imember_from].offset;
+ for (; imember_from < int(place_ctx.pl_macros[imacro_from].members.size()) && imember_to < int(place_ctx.pl_macros[imacro_to].members.size());
+ ++imember_from, ++imember_to) {
+ //Check that both macros have the same shape while they overlap
+ if (place_ctx.pl_macros[imacro_from].members[imember_from].offset != place_ctx.pl_macros[imacro_to].members[imember_to].offset + from_to_macro_offset) {
+ log_move_abort("macro shapes disagree");
+ return e_block_move_result::ABORT;
+ }
+
+ ClusterBlockId b_from = place_ctx.pl_macros[imacro_from].members[imember_from].blk_index;
+
+ t_pl_loc curr_to = place_ctx.block_locs[b_from].loc + swap_offset;
+
+ ClusterBlockId b_to = place_ctx.pl_macros[imacro_to].members[imember_to].blk_index;
+ VTR_ASSERT_SAFE(curr_to == place_ctx.block_locs[b_to].loc);
+
+ if (!is_legal_swap_to_location(b_from, curr_to)) {
+ log_move_abort("macro_from swap to location illegal");
+ return e_block_move_result::ABORT;
+ }
+
+ auto outcome = record_single_block_swap(blocks_affected, b_from, curr_to);
+ if (outcome != e_block_move_result::VALID) {
+ return outcome;
+ }
+ }
+
+ if (imember_to < int(place_ctx.pl_macros[imacro_to].members.size())) {
+ //The to macro extends beyond the from macro.
+ //
+ //Swap the remainder of the 'to' macro to locations after the 'from' macro.
+ //Note that we are swapping in the opposite direction so the swap offsets are inverted.
+ return record_macro_swaps(blocks_affected, imacro_to, imember_to, -swap_offset);
+ }
+
+ return e_block_move_result::VALID;
+}
+
+//Moves the macro imacro by the specified offset
+//
+//Records the block movements in block_moves, the other blocks displaced in displaced_blocks,
+//and any generated empty locations in empty_locations.
+//
+//This function moves a single macro and does not check for overlap with other macros!
+e_block_move_result record_macro_move(t_pl_blocks_to_be_moved& blocks_affected,
+ std::vector<ClusterBlockId>& displaced_blocks,
+ const int imacro,
+ t_pl_offset swap_offset) {
+ auto& place_ctx = g_vpr_ctx.placement();
+
+ for (const t_pl_macro_member& member : place_ctx.pl_macros[imacro].members) {
+ t_pl_loc from = place_ctx.block_locs[member.blk_index].loc;
+
+ t_pl_loc to = from + swap_offset;
+
+ if (!is_legal_swap_to_location(member.blk_index, to)) {
+ log_move_abort("macro move to location illegal");
+ return e_block_move_result::ABORT;
+ }
+
+ ClusterBlockId blk_to = place_ctx.grid_blocks[to.x][to.y].blocks[to.z];
+
+ record_block_move(blocks_affected, member.blk_index, to);
+
+ int imacro_to = -1;
+ get_imacro_from_iblk(&imacro_to, blk_to, place_ctx.pl_macros);
+ if (blk_to && imacro_to != imacro) { //Block displaced only if exists and not part of current macro
+ displaced_blocks.push_back(blk_to);
+ }
+ }
+ return e_block_move_result::VALID;
+}
+
+//Returns the set of macros affected by moving imacro by the specified offset
+//
+//The resulting 'macros' may contain duplicates
+e_block_move_result identify_macro_self_swap_affected_macros(std::vector<int>& macros, const int imacro, t_pl_offset swap_offset) {
+ e_block_move_result outcome = e_block_move_result::VALID;
+ auto& place_ctx = g_vpr_ctx.placement();
+
+ for (size_t imember = 0; imember < place_ctx.pl_macros[imacro].members.size() && outcome == e_block_move_result::VALID; ++imember) {
+ ClusterBlockId blk = place_ctx.pl_macros[imacro].members[imember].blk_index;
+
+ t_pl_loc from = place_ctx.block_locs[blk].loc;
+ t_pl_loc to = from + swap_offset;
+
+ if (!is_legal_swap_to_location(blk, to)) {
+ log_move_abort("macro move to location illegal");
+ return e_block_move_result::ABORT;
+ }
+
+ ClusterBlockId blk_to = place_ctx.grid_blocks[to.x][to.y].blocks[to.z];
+
+ int imacro_to = -1;
+ get_imacro_from_iblk(&imacro_to, blk_to, place_ctx.pl_macros);
+
+ if (imacro_to != -1) {
+ auto itr = std::find(macros.begin(), macros.end(), imacro_to);
+ if (itr == macros.end()) {
+ macros.push_back(imacro_to);
+ outcome = identify_macro_self_swap_affected_macros(macros, imacro_to, swap_offset);
+ }
+ }
+ }
+ return e_block_move_result::VALID;
+}
+
+e_block_move_result record_macro_self_swaps(t_pl_blocks_to_be_moved& blocks_affected,
+ const int imacro,
+ t_pl_offset swap_offset) {
+ auto& place_ctx = g_vpr_ctx.placement();
+
+ //Reset any partial move
+ clear_move_blocks(blocks_affected);
+
+ //Collect the macros affected
+ std::vector<int> affected_macros;
+ auto outcome = identify_macro_self_swap_affected_macros(affected_macros, imacro,
+ swap_offset);
+
+ if (outcome != e_block_move_result::VALID) {
+ return outcome;
+ }
+
+ //Remove any duplicate macros
+ affected_macros.resize(std::distance(affected_macros.begin(), std::unique(affected_macros.begin(), affected_macros.end())));
+
+ std::vector<ClusterBlockId> displaced_blocks;
+
+ //Move all the affected macros by the offset
+ for (int imacro_affected : affected_macros) {
+ outcome = record_macro_move(blocks_affected, displaced_blocks, imacro_affected, swap_offset);
+
+ if (outcome != e_block_move_result::VALID) {
+ return outcome;
+ }
+ }
+
+ auto is_non_macro_block = [&](ClusterBlockId blk) {
+ int imacro_blk = -1;
+ get_imacro_from_iblk(&imacro_blk, blk, place_ctx.pl_macros);
+
+ if (std::find(affected_macros.begin(), affected_macros.end(), imacro_blk) != affected_macros.end()) {
+ return false;
+ }
+ return true;
+ };
+
+ std::vector<ClusterBlockId> non_macro_displaced_blocks;
+ std::copy_if(displaced_blocks.begin(), displaced_blocks.end(), std::back_inserter(non_macro_displaced_blocks), is_non_macro_block);
+
+ //Based on the currently queued block moves, find the empty 'holes' left behind
+ auto empty_locs = determine_locations_emptied_by_move(blocks_affected);
+
+ VTR_ASSERT_SAFE(empty_locs.size() >= non_macro_displaced_blocks.size());
+
+ //Fit the displaced blocks into the empty locations
+ auto loc_itr = empty_locs.begin();
+ for (auto blk : non_macro_displaced_blocks) {
+ outcome = record_block_move(blocks_affected, blk, *loc_itr);
+ ++loc_itr;
+ }
+
+ return outcome;
+}
+
+bool is_legal_swap_to_location(ClusterBlockId blk, t_pl_loc to) {
+ //Make sure that the swap_to location is valid
+ //It must be:
+ // * on chip, and
+ // * match the correct block type
+ //
+ //Note that we need to explicitly check that the types match, since the device floorplan is not
+ //(neccessarily) translationally invariant for an arbitrary macro
+
+ auto& device_ctx = g_vpr_ctx.device();
+
+ if (to.x < 0 || to.x >= int(device_ctx.grid.width())
+ || to.y < 0 || to.y >= int(device_ctx.grid.height())
+ || to.z < 0 || to.z >= device_ctx.grid[to.x][to.y].type->capacity
+ || (device_ctx.grid[to.x][to.y].type != physical_tile_type(blk))) {
+ return false;
+ }
+ return true;
+}
+
+//Examines the currently proposed move and determine any empty locations
+std::set<t_pl_loc> determine_locations_emptied_by_move(t_pl_blocks_to_be_moved& blocks_affected) {
+ std::set<t_pl_loc> moved_from;
+ std::set<t_pl_loc> moved_to;
+
+ for (int iblk = 0; iblk < blocks_affected.num_moved_blocks; ++iblk) {
+ //When a block is moved it's old location becomes free
+ moved_from.emplace(blocks_affected.moved_blocks[iblk].old_loc);
+
+ //But any block later moved to a position fills it
+ moved_to.emplace(blocks_affected.moved_blocks[iblk].new_loc);
+ }
+
+ std::set<t_pl_loc> empty_locs;
+ std::set_difference(moved_from.begin(), moved_from.end(),
+ moved_to.begin(), moved_to.end(),
+ std::inserter(empty_locs, empty_locs.begin()));
+
+ return empty_locs;
+}
+
+//Pick a random block to be swapped with another random block.
+//If none is found return ClusterBlockId::INVALID()
+ClusterBlockId pick_from_block() {
+ /* Some blocks may be fixed, and should never be moved from their *
+ * initial positions. If we randomly selected such a block try *
+ * another random block. *
+ * *
+ * We need to track the blocks we have tried to avoid an infinite *
+ * loop if all blocks are fixed. */
+ auto& cluster_ctx = g_vpr_ctx.clustering();
+ auto& place_ctx = g_vpr_ctx.mutable_placement();
+
+ std::unordered_set<ClusterBlockId> tried_from_blocks;
+
+ //So long as untried blocks remain
+ while (tried_from_blocks.size() < cluster_ctx.clb_nlist.blocks().size()) {
+ //Pick a block at random
+ ClusterBlockId b_from = ClusterBlockId(vtr::irand((int)cluster_ctx.clb_nlist.blocks().size() - 1));
+
+ //Record it as tried
+ tried_from_blocks.insert(b_from);
+
+ if (place_ctx.block_locs[b_from].is_fixed) {
+ continue; //Fixed location, try again
+ }
+
+ //Found a movable block
+ return b_from;
+ }
+
+ //No movable blocks found
+ return ClusterBlockId::INVALID();
+}
+
+bool find_to_loc_uniform(t_physical_tile_type_ptr type,
+ float rlim,
+ const t_pl_loc from,
+ t_pl_loc& to) {
+ //Finds a legal swap to location for the given type, starting from 'from.x' and 'from.y'
+ //
+ //Note that the range limit (rlim) is applied in a logical sense (i.e. 'compressed' grid space consisting
+ //of the same block types, and not the physical grid space). This means, for example, that columns of 'rare'
+ //blocks (e.g. DSPs/RAMs) which are physically far appart but logically adjacent will be swappable even
+ //at an rlim fo 1.
+ //
+ //This ensures that such blocks don't get locked down too early during placement (as would be the
+ //case with a physical distance rlim)
+ auto& grid = g_vpr_ctx.device().grid;
+
+ auto grid_type = grid[from.x][from.y].type;
+ VTR_ASSERT(type == grid_type);
+
+ //Retrieve the compressed block grid for this block type
+ const auto& compressed_block_grid = g_vpr_ctx.placement().compressed_block_grids[type->index];
+
+ //Determine the rlim in each dimension
+ int rlim_x = std::min<int>(compressed_block_grid.compressed_to_grid_x.size(), rlim);
+ int rlim_y = std::min<int>(compressed_block_grid.compressed_to_grid_y.size(), rlim); /* for aspect_ratio != 1 case. */
+
+ //Determine the coordinates in the compressed grid space of the current block
+ int cx_from = grid_to_compressed(compressed_block_grid.compressed_to_grid_x, from.x);
+ int cy_from = grid_to_compressed(compressed_block_grid.compressed_to_grid_y, from.y);
+
+ //Determin the valid compressed grid location ranges
+ int min_cx = std::max(0, cx_from - rlim_x);
+ int max_cx = std::min<int>(compressed_block_grid.compressed_to_grid_x.size() - 1, cx_from + rlim_x);
+ int delta_cx = max_cx - min_cx;
+
+ int min_cy = std::max(0, cy_from - rlim_y);
+ int max_cy = std::min<int>(compressed_block_grid.compressed_to_grid_y.size() - 1, cy_from + rlim_y);
+
+ int cx_to = OPEN;
+ int cy_to = OPEN;
+ std::unordered_set<int> tried_cx_to;
+ bool legal = false;
+ while (!legal && (int)tried_cx_to.size() < delta_cx) { //Until legal or all possibilities exhaused
+ //Pick a random x-location within [min_cx, max_cx],
+ //until we find a legal swap, or have exhuasted all possiblites
+ cx_to = min_cx + vtr::irand(delta_cx);
+
+ VTR_ASSERT(cx_to >= min_cx);
+ VTR_ASSERT(cx_to <= max_cx);
+
+ //Record this x location as tried
+ auto res = tried_cx_to.insert(cx_to);
+ if (!res.second) {
+ continue; //Already tried this position
+ }
+
+ //Pick a random y location
+ //
+ //We are careful here to consider that there may be a sparse
+ //set of candidate blocks in the y-axis at this x location.
+ //
+ //The candidates are stored in a flat_map so we can efficiently find the set of valid
+ //candidates with upper/lower bound.
+ auto y_lower_iter = compressed_block_grid.grid[cx_to].lower_bound(min_cy);
+ if (y_lower_iter == compressed_block_grid.grid[cx_to].end()) {
+ continue;
+ }
+
+ auto y_upper_iter = compressed_block_grid.grid[cx_to].upper_bound(max_cy);
+
+ if (y_lower_iter->first > min_cy) {
+ //No valid blocks at this x location which are within rlim_y
+ //
+ //Fall back to allow the whole y range
+ y_lower_iter = compressed_block_grid.grid[cx_to].begin();
+ y_upper_iter = compressed_block_grid.grid[cx_to].end();
+
+ min_cy = y_lower_iter->first;
+ max_cy = (y_upper_iter - 1)->first;
+ }
+
+ int y_range = std::distance(y_lower_iter, y_upper_iter);
+ VTR_ASSERT(y_range >= 0);
+
+ //At this point we know y_lower_iter and y_upper_iter
+ //bound the range of valid blocks at this x-location, which
+ //are within rlim_y
+ std::unordered_set<int> tried_dy;
+ while (!legal && (int)tried_dy.size() < y_range) { //Until legal or all possibilities exhausted
+ //Randomly pick a y location
+ int dy = vtr::irand(y_range - 1);
+
+ //Record this y location as tried
+ auto res2 = tried_dy.insert(dy);
+ if (!res2.second) {
+ continue; //Already tried this position
+ }
+
+ //Key in the y-dimension is the compressed index location
+ cy_to = (y_lower_iter + dy)->first;
+
+ VTR_ASSERT(cy_to >= min_cy);
+ VTR_ASSERT(cy_to <= max_cy);
+
+ if (cx_from == cx_to && cy_from == cy_to) {
+ continue; //Same from/to location -- try again for new y-position
+ } else {
+ legal = true;
+ }
+ }
+ }
+
+ if (!legal) {
+ //No valid position found
+ return false;
+ }
+
+ VTR_ASSERT(cx_to != OPEN);
+ VTR_ASSERT(cy_to != OPEN);
+
+ //Convert to true (uncompressed) grid locations
+ to.x = compressed_block_grid.compressed_to_grid_x[cx_to];
+ to.y = compressed_block_grid.compressed_to_grid_y[cy_to];
+
+ //Each x/y location contains only a single type, so we can pick a random
+ //z (capcity) location
+ to.z = vtr::irand(type->capacity - 1);
+
+ auto& device_ctx = g_vpr_ctx.device();
+ VTR_ASSERT_MSG(device_ctx.grid[to.x][to.y].type == type, "Type must match");
+ VTR_ASSERT_MSG(device_ctx.grid[to.x][to.y].width_offset == 0, "Should be at block base location");
+ VTR_ASSERT_MSG(device_ctx.grid[to.x][to.y].height_offset == 0, "Should be at block base location");
+
+ return true;
+}
diff --git a/vpr/src/place/move_utils.h b/vpr/src/place/move_utils.h
new file mode 100644
index 0000000..ddf7e17
--- /dev/null
+++ b/vpr/src/place/move_utils.h
@@ -0,0 +1,53 @@
+#ifndef VPR_MOVE_UTILS_H
+#define VPR_MOVE_UTILS_H
+#include "vpr_types.h"
+#include "move_transactions.h"
+#include "compressed_grid.h"
+
+/* This is for the placement swap routines. A swap attempt could be *
+ * rejected, accepted or aborted (due to the limitations placed on the *
+ * carry chain support at this point). */
+enum e_move_result {
+ REJECTED,
+ ACCEPTED,
+ ABORTED
+};
+
+enum class e_create_move {
+ VALID, //Move successful and legal
+ ABORT, //Unable to perform move
+};
+
+//Records a reasons for an aborted move
+void log_move_abort(std::string reason);
+
+//Prints a breif report about aborted move reasons and counts
+void report_aborted_moves();
+
+e_create_move create_move(t_pl_blocks_to_be_moved& blocks_affected, ClusterBlockId b_from, t_pl_loc to);
+
+e_block_move_result find_affected_blocks(t_pl_blocks_to_be_moved& blocks_affected, ClusterBlockId b_from, t_pl_loc to);
+
+e_block_move_result record_single_block_swap(t_pl_blocks_to_be_moved& blocks_affected, ClusterBlockId b_from, t_pl_loc to);
+
+e_block_move_result record_macro_swaps(t_pl_blocks_to_be_moved& blocks_affected, const int imacro_from, int& imember_from, t_pl_offset swap_offset);
+e_block_move_result record_macro_macro_swaps(t_pl_blocks_to_be_moved& blocks_affected, const int imacro_from, int& imember_from, const int imacro_to, ClusterBlockId blk_to, t_pl_offset swap_offset);
+
+e_block_move_result record_macro_move(t_pl_blocks_to_be_moved& blocks_affected,
+ std::vector<ClusterBlockId>& displaced_blocks,
+ const int imacro,
+ t_pl_offset swap_offset);
+e_block_move_result identify_macro_self_swap_affected_macros(std::vector<int>& macros, const int imacro, t_pl_offset swap_offset);
+e_block_move_result record_macro_self_swaps(t_pl_blocks_to_be_moved& blocks_affected, const int imacro, t_pl_offset swap_offset);
+
+bool is_legal_swap_to_location(ClusterBlockId blk, t_pl_loc to);
+
+std::set<t_pl_loc> determine_locations_emptied_by_move(t_pl_blocks_to_be_moved& blocks_affected);
+
+ClusterBlockId pick_from_block();
+
+bool find_to_loc_uniform(t_physical_tile_type_ptr type,
+ float rlim,
+ const t_pl_loc from,
+ t_pl_loc& to);
+#endif
diff --git a/vpr/src/place/place.cpp b/vpr/src/place/place.cpp
index 178ffa9..15b922e 100644
--- a/vpr/src/place/place.cpp
+++ b/vpr/src/place/place.cpp
@@ -28,7 +28,10 @@
#include "histogram.h"
#include "place_util.h"
#include "place_delay_model.h"
-#include "move_generator.h"
+#include "move_transactions.h"
+#include "move_utils.h"
+
+#include "uniform_move_generator.h"
#include "PlacementDelayCalculator.h"
#include "VprTimingGraphResolver.h"
@@ -76,22 +79,6 @@
CHECK
};
-/* This is for the placement swap routines. A swap attempt could be *
- * rejected, accepted or aborted (due to the limitations placed on the *
- * carry chain support at this point). */
-enum e_swap_result {
- REJECTED,
- ACCEPTED,
- ABORTED
-};
-
-enum class e_find_affected_blocks_result {
- VALID, //Move successful
- ABORT, //Unable to perform move
- INVERT, //Try move again but with from/to inverted
- INVERT_VALID //Completed inverted move
-};
-
struct t_placer_statistics {
double av_cost, av_bb_cost, av_timing_cost,
sum_of_squares;
@@ -113,10 +100,6 @@
double timing_cost;
};
-class UniformMoveGenerator : public MoveGenerator {
- e_propose_move propose_move(t_pl_blocks_to_be_moved& affected_blocks, float rlim);
-};
-
constexpr float INVALID_DELAY = std::numeric_limits<float>::quiet_NaN();
constexpr double MAX_INV_TIMING_COST = 1.e9;
@@ -125,9 +108,6 @@
* The exact value of this cost has relatively little impact, but should not be
* large enough to be on the order of timing costs for normal constraints. */
-//Define to log and print debug info about aborted moves
-#define DEBUG_ABORTED_MOVES
-
/********************** Variables local to place.c ***************************/
/* Cost of a net, and a temporary cost of a net used during move assessment. */
@@ -174,12 +154,6 @@
static vtr::vector<ClusterNetId, t_bb> bb_coords, bb_num_on_edges;
-/* Store the information on the blocks to be moved in a swap during *
- * placement, in the form of array of structs instead of struct with *
- * arrays for cache effifiency *
- */
-static t_pl_blocks_to_be_moved blocks_affected;
-
/* The arrays below are used to precompute the inverse of the average *
* number of tracks per channel between [subhigh] and [sublow]. Access *
* them as chan?_place_cost_fac[subhigh][sublow]. They are used to *
@@ -216,43 +190,6 @@
2.5064, 2.5356, 2.5610, 2.5864, 2.6117, 2.6371, 2.6625, 2.6887, 2.7148,
2.7410, 2.7671, 2.7933};
-extern vtr::vector<ClusterNetId, float*> f_timing_place_crit; //TODO: encapsulate better
-
-static std::map<std::string, size_t> f_move_abort_reasons;
-
-struct t_type_loc {
- int x = OPEN;
- int y = OPEN;
-
- t_type_loc(int x_val, int y_val)
- : x(x_val)
- , y(y_val) {}
-
- //Returns true if this type location has valid x/y values
- operator bool() const {
- return !(x == OPEN || y == OPEN);
- }
-};
-
-struct t_compressed_block_grid {
- //If 'cx' is an index in the compressed grid space, then
- //'compressed_to_grid_x[cx]' is the corresponding location in the
- //full (uncompressed) device grid.
- std::vector<int> compressed_to_grid_x;
- std::vector<int> compressed_to_grid_y;
-
- //The grid is stored with a full/dense x-dimension (since only
- //x values which exist are considered), while the y-dimension is
- //stored sparsely, since we may not have full columns of blocks.
- //This makes it easy to check whether there exist
- std::vector<vtr::flat_map2<int, t_type_loc>> grid;
-};
-
-//Compressed grid space for each block type
-//Used to efficiently find logically 'adjacent' blocks of the same block type even though
-//the may be physically far apart
-static std::vector<t_compressed_block_grid> f_compressed_block_grids;
-
std::unique_ptr<FILE, decltype(&vtr::fclose)> f_move_stats_file(nullptr, vtr::fclose);
#ifdef VTR_ENABLE_DEBUG_LOGGING
@@ -342,10 +279,6 @@
static void alloc_and_load_try_swap_structs();
-static std::vector<t_compressed_block_grid> create_compressed_block_grids();
-
-static t_compressed_block_grid create_compressed_block_grid(const std::vector<vtr::Point<int>>& locations);
-
static void free_placement_structs(const t_placer_opts& placer_opts);
static void alloc_and_load_for_fast_cost_update(float place_cost_exp);
@@ -371,45 +304,20 @@
static double comp_bb_cost(e_cost_methods method);
-static void apply_move_blocks();
-static void revert_move_blocks();
-static void commit_move_blocks();
-static void clear_move_blocks();
-
static void update_move_nets(int num_nets_affected);
static void reset_move_nets(int num_nets_affected);
-static e_find_affected_blocks_result record_single_block_swap(ClusterBlockId b_from, t_pl_loc to);
-static e_find_affected_blocks_result record_block_move(ClusterBlockId blk, t_pl_loc to);
-
-static e_propose_move propose_move(ClusterBlockId b_from, t_pl_loc to);
-static e_find_affected_blocks_result find_affected_blocks(ClusterBlockId b_from, t_pl_loc to);
-
-static e_find_affected_blocks_result record_macro_swaps(const int imacro_from, int& imember_from, t_pl_offset swap_offset);
-static e_find_affected_blocks_result record_macro_macro_swaps(const int imacro_from, int& imember_from, const int imacro_to, ClusterBlockId blk_to, t_pl_offset swap_offset);
-
-static e_find_affected_blocks_result record_macro_move(std::vector<ClusterBlockId>& displaced_blocks,
- const int imacro,
- t_pl_offset swap_offset);
-static e_find_affected_blocks_result identify_macro_self_swap_affected_macros(std::vector<int>& macros, const int imacro, t_pl_offset swap_offset);
-static e_find_affected_blocks_result record_macro_self_swaps(const int imacro, t_pl_offset swap_offset);
-
-bool is_legal_swap_to_location(ClusterBlockId blk, t_pl_loc to);
-
-std::set<t_pl_loc> determine_locations_emptied_by_move();
-
-static e_swap_result try_swap(float t,
+static e_move_result try_swap(float t,
t_placer_costs* costs,
t_placer_prev_inverse_costs* prev_inverse_costs,
float rlim,
MoveGenerator& move_generator,
+ t_pl_blocks_to_be_moved& blocks_affected,
const PlaceDelayModel* delay_model,
float rlim_escape_fraction,
enum e_place_algorithm place_algorithm,
float timing_tradeoff);
-static ClusterBlockId pick_from_block();
-
static void check_place(const t_placer_costs& costs,
const PlaceDelayModel* delay_model,
enum e_place_algorithm place_algorithm);
@@ -428,6 +336,7 @@
float rlim,
const PlaceDelayModel* delay_model,
MoveGenerator& move_generator,
+ t_pl_blocks_to_be_moved& blocks_affected,
const t_placer_opts& placer_opts);
static void update_t(float* t, float rlim, float success_rat, t_annealing_sched annealing_sched);
@@ -446,26 +355,32 @@
static void comp_td_point_to_point_delays(const PlaceDelayModel* delay_model);
-static void update_td_cost();
+static void update_td_cost(const t_pl_blocks_to_be_moved& blocks_affected);
-static bool driven_by_moved_block(const ClusterNetId net);
+static bool driven_by_moved_block(const ClusterNetId net, const t_pl_blocks_to_be_moved& blocks_affected);
static void comp_td_costs(const PlaceDelayModel* delay_model, double* timing_cost);
-static e_swap_result assess_swap(double delta_c, double t);
-
-static bool find_to(t_physical_tile_type_ptr type, float rlim, const t_pl_loc from, t_pl_loc& to);
+static e_move_result assess_swap(double delta_c, double t);
static void get_non_updateable_bb(ClusterNetId net_id, t_bb* bb_coord_new);
static void update_bb(ClusterNetId net_id, t_bb* bb_coord_new, t_bb* bb_edge_new, int xold, int yold, int xnew, int ynew);
-static int find_affected_nets_and_update_costs(e_place_algorithm place_algorithm, const PlaceDelayModel* delay_model, double& bb_delta_c, double& timing_delta_c);
+static int find_affected_nets_and_update_costs(e_place_algorithm place_algorithm,
+ const t_pl_blocks_to_be_moved& blocks_affected,
+ const PlaceDelayModel* delay_model,
+ double& bb_delta_c,
+ double& timing_delta_c);
static void record_affected_net(const ClusterNetId net, int& num_affected_nets);
-static void update_net_bb(const ClusterNetId net, int iblk, const ClusterBlockId blk, const ClusterPinId blk_pin);
-static void update_td_delta_costs(const PlaceDelayModel* delay_model, const ClusterNetId net, const ClusterPinId pin, double& delta_timing_cost);
+static void update_net_bb(const ClusterNetId net,
+ const t_pl_blocks_to_be_moved& blocks_affected,
+ int iblk,
+ const ClusterBlockId blk,
+ const ClusterPinId blk_pin);
+static void update_td_delta_costs(const PlaceDelayModel* delay_model, const t_pl_blocks_to_be_moved& blocks_affected, const ClusterNetId net, const ClusterPinId pin, double& delta_timing_cost);
static double get_net_cost(ClusterNetId net_id, t_bb* bb_ptr);
@@ -498,6 +413,7 @@
const ClusteredPinAtomPinsLookup& netlist_pin_lookup,
const PlaceDelayModel* delay_model,
MoveGenerator& move_generator,
+ t_pl_blocks_to_be_moved& blocks_affected,
SetupTimingInfo& timing_info);
static void recompute_costs_from_scratch(const t_placer_opts& placer_opts, const PlaceDelayModel* delay_model, t_placer_costs* costs);
@@ -509,10 +425,6 @@
const SetupTimingInfo& timing_info,
const PlacementDelayCalculator& delay_calc);
-static void log_move_abort(std::string reason);
-static void report_aborted_moves();
-static int grid_to_compressed(const std::vector<int>& coords, int point);
-
static void print_place_status_header();
static void print_place_status(const float t,
const float oldt,
@@ -566,6 +478,8 @@
std::unique_ptr<PlaceDelayModel> place_delay_model;
std::unique_ptr<MoveGenerator> move_generator;
+ t_pl_blocks_to_be_moved blocks_affected(cluster_ctx.clb_nlist.blocks().size());
+
/* Allocated here because it goes into timing critical code where each memory allocation is expensive */
IntraLbPbPinLookup pb_gpin_lookup(device_ctx.logical_block_types);
@@ -718,6 +632,7 @@
annealing_sched, move_lim, rlim,
place_delay_model.get(),
*move_generator,
+ blocks_affected,
placer_opts);
if (!placer_opts.move_stats_file.empty()) {
@@ -727,6 +642,7 @@
tot_iter = 0;
moves_since_cost_recompute = 0;
+ int num_temps = 0;
/* Outer loop of the simmulated annealing begins */
while (exit_crit(t, costs.cost, annealing_sched) == 0) {
@@ -750,6 +666,7 @@
netlist_pin_lookup,
place_delay_model.get(),
*move_generator,
+ blocks_affected,
*timing_info);
tot_iter += move_lim;
@@ -758,6 +675,7 @@
oldt = t; /* for finding and printing alpha. */
update_t(&t, rlim, success_rat, annealing_sched);
+ ++num_temps;
if (placer_opts.place_algorithm == PATH_TIMING_DRIVEN_PLACE) {
critical_path = timing_info->least_slack_critical_path();
@@ -780,6 +698,7 @@
* (placer_opts.td_place_exp_last - placer_opts.td_place_exp_first)
+ placer_opts.td_place_exp_first;
}
+
#ifdef VERBOSE
if (getEchoEnabled()) {
print_clb_placement("first_iteration_clb_placement.echo");
@@ -809,9 +728,12 @@
netlist_pin_lookup,
place_delay_model.get(),
*move_generator,
+ blocks_affected,
*timing_info);
tot_iter += move_lim;
+ ++num_temps;
+
calc_placer_stats(stats, success_rat, std_dev, costs, move_lim);
if (placer_opts.place_algorithm == PATH_TIMING_DRIVEN_PLACE) {
@@ -899,6 +821,7 @@
float reject_rate = (float)num_swap_rejected / total_swap_attempts;
float accept_rate = (float)num_swap_accepted / total_swap_attempts;
float abort_rate = (float)num_swap_aborted / total_swap_attempts;
+ VTR_LOG("Placement number of temperatures: %d\n", num_temps);
VTR_LOG("Placement total # of swap attempts: %*d\n", num_swap_print_digits, total_swap_attempts);
VTR_LOG("\tSwaps accepted: %*d (%4.1f %%)\n", num_swap_print_digits, num_swap_accepted, 100 * accept_rate);
VTR_LOG("\tSwaps rejected: %*d (%4.1f %%)\n", num_swap_print_digits, num_swap_rejected, 100 * reject_rate);
@@ -969,6 +892,7 @@
const ClusteredPinAtomPinsLookup& netlist_pin_lookup,
const PlaceDelayModel* delay_model,
MoveGenerator& move_generator,
+ t_pl_blocks_to_be_moved& blocks_affected,
SetupTimingInfo& timing_info) {
int inner_crit_iter_count, inner_iter;
@@ -982,8 +906,9 @@
/* Inner loop begins */
for (inner_iter = 0; inner_iter < move_lim; inner_iter++) {
- e_swap_result swap_result = try_swap(t, costs, prev_inverse_costs, rlim,
+ e_move_result swap_result = try_swap(t, costs, prev_inverse_costs, rlim,
move_generator,
+ blocks_affected,
delay_model,
placer_opts.rlim_escape_fraction,
placer_opts.place_algorithm,
@@ -1172,6 +1097,7 @@
float rlim,
const PlaceDelayModel* delay_model,
MoveGenerator& move_generator,
+ t_pl_blocks_to_be_moved& blocks_affected,
const t_placer_opts& placer_opts) {
/* Finds the starting temperature (hot condition). */
@@ -1192,8 +1118,9 @@
/* Try one move per block. Set t high so essentially all accepted. */
for (i = 0; i < move_lim; i++) {
- e_swap_result swap_result = try_swap(HUGE_POSITIVE_FLOAT, costs, prev_inverse_costs, rlim,
+ e_move_result swap_result = try_swap(HUGE_POSITIVE_FLOAT, costs, prev_inverse_costs, rlim,
move_generator,
+ blocks_affected,
delay_model,
placer_opts.rlim_escape_fraction,
placer_opts.place_algorithm,
@@ -1231,77 +1158,6 @@
return (20. * std_dev);
}
-//Moves the blocks in blocks_affected to their new locations
-static void apply_move_blocks() {
- auto& place_ctx = g_vpr_ctx.mutable_placement();
-
- //Swap the blocks, but don't swap the nets or update place_ctx.grid_blocks
- //yet since we don't know whether the swap will be accepted
- for (int iblk = 0; iblk < blocks_affected.num_moved_blocks; ++iblk) {
- ClusterBlockId blk = blocks_affected.moved_blocks[iblk].block_num;
-
- place_ctx.block_locs[blk].loc = blocks_affected.moved_blocks[iblk].new_loc;
- }
-}
-
-//Commits the blocks in blocks_affected to their new locations (updates inverse
-//lookups via place_ctx.grid_blocks)
-static void commit_move_blocks() {
- auto& place_ctx = g_vpr_ctx.mutable_placement();
-
- /* Swap physical location */
- for (int iblk = 0; iblk < blocks_affected.num_moved_blocks; ++iblk) {
- ClusterBlockId blk = blocks_affected.moved_blocks[iblk].block_num;
-
- t_pl_loc to = blocks_affected.moved_blocks[iblk].new_loc;
-
- t_pl_loc from = blocks_affected.moved_blocks[iblk].old_loc;
-
- //Remove from old location only if it hasn't already been updated by a previous block update
- if (place_ctx.grid_blocks[from.x][from.y].blocks[from.z] == blk) {
- ;
- place_ctx.grid_blocks[from.x][from.y].blocks[from.z] = EMPTY_BLOCK_ID;
- --place_ctx.grid_blocks[from.x][from.y].usage;
- }
-
- //Add to new location
- if (place_ctx.grid_blocks[to.x][to.y].blocks[to.z] == EMPTY_BLOCK_ID) {
- ;
- //Only need to increase usage if previously unused
- ++place_ctx.grid_blocks[to.x][to.y].usage;
- }
- place_ctx.grid_blocks[to.x][to.y].blocks[to.z] = blk;
-
- } // Finish updating clb for all blocks
-}
-
-//Moves the blocks in blocks_affected to their old locations
-static void revert_move_blocks() {
- auto& place_ctx = g_vpr_ctx.mutable_placement();
-
- // Swap the blocks back, nets not yet swapped they don't need to be changed
- for (int iblk = 0; iblk < blocks_affected.num_moved_blocks; ++iblk) {
- ClusterBlockId blk = blocks_affected.moved_blocks[iblk].block_num;
-
- t_pl_loc old = blocks_affected.moved_blocks[iblk].old_loc;
-
- place_ctx.block_locs[blk].loc = old;
-
- VTR_ASSERT_SAFE_MSG(place_ctx.grid_blocks[old.x][old.y].blocks[old.z] = blk, "Grid blocks should only have been updated if swap commited (not reverted)");
- }
-}
-
-//Clears the current move so a new move can be proposed
-static void clear_move_blocks() {
- //Reset moved flags
- blocks_affected.moved_to.clear();
- blocks_affected.moved_from.clear();
-
- //For run-time we just reset num_moved_blocks to zero, but do not free the blocks_affected
- //array to avoid memory allocation
- blocks_affected.num_moved_blocks = 0;
-}
-
static void update_move_nets(int num_nets_affected) {
/* update net cost functions and reset flags. */
auto& cluster_ctx = g_vpr_ctx.clustering();
@@ -1329,465 +1185,12 @@
}
}
-static e_find_affected_blocks_result record_block_move(ClusterBlockId blk, t_pl_loc to) {
- auto res = blocks_affected.moved_to.emplace(to);
- if (!res.second) {
- log_move_abort("duplicate block move to location");
- return e_find_affected_blocks_result::ABORT;
- }
-
- auto& place_ctx = g_vpr_ctx.mutable_placement();
-
- t_pl_loc from = place_ctx.block_locs[blk].loc;
-
- auto res2 = blocks_affected.moved_from.emplace(from);
- if (!res2.second) {
- log_move_abort("duplicate block move from location");
- return e_find_affected_blocks_result::ABORT;
- }
-
- VTR_ASSERT_SAFE(to.z < int(place_ctx.grid_blocks[to.x][to.y].blocks.size()));
-
- // Sets up the blocks moved
- int imoved_blk = blocks_affected.num_moved_blocks;
- blocks_affected.moved_blocks[imoved_blk].block_num = blk;
- blocks_affected.moved_blocks[imoved_blk].old_loc = from;
- blocks_affected.moved_blocks[imoved_blk].new_loc = to;
- blocks_affected.num_moved_blocks++;
-
- return e_find_affected_blocks_result::VALID;
-}
-
-static e_find_affected_blocks_result record_single_block_swap(ClusterBlockId b_from, t_pl_loc to) {
- /* Find all the blocks affected when b_from is swapped with b_to.
- * Returns abort_swap. */
-
- VTR_ASSERT_SAFE(b_from);
-
- auto& place_ctx = g_vpr_ctx.mutable_placement();
-
- VTR_ASSERT_SAFE(to.z < int(place_ctx.grid_blocks[to.x][to.y].blocks.size()));
-
- ClusterBlockId b_to = place_ctx.grid_blocks[to.x][to.y].blocks[to.z];
-
- e_find_affected_blocks_result outcome = e_find_affected_blocks_result::VALID;
-
- // Check whether the to_location is empty
- if (b_to == EMPTY_BLOCK_ID) {
- // Sets up the blocks moved
- outcome = record_block_move(b_from, to);
-
- } else if (b_to != INVALID_BLOCK_ID) {
- // Sets up the blocks moved
- outcome = record_block_move(b_from, to);
-
- if (outcome != e_find_affected_blocks_result::VALID) {
- return outcome;
- }
-
- t_pl_loc from = place_ctx.block_locs[b_from].loc;
- outcome = record_block_move(b_to, from);
-
- } // Finish swapping the blocks and setting up blocks_affected
-
- return outcome;
-}
-
-static e_propose_move propose_move(ClusterBlockId b_from, t_pl_loc to) {
- e_find_affected_blocks_result outcome = find_affected_blocks(b_from, to);
-
- if (outcome == e_find_affected_blocks_result::INVERT) {
- //Try inverting the swap direction
-
- auto& place_ctx = g_vpr_ctx.placement();
- ClusterBlockId b_to = place_ctx.grid_blocks[to.x][to.y].blocks[to.z];
-
- if (!b_to) {
- log_move_abort("inverted move no to block");
- outcome = e_find_affected_blocks_result::ABORT;
- } else {
- t_pl_loc from = place_ctx.block_locs[b_from].loc;
-
- outcome = find_affected_blocks(b_to, from);
-
- if (outcome == e_find_affected_blocks_result::INVERT) {
- log_move_abort("inverted move recurrsion");
- outcome = e_find_affected_blocks_result::ABORT;
- }
- }
- }
-
- if (outcome == e_find_affected_blocks_result::VALID
- || outcome == e_find_affected_blocks_result::INVERT_VALID) {
- return e_propose_move::VALID;
- } else {
- VTR_ASSERT_SAFE(outcome == e_find_affected_blocks_result::ABORT);
- return e_propose_move::ABORT;
- }
-}
-
-static e_find_affected_blocks_result find_affected_blocks(ClusterBlockId b_from, t_pl_loc to) {
- /* Finds and set ups the affected_blocks array.
- * Returns abort_swap. */
- VTR_ASSERT_SAFE(b_from);
-
- int imacro_from;
- ClusterBlockId curr_b_from;
- e_find_affected_blocks_result outcome = e_find_affected_blocks_result::VALID;
-
- auto& place_ctx = g_vpr_ctx.placement();
-
- t_pl_loc from = place_ctx.block_locs[b_from].loc;
-
- auto& pl_macros = place_ctx.pl_macros;
-
- get_imacro_from_iblk(&imacro_from, b_from, pl_macros);
- if (imacro_from != -1) {
- // b_from is part of a macro, I need to swap the whole macro
-
- // Record down the relative position of the swap
- t_pl_offset swap_offset = to - from;
-
- int imember_from = 0;
- outcome = record_macro_swaps(imacro_from, imember_from, swap_offset);
-
- VTR_ASSERT_SAFE(outcome != e_find_affected_blocks_result::VALID || imember_from == int(pl_macros[imacro_from].members.size()));
-
- } else {
- ClusterBlockId b_to = place_ctx.grid_blocks[to.x][to.y].blocks[to.z];
- int imacro_to = -1;
- get_imacro_from_iblk(&imacro_to, b_to, pl_macros);
-
- if (imacro_to != -1) {
- //To block is a macro but from is a single block.
- //
- //Since we support swapping a macro as 'from' to a single 'to' block,
- //just invert the swap direction (which is equivalent)
- outcome = e_find_affected_blocks_result::INVERT;
- } else {
- // This is not a macro - I could use the from and to info from before
- outcome = record_single_block_swap(b_from, to);
- }
-
- } // Finish handling cases for blocks in macro and otherwise
-
- return outcome;
-}
-
-//Records all the block movements required to move the macro imacro_from starting at member imember_from
-//to a new position offset from its current position by swap_offset. The new location may be a
-//single (non-macro) block, or another macro.
-static e_find_affected_blocks_result record_macro_swaps(const int imacro_from, int& imember_from, t_pl_offset swap_offset) {
- auto& place_ctx = g_vpr_ctx.placement();
- auto& pl_macros = place_ctx.pl_macros;
-
- e_find_affected_blocks_result outcome = e_find_affected_blocks_result::VALID;
-
- for (; imember_from < int(pl_macros[imacro_from].members.size()) && outcome == e_find_affected_blocks_result::VALID; imember_from++) {
- // Gets the new from and to info for every block in the macro
- // cannot use the old from and to info
- ClusterBlockId curr_b_from = pl_macros[imacro_from].members[imember_from].blk_index;
-
- t_pl_loc curr_from = place_ctx.block_locs[curr_b_from].loc;
-
- t_pl_loc curr_to = curr_from + swap_offset;
-
- //Make sure that the swap_to location is valid
- //It must be:
- // * on chip, and
- // * match the correct block type
- //
- //Note that we need to explicitly check that the types match, since the device floorplan is not
- //(neccessarily) translationally invariant for an arbitrary macro
- if (!is_legal_swap_to_location(curr_b_from, curr_to)) {
- log_move_abort("macro_from swap to location illegal");
- outcome = e_find_affected_blocks_result::ABORT;
- } else {
- ClusterBlockId b_to = place_ctx.grid_blocks[curr_to.x][curr_to.y].blocks[curr_to.z];
- int imacro_to = -1;
- get_imacro_from_iblk(&imacro_to, b_to, pl_macros);
-
- if (imacro_to != -1) {
- //To block is a macro
-
- if (imacro_from == imacro_to) {
- outcome = record_macro_self_swaps(imacro_from, swap_offset);
- imember_from = pl_macros[imacro_from].members.size();
- break; //record_macro_self_swaps() handles this case completely, so we don't need to continue the loop
- } else {
- outcome = record_macro_macro_swaps(imacro_from, imember_from, imacro_to, b_to, swap_offset);
- if (outcome == e_find_affected_blocks_result::INVERT_VALID) {
- break; //The move was inverted and successfully proposed, don't need to continue the loop
- }
- imember_from -= 1; //record_macro_macro_swaps() will have already advanced the original imember_from
- }
- } else {
- //To block is not a macro
- outcome = record_single_block_swap(curr_b_from, curr_to);
- }
- }
- } // Finish going through all the blocks in the macro
- return outcome;
-}
-
-//Records all the block movements required to move the macro imacro_from starting at member imember_from
-//to a new position offset from its current position by swap_offset. The new location must be where
-//blk_to is located and blk_to must be part of imacro_to.
-static e_find_affected_blocks_result record_macro_macro_swaps(const int imacro_from, int& imember_from, const int imacro_to, ClusterBlockId blk_to, t_pl_offset swap_offset) {
- //Adds the macro imacro_to to the set of affected block caused by swapping 'blk_to' to it's
- //new position.
- //
- //This function is only called when both the main swap's from/to blocks are placement macros.
- //The position in the from macro ('imacro_from') is specified by 'imember_from', and the relevant
- //macro fro the to block is 'imacro_to'.
-
- auto& place_ctx = g_vpr_ctx.placement();
-
- //At the moment, we only support blk_to being the first element of the 'to' macro.
- //
- //For instance, this means that we can swap two carry chains so long as one starts
- //below the other (not a big limitation since swapping in the oppostie direction would
- //allow these blocks to swap)
- if (place_ctx.pl_macros[imacro_to].members[0].blk_index != blk_to) {
- int imember_to = 0;
- auto outcome = record_macro_swaps(imacro_to, imember_to, -swap_offset);
- if (outcome == e_find_affected_blocks_result::INVERT) {
- log_move_abort("invert recursion2");
- outcome = e_find_affected_blocks_result::ABORT;
- } else if (outcome == e_find_affected_blocks_result::VALID) {
- outcome = e_find_affected_blocks_result::INVERT_VALID;
- }
- return outcome;
- }
-
- //From/To blocks should be exactly the swap offset appart
- ClusterBlockId blk_from = place_ctx.pl_macros[imacro_from].members[imember_from].blk_index;
- VTR_ASSERT_SAFE(place_ctx.block_locs[blk_from].loc + swap_offset == place_ctx.block_locs[blk_to].loc);
-
- //Continue walking along the overlapping parts of the from and to macros, recording
- //each block swap.
- //
- //At the momemnt we only support swapping the two macros if they have the same shape.
- //This will be the case with the common cases we care about (i.e. carry-chains), so
- //we just abort in any other cases (if these types of macros become more common in
- //the future this could be updated).
- //
- //Unless the two macros have thier root blocks aligned (i.e. the mutual overlap starts
- //at imember_from == 0), then theree will be a fixed offset between the macros' relative
- //position. We record this as from_to_macro_*_offset which is used to verify the shape
- //of the macros is consistent.
- //
- //NOTE: We mutate imember_from so the outer from macro walking loop moves in lock-step
- int imember_to = 0;
- t_pl_offset from_to_macro_offset = place_ctx.pl_macros[imacro_from].members[imember_from].offset;
- for (; imember_from < int(place_ctx.pl_macros[imacro_from].members.size()) && imember_to < int(place_ctx.pl_macros[imacro_to].members.size());
- ++imember_from, ++imember_to) {
- //Check that both macros have the same shape while they overlap
- if (place_ctx.pl_macros[imacro_from].members[imember_from].offset != place_ctx.pl_macros[imacro_to].members[imember_to].offset + from_to_macro_offset) {
- log_move_abort("macro shapes disagree");
- return e_find_affected_blocks_result::ABORT;
- }
-
- ClusterBlockId b_from = place_ctx.pl_macros[imacro_from].members[imember_from].blk_index;
-
- t_pl_loc curr_to = place_ctx.block_locs[b_from].loc + swap_offset;
-
- ClusterBlockId b_to = place_ctx.pl_macros[imacro_to].members[imember_to].blk_index;
- VTR_ASSERT_SAFE(curr_to == place_ctx.block_locs[b_to].loc);
-
- if (!is_legal_swap_to_location(b_from, curr_to)) {
- log_move_abort("macro_from swap to location illegal");
- return e_find_affected_blocks_result::ABORT;
- }
-
- auto outcome = record_single_block_swap(b_from, curr_to);
- if (outcome != e_find_affected_blocks_result::VALID) {
- return outcome;
- }
- }
-
- if (imember_to < int(place_ctx.pl_macros[imacro_to].members.size())) {
- //The to macro extends beyond the from macro.
- //
- //Swap the remainder of the 'to' macro to locations after the 'from' macro.
- //Note that we are swapping in the opposite direction so the swap offsets are inverted.
- return record_macro_swaps(imacro_to, imember_to, -swap_offset);
- }
-
- return e_find_affected_blocks_result::VALID;
-}
-
-//Returns the set of macros affected by moving imacro by the specified offset
-//
-//The resulting 'macros' may contain duplicates
-static e_find_affected_blocks_result identify_macro_self_swap_affected_macros(std::vector<int>& macros, const int imacro, t_pl_offset swap_offset) {
- e_find_affected_blocks_result outcome = e_find_affected_blocks_result::VALID;
- auto& place_ctx = g_vpr_ctx.placement();
-
- for (size_t imember = 0; imember < place_ctx.pl_macros[imacro].members.size() && outcome == e_find_affected_blocks_result::VALID; ++imember) {
- ClusterBlockId blk = place_ctx.pl_macros[imacro].members[imember].blk_index;
-
- t_pl_loc from = place_ctx.block_locs[blk].loc;
- t_pl_loc to = from + swap_offset;
-
- if (!is_legal_swap_to_location(blk, to)) {
- log_move_abort("macro move to location illegal");
- return e_find_affected_blocks_result::ABORT;
- }
-
- ClusterBlockId blk_to = place_ctx.grid_blocks[to.x][to.y].blocks[to.z];
-
- int imacro_to = -1;
- get_imacro_from_iblk(&imacro_to, blk_to, place_ctx.pl_macros);
-
- if (imacro_to != -1) {
- auto itr = std::find(macros.begin(), macros.end(), imacro_to);
- if (itr == macros.end()) {
- macros.push_back(imacro_to);
- outcome = identify_macro_self_swap_affected_macros(macros, imacro_to, swap_offset);
- }
- }
- }
- return e_find_affected_blocks_result::VALID;
-}
-
-//Moves the macro imacro by the specified offset
-//
-//Records the block movements in block_moves, the other blocks displaced in displaced_blocks,
-//and any generated empty locations in empty_locations.
-//
-//This function moves a single macro and does not check for overlap with other macros!
-static e_find_affected_blocks_result record_macro_move(std::vector<ClusterBlockId>& displaced_blocks,
- const int imacro,
- t_pl_offset swap_offset) {
- auto& place_ctx = g_vpr_ctx.placement();
-
- for (const t_pl_macro_member& member : place_ctx.pl_macros[imacro].members) {
- t_pl_loc from = place_ctx.block_locs[member.blk_index].loc;
-
- t_pl_loc to = from + swap_offset;
-
- if (!is_legal_swap_to_location(member.blk_index, to)) {
- log_move_abort("macro move to location illegal");
- return e_find_affected_blocks_result::ABORT;
- }
-
- ClusterBlockId blk_to = place_ctx.grid_blocks[to.x][to.y].blocks[to.z];
-
- record_block_move(member.blk_index, to);
-
- int imacro_to = -1;
- get_imacro_from_iblk(&imacro_to, blk_to, place_ctx.pl_macros);
- if (blk_to && imacro_to != imacro) { //Block displaced only if exists and not part of current macro
- displaced_blocks.push_back(blk_to);
- }
- }
- return e_find_affected_blocks_result::VALID;
-}
-
-static e_find_affected_blocks_result record_macro_self_swaps(const int imacro, t_pl_offset swap_offset) {
- auto& place_ctx = g_vpr_ctx.placement();
-
- //Reset any paritao move
- clear_move_blocks();
-
- //Collect the macros affected
- std::vector<int> affected_macros;
- auto outcome = identify_macro_self_swap_affected_macros(affected_macros, imacro,
- swap_offset);
-
- if (outcome != e_find_affected_blocks_result::VALID) {
- return outcome;
- }
-
- //Remove any duplicate macros
- affected_macros.resize(std::distance(affected_macros.begin(), std::unique(affected_macros.begin(), affected_macros.end())));
-
- std::vector<ClusterBlockId> displaced_blocks;
-
- //Move all the affected macros by the offset
- for (int imacro_affected : affected_macros) {
- outcome = record_macro_move(displaced_blocks, imacro_affected, swap_offset);
-
- if (outcome != e_find_affected_blocks_result::VALID) {
- return outcome;
- }
- }
-
- auto is_non_macro_block = [&](ClusterBlockId blk) {
- int imacro_blk = -1;
- get_imacro_from_iblk(&imacro_blk, blk, place_ctx.pl_macros);
-
- if (std::find(affected_macros.begin(), affected_macros.end(), imacro_blk) != affected_macros.end()) {
- return false;
- }
- return true;
- };
-
- std::vector<ClusterBlockId> non_macro_displaced_blocks;
- std::copy_if(displaced_blocks.begin(), displaced_blocks.end(), std::back_inserter(non_macro_displaced_blocks), is_non_macro_block);
-
- //Based on the currently queued block moves, find the empty 'holes' left behind
- auto empty_locs = determine_locations_emptied_by_move();
-
- VTR_ASSERT_SAFE(empty_locs.size() >= non_macro_displaced_blocks.size());
-
- //Fit the displaced blocks into the empty locations
- auto loc_itr = empty_locs.begin();
- for (auto blk : non_macro_displaced_blocks) {
- outcome = record_block_move(blk, *loc_itr);
- ++loc_itr;
- }
-
- return outcome;
-}
-
-bool is_legal_swap_to_location(ClusterBlockId blk, t_pl_loc to) {
- //Make sure that the swap_to location is valid
- //It must be:
- // * on chip, and
- // * match the correct block type
- //
- //Note that we need to explicitly check that the types match, since the device floorplan is not
- //(neccessarily) translationally invariant for an arbitrary macro
-
- auto& device_ctx = g_vpr_ctx.device();
-
- if (to.x < 0 || to.x >= int(device_ctx.grid.width())
- || to.y < 0 || to.y >= int(device_ctx.grid.height())
- || to.z < 0 || to.z >= device_ctx.grid[to.x][to.y].type->capacity
- || (device_ctx.grid[to.x][to.y].type != physical_tile_type(blk))) {
- return false;
- }
- return true;
-}
-
-//Examines the currently proposed move and determine any empty locations
-std::set<t_pl_loc> determine_locations_emptied_by_move() {
- std::set<t_pl_loc> moved_from;
- std::set<t_pl_loc> moved_to;
-
- for (int iblk = 0; iblk < blocks_affected.num_moved_blocks; ++iblk) {
- //When a block is moved it's old location becomes free
- moved_from.emplace(blocks_affected.moved_blocks[iblk].old_loc);
-
- //But any block later moved to a position fills it
- moved_to.emplace(blocks_affected.moved_blocks[iblk].new_loc);
- }
-
- std::set<t_pl_loc> empty_locs;
- std::set_difference(moved_from.begin(), moved_from.end(),
- moved_to.begin(), moved_to.end(),
- std::inserter(empty_locs, empty_locs.begin()));
-
- return empty_locs;
-}
-
-static e_swap_result try_swap(float t,
+static e_move_result try_swap(float t,
t_placer_costs* costs,
t_placer_prev_inverse_costs* prev_inverse_costs,
float rlim,
MoveGenerator& move_generator,
+ t_pl_blocks_to_be_moved& blocks_affected,
const PlaceDelayModel* delay_model,
float rlim_escape_fraction,
enum e_place_algorithm place_algorithm,
@@ -1800,6 +1203,8 @@
num_ts_called++;
+ MoveOutcomeStats move_outcome_stats;
+
/* I'm using negative values of temp_net_cost as a flag, so DO NOT *
* use cost functions that can go negative. */
@@ -1813,85 +1218,100 @@
rlim = std::numeric_limits<float>::infinity();
}
- //Generate a new move used to explore the space of possible placements
- e_propose_move move_outcome = move_generator.propose_move(blocks_affected, rlim);
+ //Generate a new move (perturbation) used to explore the space of possible placements
+ e_create_move create_move_outcome = move_generator.propose_move(blocks_affected, rlim);
LOG_MOVE_STATS_PROPOSED(t, blocks_affected);
- if (move_outcome == e_propose_move::ABORT) {
+ e_move_result move_outcome = ABORTED;
+
+ if (create_move_outcome == e_create_move::ABORT) {
//Proposed move is not legal -- give up on this move
- clear_move_blocks();
+ clear_move_blocks(blocks_affected);
LOG_MOVE_STATS_OUTCOME(std::numeric_limits<float>::quiet_NaN(),
std::numeric_limits<float>::quiet_NaN(),
std::numeric_limits<float>::quiet_NaN(),
"ABORTED", "illegal move");
- return ABORTED;
- }
-
- VTR_ASSERT(move_outcome == e_propose_move::VALID);
-
- /*
- * To make evaluating the move simpler (e.g. calculating changed bounding box),
- * we first move the blocks to thier new locations (apply the move to
- * place_ctx.block_locs) and then computed the change in cost. If the move is
- * accepted, the inverse look-up in place_ctx.grid_blocks is updated (committing
- * the move). If the move is rejected the blocks are returned to their original
- * positions (reverting place_ctx.block_locs to its original state).
- *
- * Note that the inverse look-up place_ctx.block_locs is only updated until
- * after move acceptance is determined, and so should not be used when
- * evaluating a move.
- */
-
- //Update the block positions
- apply_move_blocks();
-
- // Find all the nets affected by this swap and update their costs
- int num_nets_affected = find_affected_nets_and_update_costs(place_algorithm, delay_model, bb_delta_c, timing_delta_c);
-
- if (place_algorithm == PATH_TIMING_DRIVEN_PLACE) {
- /*in this case we redefine delta_c as a combination of timing and bb. *
- *additionally, we normalize all values, therefore delta_c is in *
- *relation to 1*/
-
- delta_c = (1 - timing_tradeoff) * bb_delta_c * prev_inverse_costs->bb_cost
- + timing_tradeoff * timing_delta_c * prev_inverse_costs->timing_cost;
+ move_outcome = ABORTED;
} else {
- delta_c = bb_delta_c;
- }
+ VTR_ASSERT(create_move_outcome == e_create_move::VALID);
- /* 1 -> move accepted, 0 -> rejected. */
- e_swap_result keep_switch = assess_swap(delta_c, t);
+ /*
+ * To make evaluating the move simpler (e.g. calculating changed bounding box),
+ * we first move the blocks to thier new locations (apply the move to
+ * place_ctx.block_locs) and then computed the change in cost. If the move is
+ * accepted, the inverse look-up in place_ctx.grid_blocks is updated (committing
+ * the move). If the move is rejected the blocks are returned to their original
+ * positions (reverting place_ctx.block_locs to its original state).
+ *
+ * Note that the inverse look-up place_ctx.grid_blocks is only updated
+ * after move acceptance is determined, and so should not be used when
+ * evaluating a move.
+ */
- if (keep_switch == ACCEPTED) {
- costs->cost += delta_c;
- costs->bb_cost += bb_delta_c;
+ //Update the block positions
+ apply_move_blocks(blocks_affected);
+ // Find all the nets affected by this swap and update their costs
+ int num_nets_affected = find_affected_nets_and_update_costs(place_algorithm, blocks_affected, delay_model, bb_delta_c, timing_delta_c);
if (place_algorithm == PATH_TIMING_DRIVEN_PLACE) {
- /*update the point_to_point_timing_cost and point_to_point_delay
- * values from the temporary values */
- costs->timing_cost += timing_delta_c;
+ /*in this case we redefine delta_c as a combination of timing and bb. *
+ *additionally, we normalize all values, therefore delta_c is in *
+ *relation to 1*/
- update_td_cost();
+ delta_c = (1 - timing_tradeoff) * bb_delta_c * prev_inverse_costs->bb_cost
+ + timing_tradeoff * timing_delta_c * prev_inverse_costs->timing_cost;
+ } else {
+ delta_c = bb_delta_c;
}
- /* update net cost functions and reset flags. */
- update_move_nets(num_nets_affected);
+ /* 1 -> move accepted, 0 -> rejected. */
+ move_outcome = assess_swap(delta_c, t);
- /* Update clb data structures since we kept the move. */
- commit_move_blocks();
+ if (move_outcome == ACCEPTED) {
+ costs->cost += delta_c;
+ costs->bb_cost += bb_delta_c;
- } else { /* Move was rejected. */
- /* Reset the net cost function flags first. */
- reset_move_nets(num_nets_affected);
+ if (place_algorithm == PATH_TIMING_DRIVEN_PLACE) {
+ /*update the point_to_point_timing_cost and point_to_point_delay
+ * values from the temporary values */
+ costs->timing_cost += timing_delta_c;
- /* Restore the place_ctx.block_locs data structures to their state before the move. */
- revert_move_blocks();
+ update_td_cost(blocks_affected);
+ }
+
+ /* update net cost functions and reset flags. */
+ update_move_nets(num_nets_affected);
+
+ /* Update clb data structures since we kept the move. */
+ commit_move_blocks(blocks_affected);
+
+ } else { /* Move was rejected. */
+ /* Reset the net cost function flags first. */
+ reset_move_nets(num_nets_affected);
+
+ /* Restore the place_ctx.block_locs data structures to their state before the move. */
+ revert_move_blocks(blocks_affected);
+ }
+
+ move_outcome_stats.delta_cost_norm = delta_c;
+ move_outcome_stats.delta_bb_cost_norm = bb_delta_c * prev_inverse_costs->bb_cost;
+ move_outcome_stats.delta_timing_cost_norm = timing_delta_c * prev_inverse_costs->timing_cost;
+
+ move_outcome_stats.delta_bb_cost_abs = bb_delta_c;
+ move_outcome_stats.delta_timing_cost_abs = timing_delta_c;
+
+ LOG_MOVE_STATS_OUTCOME(delta_c, bb_delta_c, timing_delta_c,
+ (move_outcome ? "ACCEPTED" : "REJECTED"), "");
}
- clear_move_blocks();
+ move_outcome_stats.outcome = move_outcome;
+
+ move_generator.process_outcome(move_outcome_stats);
+
+ clear_move_blocks(blocks_affected);
//VTR_ASSERT(check_macro_placement_consistency() == 0);
#if 0
@@ -1899,50 +1319,18 @@
check_place(*costs, delay_model, place_algorithm);
#endif
- LOG_MOVE_STATS_OUTCOME(delta_c, bb_delta_c, timing_delta_c,
- (keep_switch ? "ACCEPTED" : "REJECTED"), "");
- return (keep_switch);
-}
-
-//Pick a random block to be swapped with another random block.
-//If none is found return ClusterBlockId::INVALID()
-static ClusterBlockId pick_from_block() {
- /* Some blocks may be fixed, and should never be moved from their *
- * initial positions. If we randomly selected such a block try *
- * another random block. *
- * *
- * We need to track the blocks we have tried to avoid an infinite *
- * loop if all blocks are fixed. */
- auto& cluster_ctx = g_vpr_ctx.clustering();
- auto& place_ctx = g_vpr_ctx.mutable_placement();
-
- std::unordered_set<ClusterBlockId> tried_from_blocks;
-
- //So long as untried blocks remain
- while (tried_from_blocks.size() < cluster_ctx.clb_nlist.blocks().size()) {
- //Pick a block at random
- ClusterBlockId b_from = ClusterBlockId(vtr::irand((int)cluster_ctx.clb_nlist.blocks().size() - 1));
-
- //Record it as tried
- tried_from_blocks.insert(b_from);
-
- if (place_ctx.block_locs[b_from].is_fixed) {
- continue; //Fixed location, try again
- }
-
- //Found a movable block
- return b_from;
- }
-
- //No movable blocks found
- return ClusterBlockId::INVALID();
+ return (move_outcome);
}
//Puts all the nets changed by the current swap into nets_to_update,
//and updates their bounding box.
//
//Returns the number of affected nets.
-static int find_affected_nets_and_update_costs(e_place_algorithm place_algorithm, const PlaceDelayModel* delay_model, double& bb_delta_c, double& timing_delta_c) {
+static int find_affected_nets_and_update_costs(e_place_algorithm place_algorithm,
+ const t_pl_blocks_to_be_moved& blocks_affected,
+ const PlaceDelayModel* delay_model,
+ double& bb_delta_c,
+ double& timing_delta_c) {
VTR_ASSERT_SAFE(bb_delta_c == 0.);
VTR_ASSERT_SAFE(timing_delta_c == 0.);
auto& cluster_ctx = g_vpr_ctx.clustering();
@@ -1968,11 +1356,11 @@
//
//Do not update the net cost here since it should only be updated
//once per net, not once per pin.
- update_net_bb(net_id, iblk, blk, blk_pin);
+ update_net_bb(net_id, blocks_affected, iblk, blk, blk_pin);
if (place_algorithm == PATH_TIMING_DRIVEN_PLACE) {
//Determine the change in timing costs if required
- update_td_delta_costs(delay_model, net_id, blk_pin, timing_delta_c);
+ update_td_delta_costs(delay_model, blocks_affected, net_id, blk_pin, timing_delta_c);
}
}
}
@@ -2002,7 +1390,11 @@
}
}
-static void update_net_bb(const ClusterNetId net, int iblk, const ClusterBlockId blk, const ClusterPinId blk_pin) {
+static void update_net_bb(const ClusterNetId net,
+ const t_pl_blocks_to_be_moved& blocks_affected,
+ int iblk,
+ const ClusterBlockId blk,
+ const ClusterPinId blk_pin) {
auto& cluster_ctx = g_vpr_ctx.clustering();
if (cluster_ctx.clb_nlist.net_sinks(net).size() < SMALL_NET) {
@@ -2029,7 +1421,7 @@
}
}
-static void update_td_delta_costs(const PlaceDelayModel* delay_model, const ClusterNetId net, const ClusterPinId pin, double& delta_timing_cost) {
+static void update_td_delta_costs(const PlaceDelayModel* delay_model, const t_pl_blocks_to_be_moved& blocks_affected, const ClusterNetId net, const ClusterPinId pin, double& delta_timing_cost) {
auto& cluster_ctx = g_vpr_ctx.clustering();
if (cluster_ctx.clb_nlist.pin_type(pin) == PinType::DRIVER) {
@@ -2052,7 +1444,7 @@
//
//Computing it here would double count the change, and mess up the
//delta_timing_cost value.
- if (!driven_by_moved_block(net)) {
+ if (!driven_by_moved_block(net, blocks_affected)) {
int net_pin = cluster_ctx.clb_nlist.pin_net_index(pin);
float temp_delay = comp_td_point_to_point_delay(delay_model, net, net_pin);
@@ -2064,139 +1456,7 @@
}
}
-static bool find_to(t_physical_tile_type_ptr type, float rlim, const t_pl_loc from, t_pl_loc& to) {
- //Finds a legal swap to location for the given type, starting from 'x_from' and 'y_from'
- //
- //Note that the range limit (rlim) is applied in a logical sense (i.e. 'compressed' grid space consisting
- //of the same block types, and not the physical grid space). This means, for example, that columns of 'rare'
- //blocks (e.g. DSPs/RAMs) which are physically far appart but logically adjacent will be swappable even
- //at an rlim fo 1.
- //
- //This ensures that such blocks don't get locked down too early during placement (as would be the
- //case with a physical distance rlim)
- auto& grid = g_vpr_ctx.device().grid;
-
- auto grid_type = grid[from.x][from.y].type;
- VTR_ASSERT(type == grid_type);
-
- //Retrieve the compressed block grid for this block type
- const auto& compressed_block_grid = f_compressed_block_grids[type->index];
-
- //Determine the rlim in each dimension
- int rlim_x = min<int>(compressed_block_grid.compressed_to_grid_x.size(), rlim);
- int rlim_y = min<int>(compressed_block_grid.compressed_to_grid_y.size(), rlim); /* for aspect_ratio != 1 case. */
-
- //Determine the coordinates in the compressed grid space of the current block
- int cx_from = grid_to_compressed(compressed_block_grid.compressed_to_grid_x, from.x);
- int cy_from = grid_to_compressed(compressed_block_grid.compressed_to_grid_y, from.y);
-
- //Determin the valid compressed grid location ranges
- int min_cx = std::max(0, cx_from - rlim_x);
- int max_cx = std::min<int>(compressed_block_grid.compressed_to_grid_x.size() - 1, cx_from + rlim_x);
- int delta_cx = max_cx - min_cx;
-
- int min_cy = std::max(0, cy_from - rlim_y);
- int max_cy = std::min<int>(compressed_block_grid.compressed_to_grid_y.size() - 1, cy_from + rlim_y);
-
- int cx_to = OPEN;
- int cy_to = OPEN;
- std::unordered_set<int> tried_cx_to;
- bool legal = false;
- while (!legal && (int)tried_cx_to.size() < delta_cx) { //Until legal or all possibilities exhaused
- //Pick a random x-location within [min_cx, max_cx],
- //until we find a legal swap, or have exhuasted all possiblites
- cx_to = min_cx + vtr::irand(delta_cx);
-
- VTR_ASSERT(cx_to >= min_cx);
- VTR_ASSERT(cx_to <= max_cx);
-
- //Record this x location as tried
- auto res = tried_cx_to.insert(cx_to);
- if (!res.second) {
- continue; //Already tried this position
- }
-
- //Pick a random y location
- //
- //We are careful here to consider that there may be a sparse
- //set of candidate blocks in the y-axis at this x location.
- //
- //The candidates are stored in a flat_map so we can efficiently find the set of valid
- //candidates with upper/lower bound.
- auto y_lower_iter = compressed_block_grid.grid[cx_to].lower_bound(min_cy);
- if (y_lower_iter == compressed_block_grid.grid[cx_to].end()) {
- continue;
- }
-
- auto y_upper_iter = compressed_block_grid.grid[cx_to].upper_bound(max_cy);
-
- if (y_lower_iter->first > min_cy) {
- //No valid blocks at this x location which are within rlim_y
- //
- //Fall back to allow the whole y range
- y_lower_iter = compressed_block_grid.grid[cx_to].begin();
- y_upper_iter = compressed_block_grid.grid[cx_to].end();
-
- min_cy = y_lower_iter->first;
- max_cy = (y_upper_iter - 1)->first;
- }
-
- int y_range = std::distance(y_lower_iter, y_upper_iter);
- VTR_ASSERT(y_range >= 0);
-
- //At this point we know y_lower_iter and y_upper_iter
- //bound the range of valid blocks at this x-location, which
- //are within rlim_y
- std::unordered_set<int> tried_dy;
- while (!legal && (int)tried_dy.size() < y_range) { //Until legal or all possibilities exhausted
- //Randomly pick a y location
- int dy = vtr::irand(y_range - 1);
-
- //Record this y location as tried
- auto res2 = tried_dy.insert(dy);
- if (!res2.second) {
- continue; //Already tried this position
- }
-
- //Key in the y-dimension is the compressed index location
- cy_to = (y_lower_iter + dy)->first;
-
- VTR_ASSERT(cy_to >= min_cy);
- VTR_ASSERT(cy_to <= max_cy);
-
- if (cx_from == cx_to && cy_from == cy_to) {
- continue; //Same from/to location -- try again for new y-position
- } else {
- legal = true;
- }
- }
- }
-
- if (!legal) {
- //No valid position found
- return false;
- }
-
- VTR_ASSERT(cx_to != OPEN);
- VTR_ASSERT(cy_to != OPEN);
-
- //Convert to true (uncompressed) grid locations
- to.x = compressed_block_grid.compressed_to_grid_x[cx_to];
- to.y = compressed_block_grid.compressed_to_grid_y[cy_to];
-
- //Each x/y location contains only a single type, so we can pick a random
- //z (capcity) location
- to.z = vtr::irand(type->capacity - 1);
-
- auto& device_ctx = g_vpr_ctx.device();
- VTR_ASSERT_MSG(device_ctx.grid[to.x][to.y].type == type, "Type must match");
- VTR_ASSERT_MSG(device_ctx.grid[to.x][to.y].width_offset == 0, "Should be at block base location");
- VTR_ASSERT_MSG(device_ctx.grid[to.x][to.y].height_offset == 0, "Should be at block base location");
-
- return true;
-}
-
-static e_swap_result assess_swap(double delta_c, double t) {
+static e_move_result assess_swap(double delta_c, double t) {
/* Returns: 1 -> move accepted, 0 -> rejected. */
if (delta_c <= 0) {
return ACCEPTED;
@@ -2299,7 +1559,7 @@
/* Update the point_to_point_timing_cost values from the temporary *
* values for all connections that have changed. */
-static void update_td_cost() {
+static void update_td_cost(const t_pl_blocks_to_be_moved& blocks_affected) {
auto& cluster_ctx = g_vpr_ctx.clustering();
/* Go through all the blocks moved. */
@@ -2325,7 +1585,7 @@
VTR_ASSERT_SAFE(cluster_ctx.clb_nlist.pin_type(pin_id) == PinType::SINK);
/* The following "if" prevents the value from being updated twice. */
- if (!driven_by_moved_block(net_id)) {
+ if (!driven_by_moved_block(net_id, blocks_affected)) {
int net_pin = cluster_ctx.clb_nlist.pin_net_index(pin_id);
point_to_point_delay[net_id][net_pin] = temp_point_to_point_delay[net_id][net_pin];
@@ -2338,7 +1598,7 @@
} /* Finished going through all the blocks moved */
}
-static bool driven_by_moved_block(const ClusterNetId net) {
+static bool driven_by_moved_block(const ClusterNetId net, const t_pl_blocks_to_be_moved& blocks_affected) {
auto& cluster_ctx = g_vpr_ctx.clustering();
ClusterBlockId net_driver_block = cluster_ctx.clb_nlist.net_driver_block(net);
@@ -2583,101 +1843,8 @@
ts_bb_edge_new.resize(num_nets, t_bb());
ts_nets_to_update.resize(num_nets, ClusterNetId::INVALID());
- /* Allocate with size cluster_ctx.clb_nlist.blocks().size() for any number of moved blocks. */
- blocks_affected.moved_blocks = std::vector<t_pl_moved_block>(cluster_ctx.clb_nlist.blocks().size());
- blocks_affected.num_moved_blocks = 0;
-
- f_compressed_block_grids = create_compressed_block_grids();
-}
-
-static std::vector<t_compressed_block_grid> create_compressed_block_grids() {
- auto& device_ctx = g_vpr_ctx.device();
- auto& grid = device_ctx.grid;
-
- //Collect the set of x/y locations for each instace of a block type
- std::vector<std::vector<vtr::Point<int>>> block_locations(device_ctx.physical_tile_types.size());
- for (size_t x = 0; x < grid.width(); ++x) {
- for (size_t y = 0; y < grid.height(); ++y) {
- const t_grid_tile& tile = grid[x][y];
- if (tile.width_offset == 0 && tile.height_offset == 0) {
- //Only record at block root location
- block_locations[tile.type->index].emplace_back(x, y);
- }
- }
- }
-
- std::vector<t_compressed_block_grid> compressed_type_grids(device_ctx.physical_tile_types.size());
- for (const auto& type : device_ctx.physical_tile_types) {
- compressed_type_grids[type.index] = create_compressed_block_grid(block_locations[type.index]);
- }
-
- return compressed_type_grids;
-}
-
-//Given a set of locations, returns a 2D matrix in a compressed space
-static t_compressed_block_grid create_compressed_block_grid(const std::vector<vtr::Point<int>>& locations) {
- t_compressed_block_grid compressed_grid;
-
- if (locations.empty()) {
- return compressed_grid;
- }
-
- {
- std::vector<int> x_locs;
- std::vector<int> y_locs;
-
- //Record all the x/y locations seperately
- for (auto point : locations) {
- x_locs.emplace_back(point.x());
- y_locs.emplace_back(point.y());
- }
-
- //Uniquify x/y locations
- std::sort(x_locs.begin(), x_locs.end());
- x_locs.erase(unique(x_locs.begin(), x_locs.end()), x_locs.end());
-
- std::sort(y_locs.begin(), y_locs.end());
- y_locs.erase(unique(y_locs.begin(), y_locs.end()), y_locs.end());
-
- //The index of an x-position in x_locs corresponds to it's compressed
- //x-coordinate (similarly for y)
- compressed_grid.compressed_to_grid_x = x_locs;
- compressed_grid.compressed_to_grid_y = y_locs;
- }
-
- //
- //Build the compressed grid
- //
-
- //Create a full/dense x-dimension (since there must be at least one
- //block per x location)
- compressed_grid.grid.resize(compressed_grid.compressed_to_grid_x.size());
-
- //Fill-in the y-dimensions
- //
- //Note that we build the y-dimension sparsely (using a flat map), since
- //there may not be full columns of blocks at each x location, this makes
- //it efficient to find the non-empty blocks in the y dimension
- for (auto point : locations) {
- //Determine the compressed indices in the x & y dimensions
- auto x_itr = std::lower_bound(compressed_grid.compressed_to_grid_x.begin(), compressed_grid.compressed_to_grid_x.end(), point.x());
- int cx = std::distance(compressed_grid.compressed_to_grid_x.begin(), x_itr);
-
- auto y_itr = std::lower_bound(compressed_grid.compressed_to_grid_y.begin(), compressed_grid.compressed_to_grid_y.end(), point.y());
- int cy = std::distance(compressed_grid.compressed_to_grid_y.begin(), y_itr);
-
- VTR_ASSERT(cx >= 0 && cx < (int)compressed_grid.compressed_to_grid_x.size());
- VTR_ASSERT(cy >= 0 && cy < (int)compressed_grid.compressed_to_grid_y.size());
-
- VTR_ASSERT(compressed_grid.compressed_to_grid_x[cx] == point.x());
- VTR_ASSERT(compressed_grid.compressed_to_grid_y[cy] == point.y());
-
- auto result = compressed_grid.grid[cx].insert(std::make_pair(cy, t_type_loc(point.x(), point.y())));
-
- VTR_ASSERT_MSG(result.second, "Duplicates should not exist in compressed grid space");
- }
-
- return compressed_grid;
+ auto& place_ctx = g_vpr_ctx.mutable_placement();
+ place_ctx.compressed_block_grids = create_compressed_block_grids();
}
/* This routine finds the bounding box of each net from scratch (i.e. *
@@ -3695,9 +2862,7 @@
#endif
static void free_try_swap_arrays() {
- blocks_affected.moved_blocks.clear();
- blocks_affected.num_moved_blocks = 0;
- f_compressed_block_grids.clear();
+ g_vpr_ctx.mutable_placement().compressed_block_grids.clear();
}
static void calc_placer_stats(t_placer_statistics& stats, float& success_rat, double& std_dev, const t_placer_costs& costs, const int move_lim) {
@@ -3741,31 +2906,6 @@
}
#endif
-#ifdef DEBUG_ABORTED_MOVES
-static void log_move_abort(std::string reason) {
- ++f_move_abort_reasons[reason];
-#else
-static void log_move_abort(std::string /*reason*/) {
-#endif
-}
-
-static void report_aborted_moves() {
-#ifdef DEBUG_ABORTED_MOVES
- VTR_LOG("\n");
- VTR_LOG("Aborted Move Reasons:\n");
- for (auto kv : f_move_abort_reasons) {
- VTR_LOG(" %s: %zu\n", kv.first.c_str(), kv.second);
- }
-#endif
-}
-
-static int grid_to_compressed(const std::vector<int>& coords, int point) {
- auto itr = std::lower_bound(coords.begin(), coords.end(), point);
- VTR_ASSERT(*itr == point);
-
- return std::distance(coords.begin(), itr);
-}
-
static void print_place_status_header() {
VTR_LOG("------- ------- ---------- ---------- ------- ---------- -------- ------- ------- ------ -------- --------- ------\n");
VTR_LOG(" T Av Cost Av BB Cost Av TD Cost CPD sTNS sWNS Ac Rate Std Dev R lim Crit Exp Tot Moves Alpha\n");
@@ -3798,39 +2938,3 @@
VTR_LOG(" %6.3f\n", t / oldt);
fflush(stdout);
}
-
-e_propose_move UniformMoveGenerator::propose_move(t_pl_blocks_to_be_moved& /*affected_blocks*/, float rlim) {
- /* Pick a random block to be swapped with another random block. */
- ClusterBlockId b_from = pick_from_block();
- if (!b_from) {
- return e_propose_move::ABORT; //No movable block found
- }
-
- auto& place_ctx = g_vpr_ctx.placement();
- auto& cluster_ctx = g_vpr_ctx.clustering();
-
- t_pl_loc from = place_ctx.block_locs[b_from].loc;
- auto cluster_from_type = cluster_ctx.clb_nlist.block_type(b_from);
- auto grid_from_type = g_vpr_ctx.device().grid[from.x][from.y].type;
- VTR_ASSERT(physical_tile_type(cluster_from_type) == grid_from_type);
-
- t_pl_loc to;
- if (!find_to(physical_tile_type(b_from), rlim, from, to)) {
- return e_propose_move::ABORT;
- }
-
-#if 0
- auto& grid = g_vpr_ctx.device().grid;
- VTR_LOG( "swap [%d][%d][%d] %s block %zu \"%s\" <=> [%d][%d][%d] %s block ",
- from.x, from.y, from.z, grid[from.x][from.y].type->name, size_t(b_from), (b_from ? cluster_ctx.clb_nlist.block_name(b_from).c_str() : ""),
- to.x, to.y, to.z, grid[to.x][to.y].type->name);
- if (b_to) {
- VTR_LOG("%zu \"%s\"", size_t(b_to), cluster_ctx.clb_nlist.block_name(b_to).c_str());
- } else {
- VTR_LOG("(EMPTY)");
- }
- VTR_LOG("\n");
-#endif
-
- return ::propose_move(b_from, to);
-}
diff --git a/vpr/src/place/place_delay_model.h b/vpr/src/place/place_delay_model.h
index 6e4b161..f2412b1 100644
--- a/vpr/src/place/place_delay_model.h
+++ b/vpr/src/place/place_delay_model.h
@@ -4,30 +4,62 @@
#include "vtr_ndmatrix.h"
#include "vtr_flat_map.h"
#include "vpr_types.h"
-#include "router_lookahead_map.h"
+#include "router_delay_profiling.h"
//Abstract interface to a placement delay model
class PlaceDelayModel {
public:
virtual ~PlaceDelayModel() = default;
+ // Computes place delay model.
+ virtual void compute(
+ const RouterDelayProfiler& route_profiler,
+ const t_placer_opts& placer_opts,
+ const t_router_opts& router_opts,
+ int longest_length)
+ = 0;
+
//Returns the delay estimate between the specified block pins
+ //
+ // Either compute or read methods must be invoked before invoking
+ // delay.
virtual float delay(int from_x, int from_y, int from_pin, int to_x, int to_y, int to_pin) const = 0;
//Dumps the delay model to an echo file
virtual void dump_echo(std::string filename) const = 0;
+
+ // Write place delay model to specified file.
+ // May be unimplemented, in which case method should throw an exception.
+ virtual void write(const std::string& file) const = 0;
+
+ // Read place delay model from specified file.
+ // May be unimplemented, in which case method should throw an exception.
+ virtual void read(const std::string& file) = 0;
};
//A simple delay model based on the distance (delta) between block locations
class DeltaDelayModel : public PlaceDelayModel {
public:
+ DeltaDelayModel() {}
DeltaDelayModel(vtr::Matrix<float> delta_delays, t_router_opts router_opts)
: delays_(std::move(delta_delays))
, router_opts_(router_opts) {}
+ void compute(
+ const RouterDelayProfiler& router,
+ const t_placer_opts& placer_opts,
+ const t_router_opts& router_opts,
+ int longest_length) override;
float delay(int from_x, int from_y, int /*from_pin*/, int to_x, int to_y, int /*to_pin*/) const override;
void dump_echo(std::string filepath) const override;
+ void read(const std::string& /*file*/) override {
+ VPR_THROW(VPR_ERROR_ROUTE, "DeltaDelayModel::read unimplemented");
+ }
+ void write(const std::string& /*file*/) const override {
+ VPR_THROW(VPR_ERROR_ROUTE, "DeltaDelayModel::write unimplemented");
+ }
+
private:
vtr::Matrix<float> delays_;
t_router_opts router_opts_;
@@ -35,19 +67,28 @@
class OverrideDelayModel : public PlaceDelayModel {
public:
- OverrideDelayModel(std::unique_ptr<PlaceDelayModel> base_delay_model, t_router_opts router_opts)
- : base_delay_model_(std::move(base_delay_model))
- , router_opts_(router_opts) {}
-
+ void compute(
+ const RouterDelayProfiler& route_profiler,
+ const t_placer_opts& placer_opts,
+ const t_router_opts& router_opts,
+ int longest_length) override;
float delay(int from_x, int from_y, int from_pin, int to_x, int to_y, int to_pin) const override;
void dump_echo(std::string filepath) const override;
- public: //Mutators
- void set_delay_override(int from_type, int from_class, int to_type, int to_class, int delta_x, int delta_y, float delay);
+ void read(const std::string& /*file*/) override {
+ VPR_THROW(VPR_ERROR_ROUTE, "OverrideDelayModel::read unimplemented");
+ }
+ void write(const std::string& /*file*/) const override {
+ VPR_THROW(VPR_ERROR_ROUTE, "OverrideDelayModel::write unimplemented");
+ }
+ public: //Mutators
private:
std::unique_ptr<PlaceDelayModel> base_delay_model_;
+ void set_delay_override(int from_type, int from_class, int to_type, int to_class, int delta_x, int delta_y, float delay);
+ void compute_override_delay_model(const RouterDelayProfiler& router);
+
struct t_override {
short from_type;
short to_type;
diff --git a/vpr/src/place/place_macro.cpp b/vpr/src/place/place_macro.cpp
index 28ff305..4faeb1d 100644
--- a/vpr/src/place/place_macro.cpp
+++ b/vpr/src/place/place_macro.cpp
@@ -3,7 +3,6 @@
#include <cmath>
#include <sstream>
#include <map>
-using namespace std;
#include "vtr_assert.h"
#include "vtr_memory.h"
diff --git a/vpr/src/place/place_util.h b/vpr/src/place/place_util.h
index b9df578..f35ec85 100644
--- a/vpr/src/place/place_util.h
+++ b/vpr/src/place/place_util.h
@@ -1,5 +1,6 @@
#ifndef PLACE_UTIL_H
#define PLACE_UTIL_H
+#include <string>
//Initialize the placement context
void init_placement_context();
diff --git a/vpr/src/place/timing_place.cpp b/vpr/src/place/timing_place.cpp
index 3ae36d1..ab97a77 100644
--- a/vpr/src/place/timing_place.cpp
+++ b/vpr/src/place/timing_place.cpp
@@ -1,6 +1,5 @@
#include <cstdio>
#include <cmath>
-using namespace std;
#include "vtr_util.h"
#include "vtr_memory.h"
@@ -35,8 +34,8 @@
f_timing_place_crit.resize(cluster_ctx.clb_nlist.nets().size());
for (auto net_id : cluster_ctx.clb_nlist.nets()) {
- tmp_ptr = (float*)vtr::chunk_malloc((cluster_ctx.clb_nlist.net_sinks(net_id).size()) * sizeof(float), chunk_list_ptr);
- f_timing_place_crit[net_id] = tmp_ptr - 1; /* [1..num_sinks] */
+ tmp_ptr = (float*)vtr::chunk_malloc((cluster_ctx.clb_nlist.net_pins(net_id).size()) * sizeof(float), chunk_list_ptr);
+ f_timing_place_crit[net_id] = tmp_ptr;
}
}
diff --git a/vpr/src/place/timing_place_lookup.cpp b/vpr/src/place/timing_place_lookup.cpp
index 7e3b7b6..c3c4fac 100644
--- a/vpr/src/place/timing_place_lookup.cpp
+++ b/vpr/src/place/timing_place_lookup.cpp
@@ -3,7 +3,6 @@
#include <cmath>
#include <time.h>
#include <limits>
-using namespace std;
#include "vtr_assert.h"
#include "vtr_ndmatrix.h"
@@ -69,23 +68,43 @@
static t_chan_width setup_chan_width(const t_router_opts& router_opts,
t_chan_width_dist chan_width_dist);
-static float route_connection_delay(int source_x_loc, int source_y_loc, int sink_x_loc, int sink_y_loc, const t_router_opts& router_opts, bool measure_directconnect);
+static float route_connection_delay(
+ const RouterDelayProfiler& route_profiler,
+ int source_x_loc,
+ int source_y_loc,
+ int sink_x_loc,
+ int sink_y_loc,
+ const t_router_opts& router_opts,
+ bool measure_directconnect);
-static void generic_compute_matrix(vtr::Matrix<std::vector<float>>& matrix,
- int source_x,
- int source_y,
- int start_x,
- int start_y,
- int end_x,
- int end_y,
- const t_router_opts& router_opts,
- bool measure_directconnect);
+static void generic_compute_matrix(
+ const RouterDelayProfiler& route_profiler,
+ vtr::Matrix<std::vector<float>>& matrix,
+ int source_x,
+ int source_y,
+ int start_x,
+ int start_y,
+ int end_x,
+ int end_y,
+ const t_router_opts& router_opts,
+ bool measure_directconnect,
+ const std::set<std::string>& allowed_types);
-static vtr::Matrix<float> compute_delta_delays(const t_placer_opts& palcer_opts, const t_router_opts& router_opts, bool measure_directconnect, size_t longest_length);
+static vtr::Matrix<float> compute_delta_delays(
+ const RouterDelayProfiler& route_profiler,
+ const t_placer_opts& palcer_opts,
+ const t_router_opts& router_opts,
+ bool measure_directconnect,
+ size_t longest_length);
float delay_reduce(std::vector<float>& delays, e_reducer reducer);
-static vtr::Matrix<float> compute_delta_delay_model(const t_placer_opts& placer_opts, const t_router_opts& router_opts, bool measure_directconnect, int longest_length);
+static vtr::Matrix<float> compute_delta_delay_model(
+ const RouterDelayProfiler& route_profiler,
+ const t_placer_opts& placer_opts,
+ const t_router_opts& router_opts,
+ bool measure_directconnect,
+ int longest_length);
static bool find_direct_connect_sample_locations(const t_direct_inf* direct,
t_physical_tile_type_ptr from_type,
@@ -97,8 +116,6 @@
int* src_rr,
int* sink_rr);
-static std::unique_ptr<OverrideDelayModel> compute_override_delay_model(const t_router_opts& router_opts, std::unique_ptr<PlaceDelayModel> base_model);
-
static bool verify_delta_delays(const vtr::Matrix<float>& delta_delays);
static int get_longest_segment_length(std::vector<t_segment_inf>& segment_inf);
@@ -126,24 +143,33 @@
alloc_routing_structs(chan_width, router_opts, det_routing_arch, segment_inf,
directs, num_directs);
+ const RouterLookahead* router_lookahead = get_cached_router_lookahead(
+ router_opts.lookahead_type,
+ router_opts.write_router_lookahead,
+ router_opts.read_router_lookahead,
+ segment_inf);
+ RouterDelayProfiler route_profiler(router_lookahead);
+
int longest_length = get_longest_segment_length(segment_inf);
/*now setup and compute the actual arrays */
std::unique_ptr<PlaceDelayModel> place_delay_model;
- if (placer_opts.delay_model_type == PlaceDelayModelType::DELTA
- || placer_opts.delay_model_type == PlaceDelayModelType::DELTA_OVERRIDE) {
- bool measure_directconnect = (placer_opts.delay_model_type != PlaceDelayModelType::DELTA_OVERRIDE);
-
- auto delta_delays = compute_delta_delay_model(placer_opts, router_opts, measure_directconnect, longest_length);
- place_delay_model = std::make_unique<DeltaDelayModel>(std::move(delta_delays), router_opts);
-
+ if (placer_opts.delay_model_type == PlaceDelayModelType::DELTA) {
+ place_delay_model = std::make_unique<DeltaDelayModel>();
+ } else if (placer_opts.delay_model_type == PlaceDelayModelType::DELTA_OVERRIDE) {
+ place_delay_model = std::make_unique<OverrideDelayModel>();
} else {
VTR_ASSERT_MSG(false, "Invalid placer delay model");
}
- if (placer_opts.delay_model_type == PlaceDelayModelType::DELTA_OVERRIDE) {
- //Override direct-connect delays
- place_delay_model = compute_override_delay_model(router_opts, std::move(place_delay_model));
+ if (placer_opts.read_placement_delay_lookup.empty()) {
+ place_delay_model->compute(route_profiler, placer_opts, router_opts, longest_length);
+ } else {
+ place_delay_model->read(placer_opts.read_placement_delay_lookup);
+ }
+
+ if (!placer_opts.write_placement_delay_lookup.empty()) {
+ place_delay_model->write(placer_opts.write_placement_delay_lookup);
}
/*free all data structures that are no longer needed */
@@ -152,6 +178,34 @@
return place_delay_model;
}
+void DeltaDelayModel::compute(
+ const RouterDelayProfiler& route_profiler,
+ const t_placer_opts& placer_opts,
+ const t_router_opts& router_opts,
+ int longest_length) {
+ router_opts_ = router_opts;
+ delays_ = compute_delta_delay_model(
+ route_profiler,
+ placer_opts, router_opts, /*measure_directconnect=*/true,
+ longest_length);
+}
+
+void OverrideDelayModel::compute(
+ const RouterDelayProfiler& route_profiler,
+ const t_placer_opts& placer_opts,
+ const t_router_opts& router_opts,
+ int longest_length) {
+ router_opts_ = router_opts;
+ auto delays = compute_delta_delay_model(
+ route_profiler,
+ placer_opts, router_opts, /*measure_directconnect=*/false,
+ longest_length);
+
+ base_delay_model_ = std::make_unique<DeltaDelayModel>(delays, router_opts);
+
+ compute_override_delay_model(route_profiler);
+}
+
/******* File Accessible Functions **********/
std::vector<int> get_best_classes(enum e_pin_type pintype, t_physical_tile_type_ptr type) {
@@ -229,7 +283,14 @@
return init_chan(width_fac, chan_width_dist);
}
-static float route_connection_delay(int source_x, int source_y, int sink_x, int sink_y, const t_router_opts& router_opts, bool measure_directconnect) {
+static float route_connection_delay(
+ const RouterDelayProfiler& route_profiler,
+ int source_x,
+ int source_y,
+ int sink_x,
+ int sink_y,
+ const t_router_opts& router_opts,
+ bool measure_directconnect) {
//Routes between the source and sink locations and calculates the delay
float net_delay_value = IMPOSSIBLE_DELTA; /*set to known value for debug purposes */
@@ -261,9 +322,12 @@
continue;
}
- successfully_routed = calculate_delay(source_rr_node, sink_rr_node,
- router_opts,
- &net_delay_value);
+ {
+ successfully_routed = route_profiler.calculate_delay(
+ source_rr_node, sink_rr_node,
+ router_opts,
+ &net_delay_value);
+ }
if (successfully_routed) break;
}
@@ -278,15 +342,18 @@
return (net_delay_value);
}
-static void generic_compute_matrix(vtr::Matrix<std::vector<float>>& matrix,
- int source_x,
- int source_y,
- int start_x,
- int start_y,
- int end_x,
- int end_y,
- const t_router_opts& router_opts,
- bool measure_directconnect) {
+static void generic_compute_matrix(
+ const RouterDelayProfiler& route_profiler,
+ vtr::Matrix<std::vector<float>>& matrix,
+ int source_x,
+ int source_y,
+ int start_x,
+ int start_y,
+ int end_x,
+ int end_y,
+ const t_router_opts& router_opts,
+ bool measure_directconnect,
+ const std::set<std::string>& allowed_types) {
int delta_x, delta_y;
int sink_x, sink_y;
@@ -303,7 +370,9 @@
bool src_or_target_empty = (src_type == device_ctx.EMPTY_TYPE
|| sink_type == device_ctx.EMPTY_TYPE);
- if (src_or_target_empty) {
+ bool is_allowed_type = allowed_types.empty() || allowed_types.find(src_type->name) != allowed_types.end();
+
+ if (src_or_target_empty || !is_allowed_type) {
if (matrix[delta_x][delta_y].empty()) {
//Only set empty target if we don't already have a valid delta delay
matrix[delta_x][delta_y].push_back(EMPTY_DELTA);
@@ -318,7 +387,7 @@
} else {
//Valid start/end
- float delay = route_connection_delay(source_x, source_y, sink_x, sink_y, router_opts, measure_directconnect);
+ float delay = route_connection_delay(route_profiler, source_x, source_y, sink_x, sink_y, router_opts, measure_directconnect);
#ifdef VERBOSE
VTR_LOG("Computed delay: %12g delta: %d,%d (src: %d,%d sink: %d,%d)\n",
@@ -339,7 +408,12 @@
}
}
-static vtr::Matrix<float> compute_delta_delays(const t_placer_opts& placer_opts, const t_router_opts& router_opts, bool measure_directconnect, size_t longest_length) {
+static vtr::Matrix<float> compute_delta_delays(
+ const RouterDelayProfiler& route_profiler,
+ const t_placer_opts& placer_opts,
+ const t_router_opts& router_opts,
+ bool measure_directconnect,
+ size_t longest_length) {
//To avoid edge effects we place the source at least 'longest_length' away
//from the device edge
//and route from there for all possible delta values < dimension
@@ -357,6 +431,14 @@
size_t high_x = std::max(grid.width() - longest_length, mid_x);
size_t high_y = std::max(grid.height() - longest_length, mid_y);
+ std::set<std::string> allowed_types;
+ if (!placer_opts.allowed_tiles_for_delay_model.empty()) {
+ auto allowed_types_vector = vtr::split(placer_opts.allowed_tiles_for_delay_model, ",");
+ for (const auto& type : allowed_types_vector) {
+ allowed_types.insert(type);
+ }
+ }
+
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + | | +
// + A | B | C +
@@ -392,6 +474,9 @@
auto type = grid[x][y].type;
if (type != device_ctx.EMPTY_TYPE) {
+ if (!allowed_types.empty() && allowed_types.find(std::string(type->name)) == allowed_types.end()) {
+ continue;
+ }
src_type = type;
break;
}
@@ -405,12 +490,12 @@
#ifdef VERBOSE
VTR_LOG("Computing from lower left edge (%d,%d):\n", x, y);
#endif
- generic_compute_matrix(sampled_delta_delays,
+ generic_compute_matrix(route_profiler, sampled_delta_delays,
x, y,
x, y,
grid.width() - 1, grid.height() - 1,
router_opts,
- measure_directconnect);
+ measure_directconnect, allowed_types);
//Find the lowest x location on the bottom edge with a non-empty block
src_type = nullptr;
@@ -419,6 +504,9 @@
auto type = grid[x][y].type;
if (type != device_ctx.EMPTY_TYPE) {
+ if (!allowed_types.empty() && allowed_types.find(std::string(type->name)) == allowed_types.end()) {
+ continue;
+ }
src_type = type;
break;
}
@@ -431,60 +519,60 @@
#ifdef VERBOSE
VTR_LOG("Computing from left bottom edge (%d,%d):\n", x, y);
#endif
- generic_compute_matrix(sampled_delta_delays,
+ generic_compute_matrix(route_profiler, sampled_delta_delays,
x, y,
x, y,
grid.width() - 1, grid.height() - 1,
router_opts,
- measure_directconnect);
+ measure_directconnect, allowed_types);
//Since the other delta delay values may have suffered from edge effects,
//we recalculate deltas within regions B, C, E, F
#ifdef VERBOSE
VTR_LOG("Computing from low/low:\n");
#endif
- generic_compute_matrix(sampled_delta_delays,
+ generic_compute_matrix(route_profiler, sampled_delta_delays,
low_x, low_y,
low_x, low_y,
grid.width() - 1, grid.height() - 1,
router_opts,
- measure_directconnect);
+ measure_directconnect, allowed_types);
//Since the other delta delay values may have suffered from edge effects,
//we recalculate deltas within regions D, E, G, H
#ifdef VERBOSE
VTR_LOG("Computing from high/high:\n");
#endif
- generic_compute_matrix(sampled_delta_delays,
+ generic_compute_matrix(route_profiler, sampled_delta_delays,
high_x, high_y,
0, 0,
high_x, high_y,
router_opts,
- measure_directconnect);
+ measure_directconnect, allowed_types);
//Since the other delta delay values may have suffered from edge effects,
//we recalculate deltas within regions A, B, D, E
#ifdef VERBOSE
VTR_LOG("Computing from high/low:\n");
#endif
- generic_compute_matrix(sampled_delta_delays,
+ generic_compute_matrix(route_profiler, sampled_delta_delays,
high_x, low_y,
0, low_y,
high_x, grid.height() - 1,
router_opts,
- measure_directconnect);
+ measure_directconnect, allowed_types);
//Since the other delta delay values may have suffered from edge effects,
//we recalculate deltas within regions E, F, H, I
#ifdef VERBOSE
VTR_LOG("Computing from low/high:\n");
#endif
- generic_compute_matrix(sampled_delta_delays,
+ generic_compute_matrix(route_profiler, sampled_delta_delays,
low_x, high_y,
low_x, 0,
grid.width() - 1, high_y,
router_opts,
- measure_directconnect);
+ measure_directconnect, allowed_types);
vtr::Matrix<float> delta_delays({grid.width(), grid.height()});
for (size_t dx = 0; dx < sampled_delta_delays.dim_size(0); ++dx) {
@@ -626,9 +714,15 @@
}
}
-static vtr::Matrix<float> compute_delta_delay_model(const t_placer_opts& placer_opts, const t_router_opts& router_opts, bool measure_directconnect, int longest_length) {
+static vtr::Matrix<float> compute_delta_delay_model(
+ const RouterDelayProfiler& route_profiler,
+ const t_placer_opts& placer_opts,
+ const t_router_opts& router_opts,
+ bool measure_directconnect,
+ int longest_length) {
vtr::ScopedStartFinishTimer timer("Computing delta delays");
- vtr::Matrix<float> delta_delays = compute_delta_delays(placer_opts, router_opts, measure_directconnect, longest_length);
+ vtr::Matrix<float> delta_delays = compute_delta_delays(route_profiler,
+ placer_opts, router_opts, measure_directconnect, longest_length);
fix_uninitialized_coordinates(delta_delays);
@@ -761,10 +855,8 @@
return true;
}
-static std::unique_ptr<OverrideDelayModel> compute_override_delay_model(const t_router_opts& router_opts, std::unique_ptr<PlaceDelayModel> base_model) {
- auto delay_model = std::make_unique<OverrideDelayModel>(std::move(base_model), router_opts);
-
- t_router_opts router_opts2 = router_opts;
+void OverrideDelayModel::compute_override_delay_model(const RouterDelayProfiler& route_profiler) {
+ t_router_opts router_opts2 = router_opts_;
router_opts2.astar_fac = 0.;
//Look at all the direct connections that exist, and add overrides to delay model
@@ -824,10 +916,10 @@
VTR_ASSERT(sink_rr != OPEN);
float direct_connect_delay = std::numeric_limits<float>::quiet_NaN();
- bool found_routing_path = calculate_delay(src_rr, sink_rr, router_opts2, &direct_connect_delay);
+ bool found_routing_path = route_profiler.calculate_delay(src_rr, sink_rr, router_opts2, &direct_connect_delay);
if (found_routing_path) {
- delay_model->set_delay_override(from_type->index, from_pin_class, to_type->index, to_pin_class, direct->x_offset, direct->y_offset, direct_connect_delay);
+ set_delay_override(from_type->index, from_pin_class, to_type->index, to_pin_class, direct->x_offset, direct->y_offset, direct_connect_delay);
} else {
++missing_paths;
}
@@ -839,8 +931,6 @@
VTR_LOGV_WARN(missing_instances > 0, "Found no delta delay for %d bits of inter-block direct connect '%s' (no instances of this direct found)\n", missing_instances, direct->name);
VTR_LOGV_WARN(missing_paths > 0, "Found no delta delay for %d bits of inter-block direct connect '%s' (no routing path found)\n", missing_paths, direct->name);
}
-
- return delay_model;
}
bool directconnect_exists(int src_rr_node, int sink_rr_node) {
diff --git a/vpr/src/place/uniform_move_generator.cpp b/vpr/src/place/uniform_move_generator.cpp
new file mode 100644
index 0000000..b296041
--- /dev/null
+++ b/vpr/src/place/uniform_move_generator.cpp
@@ -0,0 +1,38 @@
+#include "uniform_move_generator.h"
+#include "globals.h"
+
+e_create_move UniformMoveGenerator::propose_move(t_pl_blocks_to_be_moved& blocks_affected, float rlim) {
+ /* Pick a random block to be swapped with another random block. */
+ ClusterBlockId b_from = pick_from_block();
+ if (!b_from) {
+ return e_create_move::ABORT; //No movable block found
+ }
+
+ auto& place_ctx = g_vpr_ctx.placement();
+ auto& cluster_ctx = g_vpr_ctx.clustering();
+
+ t_pl_loc from = place_ctx.block_locs[b_from].loc;
+ auto cluster_from_type = cluster_ctx.clb_nlist.block_type(b_from);
+ auto grid_from_type = g_vpr_ctx.device().grid[from.x][from.y].type;
+ VTR_ASSERT(physical_tile_type(cluster_from_type) == grid_from_type);
+
+ t_pl_loc to;
+ if (!find_to_loc_uniform(physical_tile_type(b_from), rlim, from, to)) {
+ return e_create_move::ABORT;
+ }
+
+#if 0
+ auto& grid = g_vpr_ctx.device().grid;
+ VTR_LOG( "swap [%d][%d][%d] %s block %zu \"%s\" <=> [%d][%d][%d] %s block ",
+ from.x, from.y, from.z, grid[from.x][from.y].type->name, size_t(b_from), (b_from ? cluster_ctx.clb_nlist.block_name(b_from).c_str() : ""),
+ to.x, to.y, to.z, grid[to.x][to.y].type->name);
+ if (b_to) {
+ VTR_LOG("%zu \"%s\"", size_t(b_to), cluster_ctx.clb_nlist.block_name(b_to).c_str());
+ } else {
+ VTR_LOG("(EMPTY)");
+ }
+ VTR_LOG("\n");
+#endif
+
+ return ::create_move(blocks_affected, b_from, to);
+}
diff --git a/vpr/src/place/uniform_move_generator.h b/vpr/src/place/uniform_move_generator.h
new file mode 100644
index 0000000..82aa243
--- /dev/null
+++ b/vpr/src/place/uniform_move_generator.h
@@ -0,0 +1,9 @@
+#ifndef VPR_UNIFORM_MOVE_GEN_H
+#define VPR_UNIFORM_MOVE_GEN_H
+#include "move_generator.h"
+
+class UniformMoveGenerator : public MoveGenerator {
+ e_create_move propose_move(t_pl_blocks_to_be_moved& affected_blocks, float rlim);
+};
+
+#endif
diff --git a/vpr/src/power/PowerSpicedComponent.cpp b/vpr/src/power/PowerSpicedComponent.cpp
index 05dd1a9..621fece 100644
--- a/vpr/src/power/PowerSpicedComponent.cpp
+++ b/vpr/src/power/PowerSpicedComponent.cpp
@@ -5,8 +5,6 @@
#include <algorithm>
#include <string>
-using namespace std;
-
#include "vtr_assert.h"
#include "vpr_error.h"
@@ -50,7 +48,7 @@
void PowerCallibInputs::callibrate() {
VTR_ASSERT(entries.size() >= 2);
- for (vector<PowerCallibSize*>::iterator it = entries.begin() + 1;
+ for (std::vector<PowerCallibSize*>::iterator it = entries.begin() + 1;
it != entries.end() - 1; it++) {
float est_power = parent->component_usage(num_inputs,
(*it)->transistor_size);
@@ -71,7 +69,7 @@
PowerCallibSize* prev = entries[0];
VTR_ASSERT(sorted);
- for (vector<PowerCallibSize*>::iterator it = entries.begin() + 1;
+ for (std::vector<PowerCallibSize*>::iterator it = entries.begin() + 1;
it != entries.end(); it++) {
if ((*it)->transistor_size > transistor_size) {
if (lower)
@@ -111,7 +109,7 @@
}
PowerCallibInputs* PowerSpicedComponent::get_entry(int num_inputs) {
- vector<PowerCallibInputs*>::iterator it;
+ std::vector<PowerCallibInputs*>::iterator it;
for (it = entries.begin(); it != entries.end(); it++) {
if ((*it)->num_inputs == num_inputs) {
@@ -131,7 +129,7 @@
PowerCallibInputs* prev = entries[0];
VTR_ASSERT(sorted);
- for (vector<PowerCallibInputs*>::iterator it = entries.begin() + 1;
+ for (std::vector<PowerCallibInputs*>::iterator it = entries.begin() + 1;
it != entries.end(); it++) {
if ((*it)->num_inputs > num_inputs) {
if (lower) {
@@ -230,7 +228,7 @@
void PowerSpicedComponent::sort_me() {
sort(entries.begin(), entries.end(), sorter_PowerCallibInputs);
- for (vector<PowerCallibInputs*>::iterator it = entries.begin();
+ for (std::vector<PowerCallibInputs*>::iterator it = entries.begin();
it != entries.end(); it++) {
(*it)->sort_me();
}
@@ -240,7 +238,7 @@
void PowerSpicedComponent::callibrate() {
sort_me();
- for (vector<PowerCallibInputs*>::iterator it = entries.begin();
+ for (std::vector<PowerCallibInputs*>::iterator it = entries.begin();
it != entries.end(); it++) {
(*it)->callibrate();
}
@@ -253,11 +251,11 @@
void PowerSpicedComponent::print(FILE* fp) {
fprintf(fp, "%s\n", name.c_str());
- for (vector<PowerCallibInputs*>::iterator it = entries.begin() + 1;
+ for (std::vector<PowerCallibInputs*>::iterator it = entries.begin() + 1;
it != entries.end() - 1; it++) {
fprintf(fp, "Num Inputs: %d\n", (*it)->num_inputs);
- for (vector<PowerCallibSize*>::iterator it2 = (*it)->entries.begin()
- + 1;
+ for (std::vector<PowerCallibSize*>::iterator it2 = (*it)->entries.begin()
+ + 1;
it2 != (*it)->entries.end() - 1; it2++) {
fprintf(fp, " Transistor Size: %6f Factor: %3f\n",
(*it2)->transistor_size, (*it2)->factor);
diff --git a/vpr/src/power/power.cpp b/vpr/src/power/power.cpp
index bed536a..1fcd06f 100644
--- a/vpr/src/power/power.cpp
+++ b/vpr/src/power/power.cpp
@@ -27,7 +27,6 @@
#include <ctime>
#include <cmath>
#include <ctype.h>
-using namespace std;
#include "vtr_util.h"
#include "vtr_path.h"
@@ -926,13 +925,13 @@
* // / (float) power_ctx.arch->seg_buffer_split;
* buffer_size = power_buffer_size_from_logical_effort(
* C_per_seg_split);
- * buffer_size = max(buffer_size, 1.0F);
+ * buffer_size = std::max(buffer_size, 1.0F);
*/
buffer_size = power_calc_buffer_size_from_Cout(device_ctx.rr_switch_inf[node_power->driver_switch_type].Cout);
break;
case POWER_BUFFER_TYPE_ABSOLUTE_SIZE:
buffer_size = device_ctx.rr_switch_inf[node_power->driver_switch_type].power_buffer_size;
- buffer_size = max(buffer_size, 1.0F);
+ buffer_size = std::max(buffer_size, 1.0F);
break;
case POWER_BUFFER_TYPE_NONE:
buffer_size = 0.;
@@ -1206,9 +1205,9 @@
switch (node->type()) {
case IPIN:
- max_IPIN_fanin = max(max_IPIN_fanin,
- static_cast<int>(node->fan_in()));
- max_fanin = max(max_fanin, static_cast<int>(node->fan_in()));
+ max_IPIN_fanin = std::max(max_IPIN_fanin,
+ static_cast<int>(node->fan_in()));
+ max_fanin = std::max(max_fanin, static_cast<int>(node->fan_in()));
node_power->in_dens = (float*)vtr::calloc(node->fan_in(),
sizeof(float));
@@ -1224,10 +1223,10 @@
fanout_to_seg++;
}
}
- max_seg_to_IPIN_fanout = max(max_seg_to_IPIN_fanout,
- fanout_to_IPIN);
- max_seg_to_seg_fanout = max(max_seg_to_seg_fanout, fanout_to_seg);
- max_fanin = max(max_fanin, static_cast<int>(node->fan_in()));
+ max_seg_to_IPIN_fanout = std::max(max_seg_to_IPIN_fanout,
+ fanout_to_IPIN);
+ max_seg_to_seg_fanout = std::max(max_seg_to_seg_fanout, fanout_to_seg);
+ max_fanin = std::max(max_fanin, static_cast<int>(node->fan_in()));
node_power->in_dens = (float*)vtr::calloc(node->fan_in(),
sizeof(float));
@@ -1245,7 +1244,7 @@
power_ctx.commonly_used->max_seg_to_IPIN_fanout = max_seg_to_IPIN_fanout;
#ifdef PRINT_SPICE_COMPARISON
- power_ctx.commonly_used->max_routing_mux_size = max(power_ctx.commonly_used->max_routing_mux_size, 26);
+ power_ctx.commonly_used->max_routing_mux_size = std::max(power_ctx.commonly_used->max_routing_mux_size, 26);
#endif
/* Populate driver switch type */
diff --git a/vpr/src/power/power_cmos_tech.cpp b/vpr/src/power/power_cmos_tech.cpp
index ef2b9ce..2054d88 100644
--- a/vpr/src/power/power_cmos_tech.cpp
+++ b/vpr/src/power/power_cmos_tech.cpp
@@ -43,9 +43,6 @@
#include "PowerSpicedComponent.h"
#include "power_callibrate.h"
-using namespace std;
-using namespace pugiutil;
-
/************************* FILE SCOPE **********************************/
static t_transistor_inf* f_transistor_last_searched;
static t_power_buffer_strength_inf* f_buffer_strength_last_searched;
@@ -80,7 +77,7 @@
pugiutil::loc_data loc_data;
try {
loc_data = pugiutil::load_xml(doc, cmos_tech_behavior_filepath);
- } catch (const XmlError& e) {
+ } catch (const pugiutil::XmlError& e) {
vpr_throw(VPR_ERROR_POWER, cmos_tech_behavior_filepath, 0,
"Failed to load CMOS Tech Properties file '%s' (%s).", cmos_tech_behavior_filepath, e.what());
}
@@ -138,7 +135,7 @@
}
static void power_tech_xml_load_component(pugi::xml_node parent, const pugiutil::loc_data& loc_data, PowerSpicedComponent** component, const char* name, float (*usage_fn)(int num_inputs, float transistor_size)) {
- string component_name(name);
+ std::string component_name(name);
*component = new PowerSpicedComponent(component_name, usage_fn);
auto cur = get_single_child(parent, name, loc_data);
diff --git a/vpr/src/power/power_components.cpp b/vpr/src/power/power_components.cpp
index eba90b3..6100b16 100644
--- a/vpr/src/power/power_components.cpp
+++ b/vpr/src/power/power_components.cpp
@@ -23,7 +23,6 @@
/************************* INCLUDES *********************************/
#include <cstring>
#include <cmath>
-using namespace std;
#include "vtr_math.h"
#include "vtr_assert.h"
diff --git a/vpr/src/power/power_sizing.cpp b/vpr/src/power/power_sizing.cpp
index 42f0c84..01c5425 100644
--- a/vpr/src/power/power_sizing.cpp
+++ b/vpr/src/power/power_sizing.cpp
@@ -23,7 +23,6 @@
/************************* INCLUDES *********************************/
#include <cstring>
#include <cmath>
-using namespace std;
#include "vtr_util.h"
#include "vtr_assert.h"
@@ -88,7 +87,7 @@
* (power_ctx.commonly_used->NMOS_1X_C_d
/ power_ctx.commonly_used->INV_1X_C_in)
/ power_ctx.arch->logical_effort_factor;
- buffer_size = max(1.0F, buffer_size);
+ buffer_size = std::max(1.0F, buffer_size);
transistor_cnt += power_ctx.solution_inf.channel_width
* power_count_transistors_buffer(buffer_size);
@@ -174,8 +173,8 @@
*/
static void power_mux_node_max_inputs(t_mux_node* mux_node,
float* max_inputs) {
- max_inputs[mux_node->level] = max(max_inputs[mux_node->level],
- static_cast<float>(mux_node->num_inputs));
+ max_inputs[mux_node->level] = std::max(max_inputs[mux_node->level],
+ static_cast<float>(mux_node->num_inputs));
if (mux_node->level != 0) {
int child_idx;
@@ -334,7 +333,7 @@
tc_interc += power_count_transistors_interc(&mode->interconnect[interc]);
}
}
- tc_interc_max = max(tc_interc_max, tc_interc);
+ tc_interc_max = std::max(tc_interc_max, tc_interc);
/* Count Child PB Types */
for (child = 0; child < mode->num_pb_type_children; child++) {
@@ -345,7 +344,7 @@
}
}
- tc_children_max = max(tc_children_max, tc_children);
+ tc_children_max = std::max(tc_children_max, tc_children);
}
}
@@ -760,8 +759,8 @@
/* Find worst-case between modes*/
for (i = 0; i < this_pb_type->num_modes; i++) {
- fanout = max(fanout, fanout_per_mode[i]);
- wirelength_out = max(wirelength_out, wirelength_out_per_mode[i]);
+ fanout = std::max(fanout, fanout_per_mode[i]);
+ wirelength_out = std::max(wirelength_out, wirelength_out_per_mode[i]);
}
if (wirelength_out != 0) {
wirelength_out += power_ctx.arch->local_interc_factor
diff --git a/vpr/src/power/power_util.cpp b/vpr/src/power/power_util.cpp
index 8ac8514..7ebc977 100644
--- a/vpr/src/power/power_util.cpp
+++ b/vpr/src/power/power_util.cpp
@@ -23,7 +23,6 @@
#include <cstring>
#include <cmath>
#include <map>
-using namespace std;
#include "vtr_assert.h"
#include "vtr_memory.h"
@@ -334,9 +333,8 @@
float power_buffer_size_from_logical_effort(float C_load) {
auto& power_ctx = g_vpr_ctx.power();
- return max(1.0f,
- C_load / power_ctx.commonly_used->INV_1X_C_in
- / (2 * power_ctx.arch->logical_effort_factor));
+ return std::max(1.0f,
+ C_load / power_ctx.commonly_used->INV_1X_C_in / (2 * power_ctx.arch->logical_effort_factor));
}
void power_print_title(FILE* fp, const char* title) {
diff --git a/vpr/src/route/build_switchblocks.cpp b/vpr/src/route/build_switchblocks.cpp
index 8929527..5a25248 100644
--- a/vpr/src/route/build_switchblocks.cpp
+++ b/vpr/src/route/build_switchblocks.cpp
@@ -141,8 +141,6 @@
#include "parse_switchblocks.h"
#include "expr_eval.h"
-using namespace std;
-
/************ Defines ************/
/* if defined, switch block patterns are loaded by first computing a row of switch blocks and then
* stamping out the row throughout the FPGA */
@@ -181,7 +179,7 @@
/************ Typedefs ************/
/* Used to get info about a given wire type based on the name */
-typedef map<string, Wire_Info> t_wire_type_sizes;
+typedef std::map<std::string, Wire_Info> t_wire_type_sizes;
/************ Function Declarations ************/
/* Counts the number of wires in each wire type in the specified channel */
@@ -221,7 +219,7 @@
static int evaluate_num_conns_formula(std::string num_conns_formula, int from_wire_count, int to_wire_count);
/* returns the wire indices belonging to the types in 'wire_type_vec' and switchpoints in 'points' at the given channel segment */
-static std::vector<t_wire_switchpoint> get_switchpoint_wires(const DeviceGrid& grid, const t_chan_seg_details* chan_details, t_rr_type chan_type, int x, int y, e_side side, const vector<t_wire_switchpoints>& wire_switchpoints_vec, t_wire_type_sizes* wire_type_sizes, bool is_dest, SwitchPointOrder order, vtr::RandState& rand_state);
+static std::vector<t_wire_switchpoint> get_switchpoint_wires(const DeviceGrid& grid, const t_chan_seg_details* chan_details, t_rr_type chan_type, int x, int y, e_side side, const std::vector<t_wire_switchpoints>& wire_switchpoints_vec, t_wire_type_sizes* wire_type_sizes, bool is_dest, SwitchPointOrder order, vtr::RandState& rand_state);
static const t_chan_details& index_into_correct_chan(int tile_x, int tile_y, enum e_side side, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, int* chan_x, int* chan_y, t_rr_type* chan_type);
@@ -257,7 +255,7 @@
t_sb_connection_map* alloc_and_load_switchblock_permutations(const t_chan_details& chan_details_x,
const t_chan_details& chan_details_y,
const DeviceGrid& grid,
- vector<t_switchblock_inf> switchblocks,
+ std::vector<t_switchblock_inf> switchblocks,
t_chan_width* nodes_per_chan,
e_directionality directionality,
vtr::RandState& rand_state) {
@@ -573,8 +571,8 @@
/* Counts the number of wires in each wire type in the specified channel */
static void count_wire_type_sizes(const t_chan_seg_details* channel, int nodes_per_chan, t_wire_type_sizes* wire_type_sizes) {
- string wire_type;
- string new_type;
+ std::string wire_type;
+ std::string new_type;
int new_length, length;
int new_start, start;
int num_wires = 0;
@@ -604,7 +602,7 @@
}
/* returns the wire indices belonging to the types in 'wire_type_vec' and switchpoints in 'points' at the given channel segment */
-static std::vector<t_wire_switchpoint> get_switchpoint_wires(const DeviceGrid& grid, const t_chan_seg_details* chan_details, t_rr_type chan_type, int x, int y, e_side side, const vector<t_wire_switchpoints>& wire_switchpoints_vec, t_wire_type_sizes* wire_type_sizes, bool is_dest, SwitchPointOrder switchpoint_order, vtr::RandState& rand_state) {
+static std::vector<t_wire_switchpoint> get_switchpoint_wires(const DeviceGrid& grid, const t_chan_seg_details* chan_details, t_rr_type chan_type, int x, int y, e_side side, const std::vector<t_wire_switchpoints>& wire_switchpoints_vec, t_wire_type_sizes* wire_type_sizes, bool is_dest, SwitchPointOrder switchpoint_order, vtr::RandState& rand_state) {
std::vector<t_wire_switchpoint> all_collected_wire_switchpoints;
int seg_coord = x;
@@ -832,7 +830,7 @@
//Evaluate permutation functions for the from_wire
SB_Side_Connection side_conn(sb_conn.from_side, sb_conn.to_side);
- vector<string>& permutations_ref = sb->permutation_map[side_conn];
+ std::vector<std::string>& permutations_ref = sb->permutation_map[side_conn];
for (int iperm = 0; iperm < (int)permutations_ref.size(); iperm++) {
/* Convert the symbolic permutation formula to a number */
t_formula_data formula_data;
diff --git a/vpr/src/route/cb_metrics.cpp b/vpr/src/route/cb_metrics.cpp
index 1a84580..a4152b4 100644
--- a/vpr/src/route/cb_metrics.cpp
+++ b/vpr/src/route/cb_metrics.cpp
@@ -44,8 +44,6 @@
#include "cb_metrics.h"
-using namespace std;
-
/* TODO: move to libarchfpga/include/util.h after ODIN II has been converted to use g++ */
/* a generic function for determining if a given map key exists */
template<typename F, typename T>
@@ -85,17 +83,17 @@
/* given a set of tracks connected to a pin, we'd like to find which of these tracks are connected to a number of switches
* greater than 'criteria'. The resulting set of tracks is passed back in the 'result' vector */
-static void find_tracks_with_more_switches_than(const set<int>* pin_tracks, const t_vec_vec_set* track_to_pins, const int side, const bool both_sides, const int criteria, vector<int>* result);
+static void find_tracks_with_more_switches_than(const std::set<int>* pin_tracks, const t_vec_vec_set* track_to_pins, const int side, const bool both_sides, const int criteria, std::vector<int>* result);
/* given a pin on some side of a block, we'd like to find the set of tracks that is NOT connected to that pin on that side. This set of tracks
* is passed back in the 'result' vector */
-static void find_tracks_unconnected_to_pin(const set<int>* pin_tracks, const vector<set<int> >* track_to_pins, vector<int>* result);
+static void find_tracks_unconnected_to_pin(const std::set<int>* pin_tracks, const std::vector<std::set<int> >* track_to_pins, std::vector<int>* result);
/* iterates through the elements of set 1 and returns the number of elements in set1 that are
* also in set2 (in terms of bit vectors, this looks for the number of positions where both bit vectors
* have a value of 1; values of 0 not counted... so, not quite true hamming proximity). Analogously, if we
* wanted the hamming distance of these two sets, (in terms of bit vectors, the number of bit positions that are
* different... i.e. the actual definition of hamming disatnce) that would be 2(set_size - returned_value) */
-static int hamming_proximity_of_two_sets(const set<int>* set1, const set<int>* set2);
+static int hamming_proximity_of_two_sets(const std::set<int>* set1, const std::set<int>* set2);
/* returns the pin diversity metric of a block */
static float get_pin_diversity(const int Fc, const int num_pin_type_pins, const Conn_Block_Metrics* cb_metrics);
/* Returns the wire homogeneity of a block's connection to tracks */
@@ -239,15 +237,15 @@
/* allocate the multi-dimensional vectors used for conveniently calculating CB metrics */
for (int iside = 0; iside < 4; iside++) {
- cb_metrics->track_to_pins.push_back(vector<set<int> >());
- cb_metrics->pin_to_tracks.push_back(vector<set<int> >());
- cb_metrics->wire_types_used_count.push_back(vector<vector<int> >());
+ cb_metrics->track_to_pins.push_back(std::vector<std::set<int> >());
+ cb_metrics->pin_to_tracks.push_back(std::vector<std::set<int> >());
+ cb_metrics->wire_types_used_count.push_back(std::vector<std::vector<int> >());
for (int i = 0; i < nodes_per_chan; i++) {
- cb_metrics->track_to_pins.at(iside).push_back(set<int>());
+ cb_metrics->track_to_pins.at(iside).push_back(std::set<int>());
}
for (int ipin = 0; ipin < (int)cb_metrics->pin_locations.at(iside).size(); ipin++) {
- cb_metrics->pin_to_tracks.at(iside).push_back(set<int>());
- cb_metrics->wire_types_used_count.at(iside).push_back(vector<int>());
+ cb_metrics->pin_to_tracks.at(iside).push_back(std::set<int>());
+ cb_metrics->wire_types_used_count.at(iside).push_back(std::vector<int>());
for (int itype = 0; itype < num_wire_types; itype++) {
cb_metrics->wire_types_used_count.at(iside).at(ipin).push_back(0);
}
@@ -255,7 +253,7 @@
}
/* set the values of the multi-dimensional vectors */
- set<int> counted_pins;
+ std::set<int> counted_pins;
int track = 0;
/* over each side of the block */
for (int iside = 0; iside < 4; iside++) {
@@ -285,14 +283,14 @@
break;
}
- pair<set<int>::iterator, bool> result1 = cb_metrics->pin_to_tracks.at(iside).at(ipin).insert(track);
+ std::pair<std::set<int>::iterator, bool> result1 = cb_metrics->pin_to_tracks.at(iside).at(ipin).insert(track);
if (!result1.second) {
/* this track should not already be a part of the set */
VPR_FATAL_ERROR(VPR_ERROR_ROUTE, "Attempted to insert element into pin_to_tracks set which already exists there\n");
}
/* insert the current pin into the corresponding tracks_to_pin entry */
- pair<set<int>::iterator, bool> result2 = cb_metrics->track_to_pins.at(iside).at(track).insert(pin);
+ std::pair<std::set<int>::iterator, bool> result2 = cb_metrics->track_to_pins.at(iside).at(track).insert(pin);
if (!result2.second) {
/* this pin should not already be a part of the set */
VPR_FATAL_ERROR(VPR_ERROR_ROUTE, "Attempted to insert element into track_to_pins set which already exists there\n");
@@ -505,10 +503,10 @@
* have a value of 1; values of 0 not counted... so, not quite true hamming proximity). Analogously, if we
* wanted the hamming distance of these two sets, (in terms of bit vectors, the number of bit positions that are
* different... i.e. the actual definition of hamming disatnce) that would be 2(set_size - returned_value) */
-static int hamming_proximity_of_two_sets(const set<int>* set1, const set<int>* set2) {
+static int hamming_proximity_of_two_sets(const std::set<int>* set1, const std::set<int>* set2) {
int result = 0;
- set<int>::const_iterator it;
+ std::set<int>::const_iterator it;
for (it = set1->begin(); it != set1->end(); it++) {
int element = *it;
if (set_has_element(element, set2)) {
@@ -553,7 +551,7 @@
}
total_conns = total_pins_on_side * Fc;
- unconnected_wires = (total_conns) ? max(0, nodes_per_chan - total_conns) : 0;
+ unconnected_wires = (total_conns) ? std::max(0, nodes_per_chan - total_conns) : 0;
mean = (float)total_conns / (float)(nodes_per_chan - unconnected_wires);
wire_homogeneity[side] = 0;
for (int track = 0; track < nodes_per_chan; track++) {
@@ -579,7 +577,7 @@
/* goes through each pin of pin_type and determines which side of the block it comes out on. results are stored in
* the 'pin_locations' 2d-vector */
static void get_pin_locations(const t_physical_tile_type_ptr block_type, const e_pin_type pin_type, const int num_pin_type_pins, int***** tracks_connected_to_pin, t_2d_int_vec* pin_locations) {
- set<int> counted_pins;
+ std::set<int> counted_pins;
pin_locations->clear();
/* over each side */
@@ -595,7 +593,7 @@
//TODO: block_type->pin_loc indicates that there are pins on all sides of an I/O block, but this is not actually the case...
// In the future we should change pin_loc to indicate the correct pin locations
/* push back an empty vector for this side */
- pin_locations->push_back(vector<int>());
+ pin_locations->push_back(std::vector<int>());
for (int iwidth = 0; iwidth < block_type->width; iwidth++) {
for (int iheight = 0; iheight < block_type->height; iheight++) {
/* check if ipin is present at this side/width/height */
@@ -621,7 +619,7 @@
/* given a set of tracks connected to a pin, we'd like to find which of these tracks are connected to a number of switches
* greater than 'criteria'. The resulting set of tracks is passed back in the 'result' vector */
-static void find_tracks_with_more_switches_than(const set<int>* pin_tracks, const t_vec_vec_set* track_to_pins, const int side, const bool both_sides, const int criteria, vector<int>* result) {
+static void find_tracks_with_more_switches_than(const std::set<int>* pin_tracks, const t_vec_vec_set* track_to_pins, const int side, const bool both_sides, const int criteria, std::vector<int>* result) {
result->clear();
if (both_sides && side >= 2) {
@@ -629,7 +627,7 @@
}
/* for each track connected to the pin */
- set<int>::const_iterator it;
+ std::set<int>::const_iterator it;
for (it = pin_tracks->begin(); it != pin_tracks->end(); it++) {
int track = *it;
@@ -647,7 +645,7 @@
/* given a pin on some side of a block, we'd like to find the set of tracks that is NOT connected to that pin on that side. This set of tracks
* is passed back in the 'result' vector */
-static void find_tracks_unconnected_to_pin(const set<int>* pin_tracks, const vector<set<int> >* track_to_pins, vector<int>* result) {
+static void find_tracks_unconnected_to_pin(const std::set<int>* pin_tracks, const std::vector<std::set<int> >* track_to_pins, std::vector<int>* result) {
result->clear();
/* for each track in the channel segment */
for (int itrack = 0; itrack < (int)track_to_pins->size(); itrack++) {
@@ -689,7 +687,7 @@
both_sides = false;
}
- static vector<int> set_of_tracks;
+ static std::vector<int> set_of_tracks;
/* the set_of_tracks vector is used to find sets of tracks satisfying some criteria that we want. we reserve memory for it, which
* should be preserved between calls of this function so that we don't have to allocate memory every time */
set_of_tracks.reserve(nodes_per_chan);
@@ -699,7 +697,7 @@
int rand_side = vtr::irand(3);
int rand_pin_index = vtr::irand(cb_metrics->pin_locations.at(rand_side).size() - 1);
int rand_pin = cb_metrics->pin_locations.at(rand_side).at(rand_pin_index);
- set<int>* tracks_connected_to_pin = &pin_to_tracks->at(rand_side).at(rand_pin_index);
+ std::set<int>* tracks_connected_to_pin = &pin_to_tracks->at(rand_side).at(rand_pin_index);
/* If the pin is unconnected, return. */
if (0 == tracks_connected_to_pin->size()) {
@@ -961,7 +959,7 @@
static void print_switch_histogram(const int nodes_per_chan, const Conn_Block_Metrics* cb_metrics) {
/* key: number of switches; element: number of tracks with that switch count */
- map<int, int> switch_histogram;
+ std::map<int, int> switch_histogram;
const t_vec_vec_set* track_to_pins = &cb_metrics->track_to_pins;
@@ -977,7 +975,7 @@
}
VTR_LOG("\t===CB Metrics Switch Histogram===\n\t#switches ==> #num tracks carrying that number of switches\n");
- map<int, int>::const_iterator it;
+ std::map<int, int>::const_iterator it;
for (it = switch_histogram.begin(); it != switch_histogram.end(); it++) {
VTR_LOG("\t%d ==> %d\n", it->first, it->second);
}
@@ -1023,7 +1021,7 @@
}
/* each pin corresponds to a row of the xbar matrix */
- xbar_matrix->push_back(vector<float>());
+ xbar_matrix->push_back(std::vector<float>());
/* each wire in the channel corresponds to a column of the xbar matrix */
for (int icol = 0; icol < nodes_per_chan; icol++) {
@@ -1048,7 +1046,7 @@
int new_rows = (int)xbar->at(0).size();
for (int i = 0; i < new_rows; i++) {
- result.push_back(vector<float>());
+ result.push_back(std::vector<float>());
for (int j = 0; j < new_cols; j++) {
result.at(i).push_back(xbar->at(j).at(i));
}
@@ -1081,7 +1079,7 @@
return result;
}
-static long double count_switch_configurations(const int level, const int signals_left, const int capacity_left, vector<int>* config, map<int, Wire_Counting>* count_map) {
+static long double count_switch_configurations(const int level, const int signals_left, const int capacity_left, std::vector<int>* config, std::map<int, Wire_Counting>* count_map) {
long double result = 0;
if (capacity_left < signals_left) {
@@ -1090,7 +1088,7 @@
}
/* get the capacity of the current wire group (here, group is defined by the number of switches a wire carries) */
- map<int, Wire_Counting>::const_iterator it = count_map->begin();
+ std::map<int, Wire_Counting>::const_iterator it = count_map->begin();
advance(it, level);
int my_capacity = it->second.num_wires;
@@ -1098,7 +1096,7 @@
int downstream_capacity = capacity_left - my_capacity;
/* get the maximum number of signals this wire group can carry */
- int can_take = min(my_capacity, signals_left);
+ int can_take = std::min(my_capacity, signals_left);
/* we cannot push more signals onto the other wire groups than they can take. to avoid this the minimum number of signals allowed
* to be carried by the current wire group may be above 0 */
@@ -1127,7 +1125,7 @@
/* add this info for the final wire group */
it = count_map->begin();
advance(it, level);
- map<int, long double>* configs_used = &count_map->at(it->first).configs_used;
+ std::map<int, long double>* configs_used = &count_map->at(it->first).configs_used;
if (map_has_key(config->at(level), configs_used)) {
configs_used->at(config->at(level)) += num_configs;
} else {
@@ -1141,7 +1139,7 @@
/* add this info for the current wire group */
it = count_map->begin();
advance(it, level);
- map<int, long double>* configs_used = &count_map->at(it->first).configs_used;
+ std::map<int, long double>* configs_used = &count_map->at(it->first).configs_used;
if (map_has_key(config->at(level), configs_used)) {
configs_used->at(config->at(level)) += num_configs;
} else {
@@ -1161,7 +1159,7 @@
int rows = (int)xbar->size(); /* rows correspond to pins */
int cols = (int)xbar->at(0).size(); /* columns correspond to wires */
- map<int, Wire_Counting> count_map;
+ std::map<int, Wire_Counting> count_map;
/* the number of signals that this channel can carry (each wire with switches contributes 1 to capacity) */
int capacity = 0;
@@ -1203,7 +1201,7 @@
/* the config vector represents some distribution of signals over available wires. i.e. x wires of type 0 get used, y wires of type 1, etc
* this vector is created here, but is updated inside the count_switch_configurations function */
- vector<int> config;
+ std::vector<int> config;
for (int i = 0; i < (int)count_map.size(); i++) {
config.push_back(0);
}
@@ -1214,13 +1212,13 @@
long double total_configurations = count_switch_configurations(0, wires_used, capacity, &config, &count_map);
/* next we need to calculate the expectation of the number of wires available for each wire group */
- map<int, Wire_Counting>::const_iterator it;
+ std::map<int, Wire_Counting>::const_iterator it;
for (it = count_map.begin(); it != count_map.end(); it++) {
- map<int, long double>* configs_used = &count_map.at(it->first).configs_used;
+ std::map<int, long double>* configs_used = &count_map.at(it->first).configs_used;
float* expectation_available = &count_map.at(it->first).expectation_available;
(*expectation_available) = 0;
- map<int, long double>::const_iterator it2;
+ std::map<int, long double>::const_iterator it2;
for (it2 = configs_used->begin(); it2 != configs_used->end(); it2++) {
int used = it2->first;
long double num_configurations = it2->second;
@@ -1279,7 +1277,7 @@
static void allocate_xbar(const int rows, const int cols, const float num, t_xbar_matrix* xbar) {
xbar->clear();
for (int irow = 0; irow < rows; irow++) {
- xbar->push_back(vector<float>());
+ xbar->push_back(std::vector<float>());
for (int icol = 0; icol < cols; icol++) {
xbar->at(irow).push_back(num);
}
diff --git a/vpr/src/route/check_route.cpp b/vpr/src/route/check_route.cpp
index 1368d8e..f0ec889 100644
--- a/vpr/src/route/check_route.cpp
+++ b/vpr/src/route/check_route.cpp
@@ -1,5 +1,4 @@
#include <cstdio>
-using namespace std;
#include "vtr_assert.h"
#include "vtr_log.h"
@@ -72,7 +71,7 @@
max_pins = 0;
for (auto net_id : cluster_ctx.clb_nlist.nets())
- max_pins = max(max_pins, (int)cluster_ctx.clb_nlist.net_pins(net_id).size());
+ max_pins = std::max(max_pins, (int)cluster_ctx.clb_nlist.net_pins(net_id).size());
pin_done = (bool*)vtr::malloc(max_pins * sizeof(bool));
diff --git a/vpr/src/route/route_breadth_first.cpp b/vpr/src/route/route_breadth_first.cpp
index e43e118..3ff2eca 100644
--- a/vpr/src/route/route_breadth_first.cpp
+++ b/vpr/src/route/route_breadth_first.cpp
@@ -1,5 +1,4 @@
#include <cstdio>
-using namespace std;
#include "vtr_log.h"
@@ -35,6 +34,21 @@
* (FPGA 95 p. 111). Returns true if it can route this FPGA, false if *
* it can't. */
+ VTR_LOG(
+ "**********************************************************************\n"
+ "* !!! WARNING !!! *\n"
+ "* *\n"
+ "* Routing with the DEPRECATED 'Breadth-First' router, which *\n"
+ "* is inferrior and may be removed in a future release. *\n"
+ "* *\n"
+ "* Use the 'Timing-Driven' router instead, which requires much *\n"
+ "* less run-time and produces higher quality results *\n"
+ "* (even with it no timing information is available). *\n"
+ "* *\n"
+ "* !!! WARNING !!! *\n"
+ "**********************************************************************\n"
+ "\n");
+
float pres_fac;
bool success, is_routable, rip_up_local_opins;
int itry;
@@ -85,7 +99,7 @@
else
pres_fac *= router_opts.pres_fac_mult;
- pres_fac = min(pres_fac, static_cast<float>(HUGE_POSITIVE_FLOAT / 1e5));
+ pres_fac = std::min(pres_fac, static_cast<float>(HUGE_POSITIVE_FLOAT / 1e5));
pathfinder_update_cost(pres_fac, router_opts.acc_fac);
}
diff --git a/vpr/src/route/route_budgets.cpp b/vpr/src/route/route_budgets.cpp
index 2f63c1d..d09656c 100644
--- a/vpr/src/route/route_budgets.cpp
+++ b/vpr/src/route/route_budgets.cpp
@@ -148,7 +148,7 @@
int ipin = cluster_ctx.clb_nlist.pin_net_index(pin_id);
/*Target delay is calculated using equation in the RCV algorithm*/
- delay_target[net_id][ipin] = min(0.5 * (delay_min_budget[net_id][ipin] + delay_max_budget[net_id][ipin]), delay_min_budget[net_id][ipin] + 0.1e-9);
+ delay_target[net_id][ipin] = std::min(0.5 * (delay_min_budget[net_id][ipin] + delay_max_budget[net_id][ipin]), delay_min_budget[net_id][ipin] + 0.1e-9);
}
void route_budgets::allocate_slack_using_weights(vtr::vector<ClusterNetId, float*>& net_delay, const ClusteredPinAtomPinsLookup& netlist_pin_lookup) {
@@ -233,7 +233,7 @@
timing_info = perform_sta(delay_max_budget);
second_max_budget_change = minimax_PERT(timing_info, delay_max_budget, net_delay, netlist_pin_lookup, SETUP, true, NEGATIVE);
- max_budget_change = max(max_budget_change, second_max_budget_change);
+ max_budget_change = std::max(max_budget_change, second_max_budget_change);
iteration++;
}
@@ -245,7 +245,7 @@
for (auto net_id : cluster_ctx.clb_nlist.nets()) {
for (auto pin_id : cluster_ctx.clb_nlist.net_sinks(net_id)) {
int ipin = cluster_ctx.clb_nlist.pin_net_index(pin_id);
- temp_budgets[net_id][ipin] = max(temp_budgets[net_id][ipin], bottom_range);
+ temp_budgets[net_id][ipin] = std::max(temp_budgets[net_id][ipin], bottom_range);
}
}
}
@@ -265,8 +265,8 @@
auto& cluster_ctx = g_vpr_ctx.clustering();
int ipin = cluster_ctx.clb_nlist.pin_net_index(pin_id);
- temp_budgets[net_id][ipin] = max(temp_budgets[net_id][ipin], delay_lower_bound[net_id][ipin]);
- temp_budgets[net_id][ipin] = min(temp_budgets[net_id][ipin], delay_upper_bound[net_id][ipin]);
+ temp_budgets[net_id][ipin] = std::max(temp_budgets[net_id][ipin], delay_lower_bound[net_id][ipin]);
+ temp_budgets[net_id][ipin] = std::min(temp_budgets[net_id][ipin], delay_upper_bound[net_id][ipin]);
}
void route_budgets::keep_min_below_max_budget() {
@@ -331,7 +331,7 @@
} else {
temp_budgets[net_id][ipin] += net_delay[net_id][ipin] * path_slack / total_path_delay;
}
- max_budget_change = max(max_budget_change, abs(net_delay[net_id][ipin] * path_slack / total_path_delay));
+ max_budget_change = std::max(max_budget_change, std::abs(net_delay[net_id][ipin] * path_slack / total_path_delay));
}
/*Budgets need to be between maximum and minimum budgets*/
@@ -475,13 +475,13 @@
* else becomes a bit less critical. This effect becomes more pronounced if
* max_criticality is set lower. */
// VTR_ASSERT(pin_criticality[ipin] > -0.01 && pin_criticality[ipin] < 1.01);
- pin_criticality = max(pin_criticality - (1.0 - router_opts.max_criticality), 0.0);
+ pin_criticality = std::max(pin_criticality - (1.0 - router_opts.max_criticality), 0.0);
/* Take pin criticality to some power (1 by default). */
- pin_criticality = pow(pin_criticality, router_opts.criticality_exp);
+ pin_criticality = std::pow(pin_criticality, router_opts.criticality_exp);
/* Cut off pin criticality at max_criticality. */
- pin_criticality = min(pin_criticality, router_opts.max_criticality);
+ pin_criticality = std::min(pin_criticality, router_opts.max_criticality);
int ipin = cluster_ctx.clb_nlist.pin_net_index(pin_id);
delay_min_budget[net_id][ipin] = 0;
@@ -492,12 +492,12 @@
//prevent invalid division
delay_max_budget[net_id][ipin] = delay_upper_bound[net_id][ipin];
} else {
- delay_max_budget[net_id][ipin] = min(net_delay[net_id][ipin] / pin_criticality, delay_upper_bound[net_id][ipin]);
+ delay_max_budget[net_id][ipin] = std::min(net_delay[net_id][ipin] / pin_criticality, delay_upper_bound[net_id][ipin]);
}
check_if_budgets_in_bounds(net_id, pin_id);
/*Use RCV algorithm for delay target
* Tend towards minimum to consider short path timing delay more*/
- delay_target[net_id][ipin] = min(0.5 * (delay_min_budget[net_id][ipin] + delay_max_budget[net_id][ipin]), delay_min_budget[net_id][ipin] + 0.1e-9);
+ delay_target[net_id][ipin] = std::min(0.5 * (delay_min_budget[net_id][ipin] + delay_max_budget[net_id][ipin]), delay_min_budget[net_id][ipin] + 0.1e-9);
}
}
}
@@ -601,8 +601,8 @@
/*Used for debugging. Prints out all the delay budget class variables to an external
* file named route_budgets.txt*/
auto& cluster_ctx = g_vpr_ctx.clustering();
- fstream fp;
- fp.open("route_budget.txt", fstream::out | fstream::trunc);
+ std::fstream fp;
+ fp.open("route_budget.txt", std::fstream::out | std::fstream::trunc);
/* Prints out general info for easy error checking*/
if (!fp.is_open() || !fp.good()) {
@@ -610,9 +610,9 @@
"could not open \"route_budget.txt\" for generating route budget file\n");
}
- fp << "Minimum Delay Budgets:" << endl;
+ fp << "Minimum Delay Budgets:" << std::endl;
for (auto net_id : cluster_ctx.clb_nlist.nets()) {
- fp << endl
+ fp << std::endl
<< "Net: " << size_t(net_id) << " ";
for (auto pin_id : cluster_ctx.clb_nlist.net_sinks(net_id)) {
int ipin = cluster_ctx.clb_nlist.pin_net_index(pin_id);
@@ -620,11 +620,11 @@
}
}
- fp << endl
- << endl
- << "Maximum Delay Budgets:" << endl;
+ fp << std::endl
+ << std::endl
+ << "Maximum Delay Budgets:" << std::endl;
for (auto net_id : cluster_ctx.clb_nlist.nets()) {
- fp << endl
+ fp << std::endl
<< "Net: " << size_t(net_id) << " ";
for (auto pin_id : cluster_ctx.clb_nlist.net_sinks(net_id)) {
int ipin = cluster_ctx.clb_nlist.pin_net_index(pin_id);
@@ -632,12 +632,12 @@
}
}
- fp << endl
- << endl
- << "Target Delay Budgets:" << endl;
+ fp << std::endl
+ << std::endl
+ << "Target Delay Budgets:" << std::endl;
for (auto net_id : cluster_ctx.clb_nlist.nets()) {
- fp << endl
+ fp << std::endl
<< "Net: " << size_t(net_id) << " ";
for (auto pin_id : cluster_ctx.clb_nlist.net_sinks(net_id)) {
int ipin = cluster_ctx.clb_nlist.pin_net_index(pin_id);
@@ -645,11 +645,11 @@
}
}
- fp << endl
- << endl
- << "Delay lower_bound:" << endl;
+ fp << std::endl
+ << std::endl
+ << "Delay lower_bound:" << std::endl;
for (auto net_id : cluster_ctx.clb_nlist.nets()) {
- fp << endl
+ fp << std::endl
<< "Net: " << size_t(net_id) << " ";
for (auto pin_id : cluster_ctx.clb_nlist.net_sinks(net_id)) {
int ipin = cluster_ctx.clb_nlist.pin_net_index(pin_id);
@@ -657,11 +657,11 @@
}
}
- fp << endl
- << endl
- << "Delay upper_bound:" << endl;
+ fp << std::endl
+ << std::endl
+ << "Delay upper_bound:" << std::endl;
for (auto net_id : cluster_ctx.clb_nlist.nets()) {
- fp << endl
+ fp << std::endl
<< "Net: " << size_t(net_id) << " ";
for (auto pin_id : cluster_ctx.clb_nlist.net_sinks(net_id)) {
int ipin = cluster_ctx.clb_nlist.pin_net_index(pin_id);
@@ -677,12 +677,12 @@
* temporary_budgets.txt. This can be used to see how the budgets change between
* each minimax PERT iteration*/
auto& cluster_ctx = g_vpr_ctx.clustering();
- fstream fp;
- fp.open("temporary_budgets.txt", fstream::out | fstream::trunc);
+ std::fstream fp;
+ fp.open("temporary_budgets.txt", std::fstream::out | std::fstream::trunc);
- fp << "Temporary Budgets:" << endl;
+ fp << "Temporary Budgets:" << std::endl;
for (auto net_id : cluster_ctx.clb_nlist.nets()) {
- fp << endl
+ fp << std::endl
<< "Net: " << size_t(net_id) << " ";
for (auto pin_id : cluster_ctx.clb_nlist.net_sinks(net_id)) {
int ipin = cluster_ctx.clb_nlist.pin_net_index(pin_id);
diff --git a/vpr/src/route/route_budgets.h b/vpr/src/route/route_budgets.h
index e4318ff..601ad84 100644
--- a/vpr/src/route/route_budgets.h
+++ b/vpr/src/route/route_budgets.h
@@ -9,8 +9,6 @@
#include "vtr_memory.h"
#include "RoutingDelayCalculator.h"
-using namespace std;
-
enum analysis_type {
SETUP,
HOLD
@@ -26,7 +24,7 @@
public:
route_budgets();
- route_budgets(vector<vector<float>> net_delay);
+ route_budgets(std::vector<std::vector<float>> net_delay);
virtual ~route_budgets();
diff --git a/vpr/src/route/route_common.cpp b/vpr/src/route/route_common.cpp
index 9bc5ebb..a788735 100644
--- a/vpr/src/route/route_common.cpp
+++ b/vpr/src/route/route_common.cpp
@@ -4,7 +4,6 @@
#include <algorithm>
#include <vector>
#include <iostream>
-using namespace std;
#include "vtr_assert.h"
#include "vtr_util.h"
@@ -236,7 +235,6 @@
router_opts.trim_empty_channels,
router_opts.trim_obs_channels,
router_opts.clock_modeling,
- router_opts.lookahead_type,
directs, num_directs,
&warning_count);
}
@@ -287,7 +285,6 @@
router_opts.trim_empty_channels,
router_opts.trim_obs_channels,
router_opts.clock_modeling,
- router_opts.lookahead_type,
directs, num_directs,
&warning_count);
@@ -316,6 +313,7 @@
success = try_timing_driven_route(router_opts,
analysis_opts,
+ segment_inf,
net_delay,
netlist_pin_lookup,
timing_info,
@@ -736,7 +734,7 @@
return (cost);
}
-/* Returns the congestion cost of using this rr_node, *ignoring*
+/* Returns the congestion cost of using this rr_node, *ignoring*
* non-configurable edges */
static float get_single_rr_cong_cost(int inode) {
auto& device_ctx = g_vpr_ctx.device();
@@ -767,7 +765,7 @@
}
}
-void mark_remaining_ends(const vector<int>& remaining_sinks) {
+void mark_remaining_ends(const std::vector<int>& remaining_sinks) {
// like mark_ends, but only performs it for the remaining sinks of a net
auto& route_ctx = g_vpr_ctx.mutable_routing();
for (int sink_node : remaining_sinks)
@@ -1112,7 +1110,7 @@
* the FPGA if necessary. The bounding box returned by this routine
* are different from the ones used by the placer in that they are
* clipped to lie within (0,0) and (device_ctx.grid.width()-1,device_ctx.grid.height()-1)
- * rather than (1,1) and (device_ctx.grid.width()-1,device_ctx.grid.height()-1).
+ * rather than (1,1) and (device_ctx.grid.width()-1,device_ctx.grid.height()-1).
*/
auto& cluster_ctx = g_vpr_ctx.clustering();
auto& device_ctx = g_vpr_ctx.device();
@@ -1161,10 +1159,10 @@
t_bb bb;
- bb.xmin = max<int>(xmin - bb_factor, 0);
- bb.xmax = min<int>(xmax + bb_factor, device_ctx.grid.width() - 1);
- bb.ymin = max<int>(ymin - bb_factor, 0);
- bb.ymax = min<int>(ymax + bb_factor, device_ctx.grid.height() - 1);
+ bb.xmin = std::max<int>(xmin - bb_factor, 0);
+ bb.xmax = std::min<int>(xmax + bb_factor, device_ctx.grid.width() - 1);
+ bb.ymin = std::max<int>(ymin - bb_factor, 0);
+ bb.ymax = std::min<int>(ymax + bb_factor, device_ctx.grid.height() - 1);
return bb;
}
@@ -1899,3 +1897,20 @@
return true;
}
+
+// True if router will use a lookahead.
+//
+// This controls whether the router lookahead cache will be primed outside of
+// the router ScopedStartFinishTimer.
+bool router_needs_lookahead(enum e_router_algorithm router_algorithm) {
+ switch (router_algorithm) {
+ case BREADTH_FIRST:
+ case NO_TIMING:
+ return false;
+ case TIMING_DRIVEN:
+ return true;
+ default:
+ VPR_FATAL_ERROR(VPR_ERROR_ROUTE, "Unknown routing algorithm %d",
+ router_algorithm);
+ }
+}
diff --git a/vpr/src/route/route_common.h b/vpr/src/route/route_common.h
index 0c2c90a..ea9ed19 100644
--- a/vpr/src/route/route_common.h
+++ b/vpr/src/route/route_common.h
@@ -126,3 +126,5 @@
t_trace* alloc_trace_data();
void free_trace_data(t_trace* trace);
+
+bool router_needs_lookahead(enum e_router_algorithm router_algorithm);
diff --git a/vpr/src/route/route_profiling.cpp b/vpr/src/route/route_profiling.cpp
index 1e0c898..c5e5737 100644
--- a/vpr/src/route/route_profiling.cpp
+++ b/vpr/src/route/route_profiling.cpp
@@ -30,19 +30,18 @@
void profiling_initialization(unsigned /*max_net_fanout*/) {}
#else
-using namespace std;
constexpr unsigned int fanout_per_bin = 1;
constexpr float criticality_per_bin = 0.05;
// data structures indexed by fanout bin (ex. fanout of x is in bin x/fanout_per_bin)
-static vector<float> time_on_fanout;
-static vector<float> time_on_fanout_rebuild;
-static vector<float> time_on_criticality;
-static vector<int> itry_on_fanout;
-static vector<int> itry_on_criticality;
-static vector<int> rerouted_sinks;
-static vector<int> finished_sinks;
+static std::vector<float> time_on_fanout;
+static std::vector<float> time_on_fanout_rebuild;
+static std::vector<float> time_on_criticality;
+static std::vector<int> itry_on_fanout;
+static std::vector<int> itry_on_criticality;
+static std::vector<int> rerouted_sinks;
+static std::vector<int> finished_sinks;
// action counters for what setup routing resources did
static int entire_net_rerouted;
diff --git a/vpr/src/route/route_timing.cpp b/vpr/src/route/route_timing.cpp
index ed1722b..5e2f358 100644
--- a/vpr/src/route/route_timing.cpp
+++ b/vpr/src/route/route_timing.cpp
@@ -300,6 +300,7 @@
/************************ Subroutine definitions *****************************/
bool try_timing_driven_route(const t_router_opts& router_opts,
const t_analysis_opts& analysis_opts,
+ const std::vector<t_segment_inf>& segment_inf,
vtr::vector<ClusterNetId, float*>& net_delay,
const ClusteredPinAtomPinsLookup& netlist_pin_lookup,
std::shared_ptr<SetupHoldTimingInfo> timing_info,
@@ -354,7 +355,11 @@
route_budgets budgeting_inf;
- auto router_lookahead = make_router_lookahead(router_opts.lookahead_type);
+ const auto* router_lookahead = get_cached_router_lookahead(
+ router_opts.lookahead_type,
+ router_opts.write_router_lookahead,
+ router_opts.read_router_lookahead,
+ segment_inf);
/*
* Routing parameters
@@ -611,7 +616,7 @@
pres_fac *= router_opts.pres_fac_mult;
/* Avoid overflow for high iteration counts, even if acc_cost is big */
- pres_fac = min(pres_fac, static_cast<float>(HUGE_POSITIVE_FLOAT / 1e5));
+ pres_fac = std::min(pres_fac, static_cast<float>(HUGE_POSITIVE_FLOAT / 1e5));
pathfinder_update_cost(pres_fac, router_opts.acc_fac);
}
@@ -884,7 +889,7 @@
for (auto net_id : cluster_ctx.clb_nlist.nets()) {
if (!cluster_ctx.clb_nlist.net_is_ignored(net_id))
- max_pins_per_net = max(max_pins_per_net, (int)cluster_ctx.clb_nlist.net_pins(net_id).size());
+ max_pins_per_net = std::max(max_pins_per_net, (int)cluster_ctx.clb_nlist.net_pins(net_id).size());
}
return (max_pins_per_net);
@@ -953,13 +958,13 @@
* else becomes a bit less critical. This effect becomes more pronounced if
* max_criticality is set lower. */
// VTR_ASSERT(pin_criticality[ipin] > -0.01 && pin_criticality[ipin] < 1.01);
- pin_criticality[ipin] = max(pin_criticality[ipin] - (1.0 - router_opts.max_criticality), 0.0);
+ pin_criticality[ipin] = std::max(pin_criticality[ipin] - (1.0 - router_opts.max_criticality), 0.0);
/* Take pin criticality to some power (1 by default). */
- pin_criticality[ipin] = pow(pin_criticality[ipin], router_opts.criticality_exp);
+ pin_criticality[ipin] = std::pow(pin_criticality[ipin], router_opts.criticality_exp);
/* Cut off pin criticality at max_criticality. */
- pin_criticality[ipin] = min(pin_criticality[ipin], router_opts.max_criticality);
+ pin_criticality[ipin] = std::min(pin_criticality[ipin], router_opts.max_criticality);
} else {
//No timing info, implies we want a min delay routing, so use criticality of 1.
pin_criticality[ipin] = 1.;
@@ -1365,7 +1370,9 @@
RouterStats& router_stats) {
//Add the route tree to the heap with no specific target node
int target_node = OPEN;
- auto router_lookahead = make_router_lookahead(e_router_lookahead::NO_OP);
+ auto router_lookahead = make_router_lookahead(e_router_lookahead::NO_OP,
+ /*write_lookahead=*/"", /*read_lookahead=*/"",
+ /*segment_inf=*/{});
add_route_tree_to_heap(rt_root, target_node, cost_params, *router_lookahead, router_stats);
heap_::build_heap(); // via sifting down everything
@@ -1385,7 +1392,9 @@
t_bb bounding_box,
std::vector<int>& modified_rr_node_inf,
RouterStats& router_stats) {
- auto router_lookahead = make_router_lookahead(e_router_lookahead::NO_OP);
+ auto router_lookahead = make_router_lookahead(e_router_lookahead::NO_OP,
+ /*write_lookahead=*/"", /*read_lookahead=*/"",
+ /*segment_inf=*/{});
auto& device_ctx = g_vpr_ctx.device();
std::vector<t_heap> cheapest_paths(device_ctx.rr_nodes.size());
@@ -1766,9 +1775,9 @@
const t_conn_delay_budget* delay_budget = cost_params.delay_budget;
if (delay_budget) {
float zero = 0.0;
- tot_cost += (delay_budget->short_path_criticality + cost_params.criticality) * max(zero, delay_budget->target_delay - tot_cost);
- tot_cost += pow(max(zero, tot_cost - delay_budget->max_delay), 2) / 100e-12;
- tot_cost += pow(max(zero, delay_budget->min_delay - tot_cost), 2) / 100e-12;
+ tot_cost += (delay_budget->short_path_criticality + cost_params.criticality) * std::max(zero, delay_budget->target_delay - tot_cost);
+ tot_cost += std::pow(std::max(zero, tot_cost - delay_budget->max_delay), 2) / 100e-12;
+ tot_cost += std::pow(std::max(zero, delay_budget->min_delay - tot_cost), 2) / 100e-12;
}
VTR_LOGV_DEBUG(f_router_debug, " Adding node %8d to heap from init route tree with cost %g (%s)\n", inode, tot_cost, describe_rr_node(inode).c_str());
@@ -2017,13 +2026,18 @@
// Integrated Circuits and Systems, vol. 27, no. 4, pp. 686-697, April 2008.
//TODO: Since these targets are delays, shouldn't we be using Tdel instead of new_costs.total_cost on RHS?
- total_cost += (delay_budget->short_path_criticality + cost_params.criticality) * max(0.f, delay_budget->target_delay - total_cost);
- total_cost += pow(max(0.f, total_cost - delay_budget->max_delay), 2) / 100e-12;
- total_cost += pow(max(0.f, delay_budget->min_delay - total_cost), 2) / 100e-12;
+ total_cost += (delay_budget->short_path_criticality + cost_params.criticality) * std::max(0.f, delay_budget->target_delay - total_cost);
+ total_cost += std::pow(std::max(0.f, total_cost - delay_budget->max_delay), 2) / 100e-12;
+ total_cost += std::pow(std::max(0.f, delay_budget->min_delay - total_cost), 2) / 100e-12;
}
//Update total cost
float expected_cost = router_lookahead.get_expected_cost(to_node, target_node, cost_params, to->R_upstream);
+ VTR_LOGV_DEBUG(f_router_debug && !std::isfinite(expected_cost),
+ " Lookahead from %s (%s) to %s (%s) is non-finite, expected_cost = %f, to->R_upstream = %f\n",
+ rr_node_arch_name(to_node).c_str(), describe_rr_node(to_node).c_str(),
+ rr_node_arch_name(target_node).c_str(), describe_rr_node(target_node).c_str(),
+ expected_cost, to->R_upstream);
total_cost = to->backward_path_cost + cost_params.astar_fac * expected_cost;
to->cost = total_cost;
@@ -2197,7 +2211,7 @@
}
}
-void Connection_based_routing_resources::convert_sink_nodes_to_net_pins(vector<int>& rr_sink_nodes) const {
+void Connection_based_routing_resources::convert_sink_nodes_to_net_pins(std::vector<int>& rr_sink_nodes) const {
/* Turn a vector of device_ctx.rr_nodes indices, assumed to be of sinks for a net *
* into the pin indices of the same net. */
@@ -2215,7 +2229,7 @@
}
}
-void Connection_based_routing_resources::put_sink_rt_nodes_in_net_pins_lookup(const vector<t_rt_node*>& sink_rt_nodes,
+void Connection_based_routing_resources::put_sink_rt_nodes_in_net_pins_lookup(const std::vector<t_rt_node*>& sink_rt_nodes,
t_rt_node** rt_node_of_sink) const {
/* Load rt_node_of_sink (which maps a PIN index to a route tree node)
* with a vector of route tree sink nodes. */
diff --git a/vpr/src/route/route_timing.h b/vpr/src/route/route_timing.h
index 004f2f8..c356b09 100644
--- a/vpr/src/route/route_timing.h
+++ b/vpr/src/route/route_timing.h
@@ -15,6 +15,7 @@
bool try_timing_driven_route(const t_router_opts& router_opts,
const t_analysis_opts& analysis_opts,
+ const std::vector<t_segment_inf>& segment_inf,
vtr::vector<ClusterNetId, float*>& net_delay,
const ClusteredPinAtomPinsLookup& netlist_pin_lookup,
std::shared_ptr<SetupHoldTimingInfo> timing_info,
diff --git a/vpr/src/route/route_tree_timing.cpp b/vpr/src/route/route_tree_timing.cpp
index 6cd8004..845394e 100644
--- a/vpr/src/route/route_tree_timing.cpp
+++ b/vpr/src/route/route_tree_timing.cpp
@@ -1,7 +1,6 @@
#include <cstdio>
#include <cmath>
#include <vector>
-using namespace std;
#include "vtr_assert.h"
#include "vtr_log.h"
@@ -688,7 +687,7 @@
void update_remaining_net_delays_from_route_tree(float* net_delay,
const t_rt_node* const* rt_node_of_sink,
- const vector<int>& remaining_sinks) {
+ const std::vector<int>& remaining_sinks) {
/* Like update_net_delays_from_route_tree, but only updates the sinks that were not already routed
* this function doesn't actually need to know about the net, just what sink pins need their net delays updated */
diff --git a/vpr/src/route/router_delay_profiling.cpp b/vpr/src/route/router_delay_profiling.cpp
index 4e89035..ab0343e 100644
--- a/vpr/src/route/router_delay_profiling.cpp
+++ b/vpr/src/route/router_delay_profiling.cpp
@@ -9,7 +9,11 @@
static t_rt_node* setup_routing_resources_no_net(int source_node);
-bool calculate_delay(int source_node, int sink_node, const t_router_opts& router_opts, float* net_delay) {
+RouterDelayProfiler::RouterDelayProfiler(
+ const RouterLookahead* lookahead)
+ : router_lookahead_(lookahead) {}
+
+bool RouterDelayProfiler::calculate_delay(int source_node, int sink_node, const t_router_opts& router_opts, float* net_delay) const {
/* Returns true as long as found some way to hook up this net, even if that *
* way resulted in overuse of resources (congestion). If there is no way *
* to route this net, even ignoring congestion, it returns false. In this *
@@ -41,8 +45,9 @@
std::vector<int> modified_rr_node_inf;
RouterStats router_stats;
- auto router_lookahead = make_router_lookahead(router_opts.lookahead_type);
- t_heap* cheapest = timing_driven_route_connection_from_route_tree(rt_root, sink_node, cost_params, bounding_box, *router_lookahead, modified_rr_node_inf, router_stats);
+ t_heap* cheapest = timing_driven_route_connection_from_route_tree(rt_root,
+ sink_node, cost_params, bounding_box, *router_lookahead_,
+ modified_rr_node_inf, router_stats);
bool found_path = (cheapest != nullptr);
if (found_path) {
@@ -125,7 +130,7 @@
for (int sink_rr_node = 0; sink_rr_node < (int) device_ctx.rr_nodes.size(); ++sink_rr_node) {
float astar_delay = std::numeric_limits<float>::quiet_NaN();
- if (sink_rr_node == src_rr_node) {
+ if (sink_rr_node == src_rr_node) {
astar_delay = 0.;
} else {
calculate_delay(src_rr_node, sink_rr_node, router_opts, &astar_delay);
@@ -191,7 +196,6 @@
router_opts.trim_empty_channels,
router_opts.trim_obs_channels,
router_opts.clock_modeling,
- router_opts.lookahead_type,
directs, num_directs,
&warnings);
diff --git a/vpr/src/route/router_delay_profiling.h b/vpr/src/route/router_delay_profiling.h
index 4275eb5..7bab4e2 100644
--- a/vpr/src/route/router_delay_profiling.h
+++ b/vpr/src/route/router_delay_profiling.h
@@ -1,8 +1,19 @@
+#ifndef ROUTER_DELAY_PROFILING_H_
+#define ROUTER_DELAY_PROFILING_H_
+
#include "vpr_types.h"
+#include "router_lookahead.h"
#include <vector>
-bool calculate_delay(int source_node, int sink_node, const t_router_opts& router_opts, float* net_delay);
+class RouterDelayProfiler {
+ public:
+ RouterDelayProfiler(const RouterLookahead* lookahead);
+ bool calculate_delay(int source_node, int sink_node, const t_router_opts& router_opts, float* net_delay) const;
+
+ private:
+ const RouterLookahead* router_lookahead_;
+};
std::vector<float> calculate_all_path_delays_from_rr_node(int src_rr_node, const t_router_opts& router_opts);
@@ -14,3 +25,5 @@
const int num_directs);
void free_routing_structs();
+
+#endif /* ROUTER_DELAY_PROFILING_H_ */
diff --git a/vpr/src/route/router_lookahead.cpp b/vpr/src/route/router_lookahead.cpp
index 3301e3c..130b862 100644
--- a/vpr/src/route/router_lookahead.cpp
+++ b/vpr/src/route/router_lookahead.cpp
@@ -8,7 +8,7 @@
static int get_expected_segs_to_target(int inode, int target_node, int* num_segs_ortho_dir_ptr);
static int round_up(float x);
-std::unique_ptr<RouterLookahead> make_router_lookahead(e_router_lookahead router_lookahead_type) {
+static std::unique_ptr<RouterLookahead> make_router_lookahead_object(e_router_lookahead router_lookahead_type) {
if (router_lookahead_type == e_router_lookahead::CLASSIC) {
return std::make_unique<ClassicLookahead>();
} else if (router_lookahead_type == e_router_lookahead::MAP) {
@@ -21,6 +21,26 @@
return nullptr;
}
+std::unique_ptr<RouterLookahead> make_router_lookahead(
+ e_router_lookahead router_lookahead_type,
+ std::string write_lookahead,
+ std::string read_lookahead,
+ const std::vector<t_segment_inf>& segment_inf) {
+ std::unique_ptr<RouterLookahead> router_lookahead = make_router_lookahead_object(router_lookahead_type);
+
+ if (read_lookahead.empty()) {
+ router_lookahead->compute(segment_inf);
+ } else {
+ router_lookahead->read(read_lookahead);
+ }
+
+ if (!write_lookahead.empty()) {
+ router_lookahead->write(write_lookahead);
+ }
+
+ return router_lookahead;
+}
+
float ClassicLookahead::get_expected_cost(int current_node, int target_node, const t_conn_cost_params& params, float R_upstream) const {
auto& device_ctx = g_vpr_ctx.device();
@@ -81,6 +101,10 @@
}
}
+void MapLookahead::compute(const std::vector<t_segment_inf>& segment_inf) {
+ compute_router_lookahead(segment_inf.size());
+}
+
float NoOpLookahead::get_expected_cost(int /*current_node*/, int /*target_node*/, const t_conn_cost_params& /*params*/, float /*R_upstream*/) const {
return 0.;
}
@@ -169,3 +193,35 @@
return (num_segs_same_dir);
}
+
+void invalidate_router_lookahead_cache() {
+ auto& router_ctx = g_vpr_ctx.mutable_routing();
+ router_ctx.cached_router_lookahead_.clear();
+}
+
+const RouterLookahead* get_cached_router_lookahead(
+ e_router_lookahead router_lookahead_type,
+ std::string write_lookahead,
+ std::string read_lookahead,
+ const std::vector<t_segment_inf>& segment_inf) {
+ auto& router_ctx = g_vpr_ctx.routing();
+
+ auto cache_key = std::make_tuple(router_lookahead_type, read_lookahead, segment_inf);
+
+ // Check if cache is valid.
+ const RouterLookahead* router_lookahead = router_ctx.cached_router_lookahead_.get(cache_key);
+ if (router_lookahead) {
+ return router_lookahead;
+ } else {
+ // Cache is not valid, compute cached object.
+ auto& mut_router_ctx = g_vpr_ctx.mutable_routing();
+
+ return mut_router_ctx.cached_router_lookahead_.set(
+ cache_key,
+ make_router_lookahead(
+ router_lookahead_type,
+ write_lookahead,
+ read_lookahead,
+ segment_inf));
+ }
+}
diff --git a/vpr/src/route/router_lookahead.h b/vpr/src/route/router_lookahead.h
index 6880651..283df54 100644
--- a/vpr/src/route/router_lookahead.h
+++ b/vpr/src/route/router_lookahead.h
@@ -2,21 +2,67 @@
#define VPR_ROUTER_LOOKAHEAD_H
#include <memory>
#include "vpr_types.h"
+#include "vpr_error.h"
struct t_conn_cost_params; //Forward declaration
class RouterLookahead {
public:
+ // Get expected cost from node to target_node.
+ //
+ // Either compute or read methods must be invoked before invoking
+ // get_expected_cost.
virtual float get_expected_cost(int node, int target_node, const t_conn_cost_params& params, float R_upstream) const = 0;
+ // Compute router lookahead (if needed).
+ virtual void compute(const std::vector<t_segment_inf>& segment_inf) = 0;
+
+ // Read router lookahead data (if any) from specified file.
+ // May be unimplemented, in which case method should throw an exception.
+ virtual void read(const std::string& file) = 0;
+
+ // Write router lookahead data (if any) to specified file.
+ // May be unimplemented, in which case method should throw an exception.
+ virtual void write(const std::string& file) const = 0;
+
virtual ~RouterLookahead() {}
};
-std::unique_ptr<RouterLookahead> make_router_lookahead(e_router_lookahead router_lookahead_type);
+// Force creation of lookahead object.
+//
+// This may involve recomputing the lookahead, so only use if lookahead cache
+// cannot be used.
+std::unique_ptr<RouterLookahead> make_router_lookahead(
+ e_router_lookahead router_lookahead_type,
+ std::string write_lookahead,
+ std::string read_lookahead,
+ const std::vector<t_segment_inf>& segment_inf);
+
+// Clear router lookahead cache (e.g. when changing or free rrgraph).
+void invalidate_router_lookahead_cache();
+
+// Returns lookahead for given rr graph.
+//
+// Object is cached in RouterContext, but access to cached object should
+// performed via this function.
+const RouterLookahead* get_cached_router_lookahead(
+ e_router_lookahead router_lookahead_type,
+ std::string write_lookahead,
+ std::string read_lookahead,
+ const std::vector<t_segment_inf>& segment_inf);
class ClassicLookahead : public RouterLookahead {
public:
float get_expected_cost(int node, int target_node, const t_conn_cost_params& params, float R_upstream) const override;
+ void compute(const std::vector<t_segment_inf>& /*segment_inf*/) override {
+ }
+
+ void read(const std::string& /*file*/) override {
+ VPR_THROW(VPR_ERROR_ROUTE, "ClassicLookahead::read unimplemented");
+ }
+ void write(const std::string& /*file*/) const override {
+ VPR_THROW(VPR_ERROR_ROUTE, "ClassicLookahead::write unimplemented");
+ }
private:
float classic_wire_lookahead_cost(int node, int target_node, float criticality, float R_upstream) const;
@@ -25,11 +71,26 @@
class MapLookahead : public RouterLookahead {
protected:
float get_expected_cost(int node, int target_node, const t_conn_cost_params& params, float R_upstream) const override;
+ void compute(const std::vector<t_segment_inf>& segment_inf) override;
+ void read(const std::string& /*file*/) override {
+ VPR_THROW(VPR_ERROR_ROUTE, "MapLookahead::read unimplemented");
+ }
+ void write(const std::string& /*file*/) const override {
+ VPR_THROW(VPR_ERROR_ROUTE, "MapLookahead::write unimplemented");
+ }
};
class NoOpLookahead : public RouterLookahead {
protected:
float get_expected_cost(int node, int target_node, const t_conn_cost_params& params, float R_upstream) const override;
+ void compute(const std::vector<t_segment_inf>& /*segment_inf*/) override {
+ }
+ void read(const std::string& /*file*/) override {
+ VPR_THROW(VPR_ERROR_ROUTE, "Read not supported for NoOpLookahead");
+ }
+ void write(const std::string& /*file*/) const override {
+ VPR_THROW(VPR_ERROR_ROUTE, "Write not supported for NoOpLookahead");
+ }
};
#endif
diff --git a/vpr/src/route/router_lookahead_map.cpp b/vpr/src/route/router_lookahead_map.cpp
index beb4f67..c2ad6aa 100644
--- a/vpr/src/route/router_lookahead_map.cpp
+++ b/vpr/src/route/router_lookahead_map.cpp
@@ -27,8 +27,6 @@
#include "vtr_time.h"
#include "router_lookahead_map.h"
-using namespace std;
-
/* the cost map is computed by running a Dijkstra search from channel segment rr nodes at the specified reference coordinate */
#define REF_X 3
#define REF_Y 3
@@ -75,7 +73,7 @@
* in the final lookahead cost map */
class Expansion_Cost_Entry {
private:
- vector<Cost_Entry> cost_vector;
+ std::vector<Cost_Entry> cost_vector;
Cost_Entry get_smallest_entry();
Cost_Entry get_average_entry();
@@ -198,7 +196,7 @@
* to that pin is stored is added to an entry in the routing_cost_map */
static void run_dijkstra(int start_node_ind, int start_x, int start_y, t_routing_cost_map& routing_cost_map);
/* iterates over the children of the specified node and selectively pushes them onto the priority queue */
-static void expand_dijkstra_neighbours(PQ_Entry parent_entry, vector<float>& node_visited_costs, vector<bool>& node_expanded, priority_queue<PQ_Entry>& pq);
+static void expand_dijkstra_neighbours(PQ_Entry parent_entry, std::vector<float>& node_visited_costs, std::vector<bool>& node_expanded, std::priority_queue<PQ_Entry>& pq);
/* sets the lookahead cost map entries based on representative cost entries from routing_cost_map */
static void set_lookahead_map_costs(int segment_index, e_rr_type chan_type, t_routing_cost_map& routing_cost_map);
/* fills in missing lookahead map entries by copying the cost of the closest valid entry */
@@ -308,7 +306,7 @@
VTR_ASSERT(rr_type == CHANX || rr_type == CHANY);
- const vector<int>& channel_node_list = device_ctx.rr_node_indices[rr_type][start_x][start_y][0];
+ const std::vector<int>& channel_node_list = device_ctx.rr_node_indices[rr_type][start_x][start_y][0];
/* find first node in channel that has specified segment index and goes in the desired direction */
for (unsigned itrack = 0; itrack < channel_node_list.size(); itrack++) {
@@ -349,12 +347,12 @@
auto& device_ctx = g_vpr_ctx.device();
/* a list of boolean flags (one for each rr node) to figure out if a certain node has already been expanded */
- vector<bool> node_expanded(device_ctx.rr_nodes.size(), false);
+ std::vector<bool> node_expanded(device_ctx.rr_nodes.size(), false);
/* for each node keep a list of the cost with which that node has been visited (used to determine whether to push
* a candidate node onto the expansion queue */
- vector<float> node_visited_costs(device_ctx.rr_nodes.size(), -1.0);
+ std::vector<float> node_visited_costs(device_ctx.rr_nodes.size(), -1.0);
/* a priority queue for expansion */
- priority_queue<PQ_Entry> pq;
+ std::priority_queue<PQ_Entry> pq;
/* first entry has no upstream delay or congestion */
PQ_Entry first_entry(start_node_ind, UNDEFINED, 0, 0, 0, true);
@@ -392,7 +390,7 @@
}
/* iterates over the children of the specified node and selectively pushes them onto the priority queue */
-static void expand_dijkstra_neighbours(PQ_Entry parent_entry, vector<float>& node_visited_costs, vector<bool>& node_expanded, priority_queue<PQ_Entry>& pq) {
+static void expand_dijkstra_neighbours(PQ_Entry parent_entry, std::vector<float>& node_visited_costs, std::vector<bool>& node_expanded, std::priority_queue<PQ_Entry>& pq) {
auto& device_ctx = g_vpr_ctx.device();
int parent_ind = parent_entry.rr_node_ind;
@@ -568,7 +566,7 @@
float bin_size = delay_diff / (float)num_bins;
/* sort the cost entries into bins */
- vector<vector<Cost_Entry> > entry_bins(num_bins, vector<Cost_Entry>());
+ std::vector<std::vector<Cost_Entry> > entry_bins(num_bins, std::vector<Cost_Entry>());
for (auto entry : this->cost_vector) {
float bin_num = floor((entry.delay - min_del_entry.delay) / bin_size);
diff --git a/vpr/src/route/rr_graph.cpp b/vpr/src/route/rr_graph.cpp
index fd837cd..c311947 100644
--- a/vpr/src/route/rr_graph.cpp
+++ b/vpr/src/route/rr_graph.cpp
@@ -6,8 +6,6 @@
#include <vector>
#include "vtr_assert.h"
-using namespace std;
-
#include "vtr_util.h"
#include "vtr_memory.h"
#include "vtr_math.h"
@@ -290,7 +288,7 @@
t_chan_width nodes_per_chan,
const enum e_switch_block_type sb_type,
const int Fs,
- const vector<t_switchblock_inf> switchblocks,
+ const std::vector<t_switchblock_inf> switchblocks,
const int num_arch_switches,
const std::vector<t_segment_inf>& segment_inf,
const int global_route_switch,
@@ -319,7 +317,6 @@
const bool trim_empty_channels,
const bool trim_obs_channels,
const enum e_clock_modeling clock_modeling,
- const e_router_lookahead router_lookahead_type,
const t_direct_inf* directs,
const int num_directs,
int* Warnings) {
@@ -380,10 +377,6 @@
print_rr_graph_stats();
- if (router_lookahead_type == e_router_lookahead::MAP) {
- compute_router_lookahead(segment_inf.size());
- }
-
//Write out rr graph file if needed
if (!det_routing_arch->write_rr_graph_filename.empty()) {
write_rr_graph(det_routing_arch->write_rr_graph_filename.c_str(), segment_inf);
@@ -422,7 +415,7 @@
t_chan_width nodes_per_chan,
const enum e_switch_block_type sb_type,
const int Fs,
- const vector<t_switchblock_inf> switchblocks,
+ const std::vector<t_switchblock_inf> switchblocks,
const int num_arch_switches,
const std::vector<t_segment_inf>& segment_inf,
const int global_route_switch,
@@ -872,7 +865,7 @@
device_ctx.switch_fanin_remap.resize(num_arch_switches);
for (int i_arch_switch = 0; i_arch_switch < num_arch_switches; i_arch_switch++) {
- map<int, int>::iterator it;
+ std::map<int, int>::iterator it;
for (auto fanin_rrswitch : arch_switch_fanins[i_arch_switch]) {
/* the fanin value is in it->first, and we'll need to set what index this i_arch_switch/fanin
* combination maps to (within rr_switch_inf) in it->second) */
@@ -1398,6 +1391,8 @@
device_ctx.rr_node_metadata.clear();
device_ctx.rr_edge_metadata.clear();
+
+ invalidate_router_lookahead_cache();
}
static void build_rr_sinks_sources(const int i,
@@ -2213,8 +2208,8 @@
int width = pin_locations[i].width_offset;
int height = pin_locations[i].height_offset;
- max_width = max(max_width, width);
- max_height = max(max_height, height);
+ max_width = std::max(max_width, width);
+ max_height = std::max(max_height, height);
}
for (int iside = 0; iside < NUM_SIDES; iside++) {
diff --git a/vpr/src/route/rr_graph.h b/vpr/src/route/rr_graph.h
index 42fa13c..f55a64f 100644
--- a/vpr/src/route/rr_graph.h
+++ b/vpr/src/route/rr_graph.h
@@ -36,7 +36,6 @@
const bool trim_empty_channels,
const bool trim_obs_channels,
const enum e_clock_modeling clock_modeling,
- const e_router_lookahead router_lookahead_type,
const t_direct_inf* directs,
const int num_directs,
int* Warnings);
diff --git a/vpr/src/route/rr_graph2.cpp b/vpr/src/route/rr_graph2.cpp
index 79168dd..72bbe09 100644
--- a/vpr/src/route/rr_graph2.cpp
+++ b/vpr/src/route/rr_graph2.cpp
@@ -1,5 +1,4 @@
#include <cstdio>
-using namespace std;
#include "vtr_util.h"
#include "vtr_assert.h"
@@ -305,7 +304,7 @@
/* These properties are used for vpr_to_phy_track to determine
* * twisting of wires. */
seg_details[cur_track].group_start = group_start;
- seg_details[cur_track].group_size = min(ntracks + first_track - group_start, length * fac);
+ seg_details[cur_track].group_size = std::min(ntracks + first_track - group_start, length * fac);
VTR_ASSERT(0 == seg_details[cur_track].group_size % fac);
if (0 == seg_details[cur_track].group_size) {
seg_details[cur_track].group_size = length * fac;
@@ -790,7 +789,7 @@
/* Clip Fc to the number of muxes. */
if (((Fc / 2) > num_inc_muxes) || ((Fc / 2) > num_dec_muxes)) {
*Fc_clipped = true;
- Fc = 2 * min(num_inc_muxes, num_dec_muxes);
+ Fc = 2 * std::min(num_inc_muxes, num_dec_muxes);
}
/* Assign tracks to meet Fc demand */
@@ -1810,7 +1809,7 @@
if (sb_conn_map->count(sb_coord) > 0) {
/* get reference to the connections vector which lists all destination wires for a given source wire
* at a specific coordinate sb_coord */
- vector<t_switchblock_edge>& conn_vector = (*sb_conn_map)[sb_coord];
+ std::vector<t_switchblock_edge>& conn_vector = (*sb_conn_map)[sb_coord];
/* go through the connections... */
for (int iconn = 0; iconn < (int)conn_vector.size(); ++iconn) {
@@ -2041,8 +2040,8 @@
/* Take the smaller index unless the other
* switch is bigger (smaller R). */
- int first_switch = min(to_node_switch, from_node_switch);
- int second_switch = max(to_node_switch, from_node_switch);
+ int first_switch = std::min(to_node_switch, from_node_switch);
+ int second_switch = std::max(to_node_switch, from_node_switch);
if (used < 2) {
VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
diff --git a/vpr/src/route/rr_graph_area.cpp b/vpr/src/route/rr_graph_area.cpp
index ec644e0..7c2ab98 100644
--- a/vpr/src/route/rr_graph_area.cpp
+++ b/vpr/src/route/rr_graph_area.cpp
@@ -1,5 +1,4 @@
#include <cmath>
-using namespace std;
#include "vtr_assert.h"
#include "vtr_log.h"
@@ -147,7 +146,7 @@
num_inputs_to_cblock = (int*)vtr::calloc(device_ctx.rr_nodes.size(), sizeof(int));
- maxlen = max(device_ctx.grid.width(), device_ctx.grid.height());
+ maxlen = std::max(device_ctx.grid.width(), device_ctx.grid.height());
cblock_counted = (bool*)vtr::calloc(maxlen, sizeof(bool));
shared_buffer_trans = (float*)vtr::calloc(maxlen, sizeof(float));
@@ -183,8 +182,8 @@
if (device_ctx.rr_switch_inf[iswitch].buffered()) {
iseg = seg_index_of_sblock(from_node, to_node);
- shared_buffer_trans[iseg] = max(shared_buffer_trans[iseg],
- sharable_switch_trans[iswitch]);
+ shared_buffer_trans[iseg] = std::max(shared_buffer_trans[iseg],
+ sharable_switch_trans[iswitch]);
ntrans_no_sharing += unsharable_switch_trans[iswitch]
+ sharable_switch_trans[iswitch];
@@ -200,8 +199,8 @@
case IPIN:
num_inputs_to_cblock[to_node]++;
- max_inputs_to_cblock = max(max_inputs_to_cblock,
- num_inputs_to_cblock[to_node]);
+ max_inputs_to_cblock = std::max(max_inputs_to_cblock,
+ num_inputs_to_cblock[to_node]);
iseg = seg_index_of_cblock(from_rr_type, to_node);
@@ -259,8 +258,8 @@
+ sharable_switch_trans[iswitch];
ntrans_sharing += unsharable_switch_trans[iswitch];
- shared_opin_buffer_trans = max(shared_opin_buffer_trans,
- sharable_switch_trans[iswitch]);
+ shared_opin_buffer_trans = std::max(shared_opin_buffer_trans,
+ sharable_switch_trans[iswitch]);
}
ntrans_sharing += shared_opin_buffer_trans;
@@ -350,7 +349,7 @@
}
num_inputs_to_cblock = (int*)vtr::calloc(device_ctx.rr_nodes.size(), sizeof(int));
- maxlen = max(device_ctx.grid.width(), device_ctx.grid.height());
+ maxlen = std::max(device_ctx.grid.width(), device_ctx.grid.height());
cblock_counted = (bool*)vtr::calloc(maxlen, sizeof(bool));
ntrans = 0;
@@ -419,8 +418,8 @@
case IPIN:
num_inputs_to_cblock[to_node]++;
- max_inputs_to_cblock = max(max_inputs_to_cblock,
- num_inputs_to_cblock[to_node]);
+ max_inputs_to_cblock = std::max(max_inputs_to_cblock,
+ num_inputs_to_cblock[to_node]);
iseg = seg_index_of_cblock(from_rr_type, to_node);
if (cblock_counted[iseg] == false) {
@@ -597,7 +596,7 @@
* ones. */
num_stage = vtr::nint(log10(R_minW_nmos / Rbuf) / log10(4.));
- num_stage = max(num_stage, 1);
+ num_stage = std::max(num_stage, 1);
stage_ratio = pow((float)(R_minW_nmos / Rbuf), (float)(1. / (float)num_stage));
Rstage = R_minW_nmos;
diff --git a/vpr/src/route/rr_graph_indexed_data.cpp b/vpr/src/route/rr_graph_indexed_data.cpp
index 9f80215..dc2218b 100644
--- a/vpr/src/route/rr_graph_indexed_data.cpp
+++ b/vpr/src/route/rr_graph_indexed_data.cpp
@@ -1,5 +1,4 @@
#include <cmath> /* Needed only for sqrt call (remove if sqrt removed) */
-using namespace std;
#include "vtr_assert.h"
#include "vtr_log.h"
diff --git a/vpr/src/route/rr_graph_reader.cpp b/vpr/src/route/rr_graph_reader.cpp
index b2d0ae6..e9380b1 100644
--- a/vpr/src/route/rr_graph_reader.cpp
+++ b/vpr/src/route/rr_graph_reader.cpp
@@ -46,9 +46,6 @@
#include "rr_graph_reader.h"
-using namespace std;
-using namespace pugiutil;
-
/*********************** Subroutines local to this module *******************/
void process_switches(pugi::xml_node parent, const pugiutil::loc_data& loc_data);
void verify_segments(pugi::xml_node parent, const pugiutil::loc_data& loc_data, const std::vector<t_segment_inf>& segment_inf);
@@ -96,7 +93,7 @@
auto rr_graph = get_single_child(doc, "rr_graph", loc_data);
//Check for errors
- Prop = get_attribute(rr_graph, "tool_version", loc_data, OPTIONAL).as_string(nullptr);
+ Prop = get_attribute(rr_graph, "tool_version", loc_data, pugiutil::OPTIONAL).as_string(nullptr);
if (Prop != nullptr) {
if (strcmp(Prop, vtr::VERSION) != 0) {
VTR_LOG("\n");
@@ -105,8 +102,8 @@
VTR_LOG("\n");
}
}
- Prop = get_attribute(rr_graph, "tool_comment", loc_data, OPTIONAL).as_string(nullptr);
- string correct_string = "Generated from arch file ";
+ Prop = get_attribute(rr_graph, "tool_comment", loc_data, pugiutil::OPTIONAL).as_string(nullptr);
+ std::string correct_string = "Generated from arch file ";
correct_string += get_arch_file_name();
if (Prop != nullptr) {
if (Prop != correct_string) {
@@ -181,7 +178,7 @@
check_rr_graph(graph_type, grid, device_ctx.physical_tile_types);
- } catch (XmlError& e) {
+ } catch (pugiutil::XmlError& e) {
vpr_throw(VPR_ERROR_ROUTE, read_rr_graph_name, e.line(), "%s", e.what());
}
}
@@ -196,7 +193,7 @@
while (Switch) {
int iSwitch = get_attribute(Switch, "id", loc_data).as_int();
auto& rr_switch = device_ctx.rr_switch_inf[iSwitch];
- const char* name = get_attribute(Switch, "name", loc_data, OPTIONAL).as_string(nullptr);
+ const char* name = get_attribute(Switch, "name", loc_data, pugiutil::OPTIONAL).as_string(nullptr);
bool found_arch_name = false;
if (name != nullptr) {
for (int i = 0; i < device_ctx.num_arch_switches; ++i) {
@@ -230,7 +227,7 @@
VPR_FATAL_ERROR(VPR_ERROR_ROUTE, "Invalid switch type '%s'\n", switch_type_str.c_str());
}
rr_switch.set_type(switch_type);
- SwitchSubnode = get_single_child(Switch, "timing", loc_data, OPTIONAL);
+ SwitchSubnode = get_single_child(Switch, "timing", loc_data, pugiutil::OPTIONAL);
if (SwitchSubnode) {
rr_switch.R = get_attribute(SwitchSubnode, "R", loc_data).as_float();
rr_switch.Cin = get_attribute(SwitchSubnode, "Cin", loc_data).as_float();
@@ -267,9 +264,9 @@
id = get_attribute(rr_node, "id", loc_data).as_int();
auto& node = device_ctx.rr_nodes[id];
- segmentSubnode = get_single_child(rr_node, "segment", loc_data, OPTIONAL);
+ segmentSubnode = get_single_child(rr_node, "segment", loc_data, pugiutil::OPTIONAL);
if (segmentSubnode) {
- attribute = get_attribute(segmentSubnode, "segment_id", loc_data, OPTIONAL);
+ attribute = get_attribute(segmentSubnode, "segment_id", loc_data, pugiutil::OPTIONAL);
if (attribute) {
int seg_id = get_attribute(segmentSubnode, "segment_id", loc_data).as_int(0);
device_ctx.rr_indexed_data[node.cost_index()].seg_index = seg_id;
@@ -357,7 +354,7 @@
node.set_ptc_num(get_attribute(locSubnode, "ptc", loc_data).as_int());
//-------
- timingSubnode = get_single_child(rr_node, "timing", loc_data, OPTIONAL);
+ timingSubnode = get_single_child(rr_node, "timing", loc_data, pugiutil::OPTIONAL);
float R = 0.;
float C = 0.;
@@ -373,7 +370,7 @@
// <metadata>
// <meta name='grid_prefix' >CLBLL_L_</meta>
// </metadata>
- auto metadata = get_single_child(rr_node, "metadata", loc_data, OPTIONAL);
+ auto metadata = get_single_child(rr_node, "metadata", loc_data, pugiutil::OPTIONAL);
if (metadata) {
auto rr_node_meta = get_first_child(metadata, "meta", loc_data);
while (rr_node_meta) {
@@ -397,7 +394,7 @@
edges = get_first_child(parent, "edge", loc_data);
//count the number of edges and store it in a vector
- vector<size_t> num_edges_for_node;
+ std::vector<size_t> num_edges_for_node;
num_edges_for_node.resize(device_ctx.rr_nodes.size(), 0);
while (edges) {
@@ -430,7 +427,7 @@
std::vector<int> count_for_wire_to_ipin_switches;
count_for_wire_to_ipin_switches.resize(num_rr_switches, 0);
//first is index, second is count
- pair<int, int> most_frequent_switch(-1, 0);
+ std::pair<int, int> most_frequent_switch(-1, 0);
while (edges) {
size_t source_node = get_attribute(edges, "src_node", loc_data).as_uint();
@@ -465,7 +462,7 @@
device_ctx.rr_nodes[source_node].set_edge_switch(num_edges_for_node[source_node], switch_id);
// Read the metadata for the edge
- auto metadata = get_single_child(edges, "metadata", loc_data, OPTIONAL);
+ auto metadata = get_single_child(edges, "metadata", loc_data, pugiutil::OPTIONAL);
if (metadata) {
auto edges_meta = get_first_child(metadata, "meta", loc_data);
while (edges_meta) {
@@ -591,9 +588,9 @@
"Architecture file does not match RR graph's block height");
}
- pin_class = get_first_child(Block, "pin_class", loc_data, OPTIONAL);
+ pin_class = get_first_child(Block, "pin_class", loc_data, pugiutil::OPTIONAL);
- block_info.num_class = count_children(Block, "pin_class", loc_data, OPTIONAL);
+ block_info.num_class = count_children(Block, "pin_class", loc_data, pugiutil::OPTIONAL);
for (int classNum = 0; classNum < block_info.num_class; classNum++) {
auto& class_inf = block_info.class_inf[classNum];
@@ -623,7 +620,7 @@
"Incorrect number of pins in %d pin_class in block %s", classNum, block_info.name);
}
- pin = get_first_child(pin_class, "pin", loc_data, OPTIONAL);
+ pin = get_first_child(pin_class, "pin", loc_data, pugiutil::OPTIONAL);
while (pin) {
auto num = get_attribute(pin, "ptc", loc_data).as_uint();
auto index = pin_index_by_num(class_inf, num);
@@ -659,7 +656,7 @@
"Architecture file does not match RR graph's segment name: arch uses %s, RR graph uses %s", segment_inf[segNum].name.c_str(), name);
}
- subnode = get_single_child(parent, "timing", loc_data, OPTIONAL);
+ subnode = get_single_child(parent, "timing", loc_data, pugiutil::OPTIONAL);
if (subnode) {
if (segment_inf[segNum].Rmetal != get_attribute(subnode, "R_per_meter", loc_data).as_float(0)) {
@@ -870,9 +867,9 @@
/*CHANX and CHANY cost index is dependent on the segment id*/
- segmentSubnode = get_single_child(rr_node, "segment", loc_data, OPTIONAL);
+ segmentSubnode = get_single_child(rr_node, "segment", loc_data, pugiutil::OPTIONAL);
if (segmentSubnode) {
- attribute = get_attribute(segmentSubnode, "segment_id", loc_data, OPTIONAL);
+ attribute = get_attribute(segmentSubnode, "segment_id", loc_data, pugiutil::OPTIONAL);
if (attribute) {
int seg_id = get_attribute(segmentSubnode, "segment_id", loc_data).as_int(0);
if (is_global_graph) {
diff --git a/vpr/src/route/rr_graph_timing_params.cpp b/vpr/src/route/rr_graph_timing_params.cpp
index df35525..69ea020 100644
--- a/vpr/src/route/rr_graph_timing_params.cpp
+++ b/vpr/src/route/rr_graph_timing_params.cpp
@@ -11,7 +11,6 @@
#include "rr_graph2.h"
#include "rr_graph_timing_params.h"
-using namespace std;
/****************** Subroutine definitions *********************************/
void add_rr_graph_C_from_switches(float C_ipin_cblock) {
@@ -41,7 +40,7 @@
auto& device_ctx = g_vpr_ctx.device();
auto& mutable_device_ctx = g_vpr_ctx.mutable_device();
- maxlen = max(device_ctx.grid.width(), device_ctx.grid.height());
+ maxlen = std::max(device_ctx.grid.width(), device_ctx.grid.height());
cblock_counted = (bool*)vtr::calloc(maxlen, sizeof(bool));
buffer_Cin = (float*)vtr::calloc(maxlen, sizeof(float));
@@ -94,7 +93,7 @@
rr_node_C[to_node] += Cout;
}
isblock = seg_index_of_sblock(inode, to_node);
- buffer_Cin[isblock] = max(buffer_Cin[isblock], Cin);
+ buffer_Cin[isblock] = std::max(buffer_Cin[isblock], Cin);
}
}
diff --git a/vpr/src/route/rr_graph_writer.cpp b/vpr/src/route/rr_graph_writer.cpp
index 502cec5..9b0b960 100644
--- a/vpr/src/route/rr_graph_writer.cpp
+++ b/vpr/src/route/rr_graph_writer.cpp
@@ -16,37 +16,35 @@
#include "vtr_version.h"
#include "rr_graph_writer.h"
-using namespace std;
-
/* All values are printed with this precision value. The higher the
* value, the more accurate the read in rr graph is. Using numeric_limits
* max_digits10 guarentees that no values change during a sequence of
* float -> string -> float conversions */
constexpr int FLOAT_PRECISION = std::numeric_limits<float>::max_digits10;
/*********************** Subroutines local to this module *******************/
-void write_rr_channel(fstream& fp);
-void write_rr_node(fstream& fp);
-void write_rr_switches(fstream& fp);
-void write_rr_grid(fstream& fp);
-void write_rr_edges(fstream& fp);
-void write_rr_block_types(fstream& fp);
-void write_rr_segments(fstream& fp, const std::vector<t_segment_inf>& segment_inf);
+void write_rr_channel(std::fstream& fp);
+void write_rr_node(std::fstream& fp);
+void write_rr_switches(std::fstream& fp);
+void write_rr_grid(std::fstream& fp);
+void write_rr_edges(std::fstream& fp);
+void write_rr_block_types(std::fstream& fp);
+void write_rr_segments(std::fstream& fp, const std::vector<t_segment_inf>& segment_inf);
/************************ Subroutine definitions ****************************/
/* This function is used to write the rr_graph into xml format into a a file with name: file_name */
void write_rr_graph(const char* file_name, const std::vector<t_segment_inf>& segment_inf) {
- fstream fp;
- fp.open(file_name, fstream::out | fstream::trunc);
+ std::fstream fp;
+ fp.open(file_name, std::fstream::out | std::fstream::trunc);
/* Prints out general info for easy error checking*/
if (!fp.is_open() || !fp.good()) {
VPR_FATAL_ERROR(VPR_ERROR_OTHER,
"couldn't open file \"%s\" for generating RR graph file\n", file_name);
}
- cout << "Writing RR graph" << endl;
+ std::cout << "Writing RR graph" << std::endl;
fp << "<rr_graph tool_name=\"vpr\" tool_version=\"" << vtr::VERSION << "\" tool_comment=\"Generated from arch file "
- << get_arch_file_name() << "\">" << endl;
+ << get_arch_file_name() << "\">" << std::endl;
/* Write out each individual component*/
write_rr_channel(fp);
@@ -60,49 +58,49 @@
fp.close();
- cout << "Finished generating RR graph file named " << file_name << endl
- << endl;
+ std::cout << "Finished generating RR graph file named " << file_name << std::endl
+ << std::endl;
}
-static void add_metadata_to_xml(fstream& fp, const char* tab_prefix, const t_metadata_dict& meta) {
- fp << tab_prefix << "<metadata>" << endl;
+static void add_metadata_to_xml(std::fstream& fp, const char* tab_prefix, const t_metadata_dict& meta) {
+ fp << tab_prefix << "<metadata>" << std::endl;
for (const auto& meta_elem : meta) {
const std::string& key = meta_elem.first;
const std::vector<t_metadata_value>& values = meta_elem.second;
for (const auto& value : values) {
fp << tab_prefix << "\t<meta name=\"" << key << "\"";
- fp << ">" << value.as_string() << "</meta>" << endl;
+ fp << ">" << value.as_string() << "</meta>" << std::endl;
}
}
- fp << tab_prefix << "</metadata>" << endl;
+ fp << tab_prefix << "</metadata>" << std::endl;
}
/* Channel info in device_ctx.chan_width is written in xml format.
* A general summary of the min and max values of the channels are first printed. Every
* x and y channel list is printed out in its own attribute*/
-void write_rr_channel(fstream& fp) {
+void write_rr_channel(std::fstream& fp) {
auto& device_ctx = g_vpr_ctx.device();
- fp << "\t<channels>" << endl;
- fp << "\t\t<channel chan_width_max =\"" << device_ctx.chan_width.max << "\" x_min=\"" << device_ctx.chan_width.x_min << "\" y_min=\"" << device_ctx.chan_width.y_min << "\" x_max=\"" << device_ctx.chan_width.x_max << "\" y_max=\"" << device_ctx.chan_width.y_max << "\"/>" << endl;
+ fp << "\t<channels>" << std::endl;
+ fp << "\t\t<channel chan_width_max =\"" << device_ctx.chan_width.max << "\" x_min=\"" << device_ctx.chan_width.x_min << "\" y_min=\"" << device_ctx.chan_width.y_min << "\" x_max=\"" << device_ctx.chan_width.x_max << "\" y_max=\"" << device_ctx.chan_width.y_max << "\"/>" << std::endl;
auto& list = device_ctx.chan_width.x_list;
for (size_t i = 0; i < device_ctx.grid.height() - 1; i++) {
- fp << "\t\t<x_list index =\"" << i << "\" info=\"" << list[i] << "\"/>" << endl;
+ fp << "\t\t<x_list index =\"" << i << "\" info=\"" << list[i] << "\"/>" << std::endl;
}
auto& list2 = device_ctx.chan_width.y_list;
for (size_t i = 0; i < device_ctx.grid.width() - 1; i++) {
- fp << "\t\t<y_list index =\"" << i << "\" info=\"" << list2[i] << "\"/>" << endl;
+ fp << "\t\t<y_list index =\"" << i << "\" info=\"" << list2[i] << "\"/>" << std::endl;
}
- fp << "\t</channels>" << endl;
+ fp << "\t</channels>" << std::endl;
}
/* All relevant rr node info is written out to the graph.
* This includes location, timing, and segment info*/
-void write_rr_node(fstream& fp) {
+void write_rr_node(std::fstream& fp) {
auto& device_ctx = g_vpr_ctx.device();
- fp << "\t<rr_nodes>" << endl;
+ fp << "\t<rr_nodes>" << std::endl;
for (size_t inode = 0; inode < device_ctx.rr_nodes.size(); inode++) {
auto& node = device_ctx.rr_nodes[inode];
@@ -113,7 +111,7 @@
fp << "\" direction=\"" << node.direction_string();
}
fp << "\" capacity=\"" << node.capacity();
- fp << "\">" << endl;
+ fp << "\">" << std::endl;
fp << "\t\t\t<loc";
fp << " xlow=\"" << node.xlow();
fp << "\" ylow=\"" << node.ylow();
@@ -123,12 +121,12 @@
fp << "\" side=\"" << node.side_string();
}
fp << "\" ptc=\"" << node.ptc_num();
- fp << "\"/>" << endl;
- fp << "\t\t\t<timing R=\"" << setprecision(FLOAT_PRECISION) << node.R()
- << "\" C=\"" << setprecision(FLOAT_PRECISION) << node.C() << "\"/>" << endl;
+ fp << "\"/>" << std::endl;
+ fp << "\t\t\t<timing R=\"" << std::setprecision(FLOAT_PRECISION) << node.R()
+ << "\" C=\"" << std::setprecision(FLOAT_PRECISION) << node.C() << "\"/>" << std::endl;
if (device_ctx.rr_indexed_data[node.cost_index()].seg_index != -1) {
- fp << "\t\t\t<segment segment_id=\"" << device_ctx.rr_indexed_data[node.cost_index()].seg_index << "\"/>" << endl;
+ fp << "\t\t\t<segment segment_id=\"" << device_ctx.rr_indexed_data[node.cost_index()].seg_index << "\"/>" << std::endl;
}
const auto iter = device_ctx.rr_node_metadata.find(inode);
@@ -137,32 +135,32 @@
add_metadata_to_xml(fp, "\t\t\t", meta);
}
- fp << "\t\t</node>" << endl;
+ fp << "\t\t</node>" << std::endl;
}
- fp << "\t</rr_nodes>" << endl
- << endl;
+ fp << "\t</rr_nodes>" << std::endl
+ << std::endl;
}
/* Segment information in the t_segment_inf data structure is written out.
* Information includes segment id, name, and optional timing parameters*/
-void write_rr_segments(fstream& fp, const std::vector<t_segment_inf>& segment_inf) {
- fp << "\t<segments>" << endl;
+void write_rr_segments(std::fstream& fp, const std::vector<t_segment_inf>& segment_inf) {
+ fp << "\t<segments>" << std::endl;
for (size_t iseg = 0; iseg < segment_inf.size(); iseg++) {
- fp << "\t\t<segment id=\"" << iseg << "\" name=\"" << segment_inf[iseg].name << "\">" << endl;
- fp << "\t\t\t<timing R_per_meter=\"" << setprecision(FLOAT_PRECISION) << segment_inf[iseg].Rmetal << "\" C_per_meter=\"" << setprecision(FLOAT_PRECISION) << segment_inf[iseg].Cmetal << "\"/>" << endl;
- fp << "\t\t</segment>" << endl;
+ fp << "\t\t<segment id=\"" << iseg << "\" name=\"" << segment_inf[iseg].name << "\">" << std::endl;
+ fp << "\t\t\t<timing R_per_meter=\"" << std::setprecision(FLOAT_PRECISION) << segment_inf[iseg].Rmetal << "\" C_per_meter=\"" << std::setprecision(FLOAT_PRECISION) << segment_inf[iseg].Cmetal << "\"/>" << std::endl;
+ fp << "\t\t</segment>" << std::endl;
}
- fp << "\t</segments>" << endl
- << endl;
+ fp << "\t</segments>" << std::endl
+ << std::endl;
}
/* Switch info is written out into xml format. This includes
* general, sizing, and optional timing information*/
-void write_rr_switches(fstream& fp) {
+void write_rr_switches(std::fstream& fp) {
auto& device_ctx = g_vpr_ctx.device();
- fp << "\t<switches>" << endl;
+ fp << "\t<switches>" << std::endl;
for (size_t iSwitch = 0; iSwitch < device_ctx.rr_switch_inf.size(); iSwitch++) {
t_rr_switch_inf rr_switch = device_ctx.rr_switch_inf[iSwitch];
@@ -187,21 +185,21 @@
if (rr_switch.name) {
fp << " name=\"" << rr_switch.name << "\"";
}
- fp << ">" << endl;
+ fp << ">" << std::endl;
- fp << "\t\t\t<timing R=\"" << setprecision(FLOAT_PRECISION) << rr_switch.R << "\" Cin=\"" << setprecision(FLOAT_PRECISION) << rr_switch.Cin << "\" Cout=\"" << setprecision(FLOAT_PRECISION) << rr_switch.Cout << "\" Cinternal=\"" << setprecision(FLOAT_PRECISION) << rr_switch.Cinternal << "\" Tdel=\"" << setprecision(FLOAT_PRECISION) << rr_switch.Tdel << "\"/>" << endl;
- fp << "\t\t\t<sizing mux_trans_size=\"" << setprecision(FLOAT_PRECISION) << rr_switch.mux_trans_size << "\" buf_size=\"" << setprecision(FLOAT_PRECISION) << rr_switch.buf_size << "\"/>" << endl;
- fp << "\t\t</switch>" << endl;
+ fp << "\t\t\t<timing R=\"" << std::setprecision(FLOAT_PRECISION) << rr_switch.R << "\" Cin=\"" << std::setprecision(FLOAT_PRECISION) << rr_switch.Cin << "\" Cout=\"" << std::setprecision(FLOAT_PRECISION) << rr_switch.Cout << "\" Cinternal=\"" << std::setprecision(FLOAT_PRECISION) << rr_switch.Cinternal << "\" Tdel=\"" << std::setprecision(FLOAT_PRECISION) << rr_switch.Tdel << "\"/>" << std::endl;
+ fp << "\t\t\t<sizing mux_trans_size=\"" << std::setprecision(FLOAT_PRECISION) << rr_switch.mux_trans_size << "\" buf_size=\"" << std::setprecision(FLOAT_PRECISION) << rr_switch.buf_size << "\"/>" << std::endl;
+ fp << "\t\t</switch>" << std::endl;
}
- fp << "\t</switches>" << endl
- << endl;
+ fp << "\t</switches>" << std::endl
+ << std::endl;
}
/* Block information is printed out in xml format. This includes general,
* pin class, and pins */
-void write_rr_block_types(fstream& fp) {
+void write_rr_block_types(std::fstream& fp) {
auto& device_ctx = g_vpr_ctx.device();
- fp << "\t<block_types>" << endl;
+ fp << "\t<block_types>" << std::endl;
for (const auto& btype : device_ctx.physical_tile_types) {
fp << "\t\t<block_type id=\"" << btype.index;
@@ -209,7 +207,7 @@
VTR_ASSERT(btype.name);
fp << "\" name=\"" << btype.name;
- fp << "\" width=\"" << btype.width << "\" height=\"" << btype.height << "\">" << endl;
+ fp << "\" width=\"" << btype.width << "\" height=\"" << btype.height << "\">" << std::endl;
for (int iClass = 0; iClass < btype.num_class; iClass++) {
auto& class_inf = btype.class_inf[iClass];
@@ -237,37 +235,37 @@
fp << vtr::string_fmt("\t\t\t\t<pin ptc=\"%d\">%s</pin>\n",
pin, block_type_pin_index_to_name(&btype, pin).c_str());
}
- fp << "\t\t\t</pin_class>" << endl;
+ fp << "\t\t\t</pin_class>" << std::endl;
}
- fp << "\t\t</block_type>" << endl;
+ fp << "\t\t</block_type>" << std::endl;
}
- fp << "\t</block_types>" << endl
- << endl;
+ fp << "\t</block_types>" << std::endl
+ << std::endl;
}
/* Grid information is printed out in xml format. Each grid location
* and its relevant information is included*/
-void write_rr_grid(fstream& fp) {
+void write_rr_grid(std::fstream& fp) {
auto& device_ctx = g_vpr_ctx.device();
- fp << "\t<grid>" << endl;
+ fp << "\t<grid>" << std::endl;
for (size_t x = 0; x < device_ctx.grid.width(); x++) {
for (size_t y = 0; y < device_ctx.grid.height(); y++) {
t_grid_tile grid_tile = device_ctx.grid[x][y];
- fp << "\t\t<grid_loc x=\"" << x << "\" y=\"" << y << "\" block_type_id=\"" << grid_tile.type->index << "\" width_offset=\"" << grid_tile.width_offset << "\" height_offset=\"" << grid_tile.height_offset << "\"/>" << endl;
+ fp << "\t\t<grid_loc x=\"" << x << "\" y=\"" << y << "\" block_type_id=\"" << grid_tile.type->index << "\" width_offset=\"" << grid_tile.width_offset << "\" height_offset=\"" << grid_tile.height_offset << "\"/>" << std::endl;
}
}
- fp << "\t</grid>" << endl
- << endl;
+ fp << "\t</grid>" << std::endl
+ << std::endl;
}
/* Edges connecting to each rr node is printed out. The two nodes
* it connects to are also printed*/
-void write_rr_edges(fstream& fp) {
+void write_rr_edges(std::fstream& fp) {
auto& device_ctx = g_vpr_ctx.device();
- fp << "\t<rr_edges>" << endl;
+ fp << "\t<rr_edges>" << std::endl;
for (size_t inode = 0; inode < device_ctx.rr_nodes.size(); inode++) {
auto& node = device_ctx.rr_nodes[inode];
@@ -277,7 +275,7 @@
bool wrote_edge_metadata = false;
const auto iter = device_ctx.rr_edge_metadata.find(std::make_tuple(inode, node.edge_sink_node(iedge), node.edge_switch(iedge)));
if (iter != device_ctx.rr_edge_metadata.end()) {
- fp << ">" << endl;
+ fp << ">" << std::endl;
const t_metadata_dict& meta = iter->second;
add_metadata_to_xml(fp, "\t\t\t", meta);
@@ -285,12 +283,12 @@
}
if (wrote_edge_metadata == false) {
- fp << "/>" << endl;
+ fp << "/>" << std::endl;
} else {
- fp << "\t\t</edge>" << endl;
+ fp << "\t\t</edge>" << std::endl;
}
}
}
- fp << "\t</rr_edges>" << endl
- << endl;
+ fp << "\t</rr_edges>" << std::endl
+ << std::endl;
}
diff --git a/vpr/src/route/segment_stats.cpp b/vpr/src/route/segment_stats.cpp
index 7ab8666..7af48b1 100644
--- a/vpr/src/route/segment_stats.cpp
+++ b/vpr/src/route/segment_stats.cpp
@@ -1,5 +1,4 @@
#include <cstdio>
-using namespace std;
#include "vtr_log.h"
#include "vtr_memory.h"
@@ -32,8 +31,8 @@
max_segment_length = 0;
for (size_t seg_type = 0; seg_type < segment_inf.size(); seg_type++) {
if (segment_inf[seg_type].longline == false)
- max_segment_length = max(max_segment_length,
- segment_inf[seg_type].length);
+ max_segment_length = std::max(max_segment_length,
+ segment_inf[seg_type].length);
}
seg_occ_by_length = (int*)vtr::calloc((max_segment_length + 1),
diff --git a/vpr/src/timing/concrete_timing_info.h b/vpr/src/timing/concrete_timing_info.h
index 745a6ba..465b3fa 100644
--- a/vpr/src/timing/concrete_timing_info.h
+++ b/vpr/src/timing/concrete_timing_info.h
@@ -34,11 +34,17 @@
public:
//Accessors
tatum::TimingPathInfo least_slack_critical_path() const override {
- return find_least_slack_critical_path_delay(*timing_constraints_, *setup_analyzer_);
+ if (least_slack_critical_path_.type() == tatum::TimingType::UNKOWN) {
+ least_slack_critical_path_ = find_least_slack_critical_path_delay(*timing_constraints_, *setup_analyzer_);
+ }
+ return least_slack_critical_path_;
}
tatum::TimingPathInfo longest_critical_path() const override {
- return find_longest_critical_path_delay(*timing_constraints_, *setup_analyzer_);
+ if (longest_critical_path_.type() == tatum::TimingType::UNKOWN) {
+ longest_critical_path_ = find_longest_critical_path_delay(*timing_constraints_, *setup_analyzer_);
+ }
+ return longest_critical_path_;
}
std::vector<tatum::TimingPathInfo> critical_paths() const override {
@@ -46,11 +52,17 @@
}
float setup_total_negative_slack() const override {
- return find_setup_total_negative_slack(*setup_analyzer_);
+ if (std::isnan(sTNS_)) {
+ sTNS_ = find_setup_total_negative_slack(*setup_analyzer_);
+ }
+ return sTNS_;
}
float setup_worst_negative_slack() const override {
- return find_setup_worst_negative_slack(*setup_analyzer_);
+ if (std::isnan(sWNS_)) {
+ sWNS_ = find_setup_worst_negative_slack(*setup_analyzer_);
+ }
+ return sWNS_;
}
float setup_pin_slack(AtomPinId pin) const override {
@@ -85,6 +97,12 @@
if (warn_unconstrained_) {
warn_unconstrained(analyzer());
}
+
+ //Reset cached values to invalid (calculated lazily in accessors)
+ sTNS_ = std::numeric_limits<float>::quiet_NaN();
+ sWNS_ = std::numeric_limits<float>::quiet_NaN();
+ least_slack_critical_path_ = tatum::TimingPathInfo();
+ longest_critical_path_ = tatum::TimingPathInfo();
}
void update_setup() override {
@@ -121,7 +139,6 @@
void set_warn_unconstrained(bool val) override { warn_unconstrained_ = val; }
private:
- private:
//Data
std::shared_ptr<const tatum::TimingGraph> timing_graph_;
std::shared_ptr<const tatum::TimingConstraints> timing_constraints_;
@@ -130,6 +147,12 @@
SetupSlackCrit slack_crit_;
+ //Cached values
+ mutable float sTNS_ = std::numeric_limits<float>::quiet_NaN();
+ mutable float sWNS_ = std::numeric_limits<float>::quiet_NaN();
+ mutable tatum::TimingPathInfo least_slack_critical_path_;
+ mutable tatum::TimingPathInfo longest_critical_path_;
+
bool warn_unconstrained_ = true;
typedef std::chrono::duration<double> dsec;
diff --git a/vpr/src/timing/net_delay.cpp b/vpr/src/timing/net_delay.cpp
index ff4b2a6..a2cbc73 100644
--- a/vpr/src/timing/net_delay.cpp
+++ b/vpr/src/timing/net_delay.cpp
@@ -1,5 +1,4 @@
#include <cstdio>
-using namespace std;
#include "vtr_memory.h"
#include "vtr_log.h"
diff --git a/vpr/src/util/hash.cpp b/vpr/src/util/hash.cpp
index 66fbf34..b55ace2 100644
--- a/vpr/src/util/hash.cpp
+++ b/vpr/src/util/hash.cpp
@@ -1,6 +1,5 @@
#include <cstdlib>
#include <cstring>
-using namespace std;
#include "vtr_memory.h"
#include "vtr_log.h"
diff --git a/vpr/src/util/vpr_utils.cpp b/vpr/src/util/vpr_utils.cpp
index 7264afe..463a727 100644
--- a/vpr/src/util/vpr_utils.cpp
+++ b/vpr/src/util/vpr_utils.cpp
@@ -3,8 +3,6 @@
#include <regex>
#include <algorithm>
-using namespace std;
-
#include "vtr_assert.h"
#include "vtr_log.h"
#include "vtr_memory.h"
@@ -2106,13 +2104,13 @@
VTR_LOG_WARN("Cannot print switch usage stats: device_ctx.switch_fanin_remap is empty\n");
return;
}
- map<int, int>* switch_fanin_count;
- map<int, float>* switch_fanin_delay;
- switch_fanin_count = new map<int, int>[device_ctx.num_arch_switches];
- switch_fanin_delay = new map<int, float>[device_ctx.num_arch_switches];
+ std::map<int, int>* switch_fanin_count;
+ std::map<int, float>* switch_fanin_delay;
+ switch_fanin_count = new std::map<int, int>[device_ctx.num_arch_switches];
+ switch_fanin_delay = new std::map<int, float>[device_ctx.num_arch_switches];
// a node can have multiple inward switches, so
// map key: switch index; map value: count (fanin)
- map<int, int>* inward_switch_inf = new map<int, int>[device_ctx.rr_nodes.size()];
+ std::map<int, int>* inward_switch_inf = new std::map<int, int>[device_ctx.rr_nodes.size()];
for (size_t inode = 0; inode < device_ctx.rr_nodes.size(); inode++) {
const t_rr_node& from_node = device_ctx.rr_nodes[inode];
int num_edges = from_node.num_edges();
@@ -2129,7 +2127,7 @@
}
}
for (size_t inode = 0; inode < device_ctx.rr_nodes.size(); inode++) {
- map<int, int>::iterator itr;
+ std::map<int, int>::iterator itr;
for (itr = inward_switch_inf[inode].begin(); itr != inward_switch_inf[inode].end(); itr++) {
int switch_index = itr->first;
int fanin = itr->second;
@@ -2154,7 +2152,7 @@
float s_area = device_ctx.arch_switch_inf[iswitch].mux_trans_size;
VTR_LOG(">>>>> switch index: %d, name: %s, mux trans size: %g\n", iswitch, s_name, s_area);
- map<int, int>::iterator itr;
+ std::map<int, int>::iterator itr;
for (itr = switch_fanin_count[iswitch].begin(); itr != switch_fanin_count[iswitch].end(); itr++) {
VTR_LOG("\t\tnumber of fanin: %d", itr->first);
VTR_LOG("\t\tnumber of wires driven by this switch: %d", itr->second);
@@ -2238,7 +2236,7 @@
for (auto& type : device_ctx.physical_tile_types) {
int pins_per_grid_tile = type.num_pins / (type.width * type.height);
//Use the maximum number of pins normalized by block area
- max_pins = max(max_pins, pins_per_grid_tile);
+ max_pins = std::max(max_pins, pins_per_grid_tile);
}
return max_pins;
}