Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
05ee3bc
use x/y attributes instead of dim and loc
soheilshahrouz Oct 8, 2025
205a663
cherry-picked device grid changes from add_interposer_wires branch
soheilshahrouz Oct 8, 2025
17d8fae
add getters for interposer cuts in device grid
soheilshahrouz Oct 8, 2025
82dbc62
draw interposer cuts
soheilshahrouz Oct 8, 2025
078423e
draw interposer cuts with respect to next loc
soheilshahrouz Oct 8, 2025
45532c5
replace float* with std::vector<float> for tile_x and tile_y
soheilshahrouz Oct 8, 2025
49a4de1
don't draw interposer lines from -inf to +inf
soheilshahrouz Oct 8, 2025
2cb2c9c
dashed and wider line for interpsoer cut
soheilshahrouz Oct 8, 2025
6fefc24
doxygen comment for draw_interposer_cuts()
soheilshahrouz Oct 8, 2025
f9d8295
updated arch reference doc
soheilshahrouz Oct 8, 2025
49ac734
Merge remote-tracking branch 'origin/master' into temp_interposer_cut…
soheilshahrouz Oct 8, 2025
61f1ade
use VERT/HORX instead of X/Y
soheilshahrouz Oct 8, 2025
b28100a
make format
soheilshahrouz Oct 8, 2025
ccd3a66
update unit tests to be compatible with DeviceGrid constructors
soheilshahrouz Oct 8, 2025
a492b43
enum class e_pic_type
soheilshahrouz Oct 8, 2025
dc85bf4
ifndef NO_GRAPHICS in draw_interposer files
soheilshahrouz Oct 8, 2025
9c23b1b
fix type in the arch reference
soheilshahrouz Oct 9, 2025
3ac8bc9
check if both x and y are specified and error out
soheilshahrouz Oct 9, 2025
1d5bf45
don't use nullptr as default value of strings
soheilshahrouz Oct 9, 2025
aa8a2e5
make get_tile_width() and get_tile_height() const methods
soheilshahrouz Oct 9, 2025
5a10ec2
apply PR comments for drawing interposer
soheilshahrouz Oct 9, 2025
8979661
add doxygen comments
soheilshahrouz Oct 10, 2025
0ee28c8
draw interposer cut lines exactly in the middle of channel/between th…
soheilshahrouz Oct 10, 2025
f256e2f
Merge branch 'master' into temp_interposer_cut_dim
soheilshahrouz Oct 10, 2025
844fe90
add tile_width/tile_height to compute the middle of channel
soheilshahrouz Oct 10, 2025
cd2381e
more detailed comments
soheilshahrouz Oct 11, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions doc/src/arch/reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -582,10 +582,12 @@ Grid Layout Example
Example FPGA grid


.. arch:tag:: <interposer_cut dim=x|y loc="int"/>
.. arch:tag:: <interposer_cut x="int" y="int"/>

:req_param dim: Dimension or axis of the cut. 'X' or 'x' means a horizontal cut while 'Y' or 'y' means a vertical cut.
:req_param loc: Location of the cut. Cuts are done above or to the right of the tiles at coordinate 'loc'. For example a cut with dim=x and loc=0 would cut the vertical wires above tiles in the 0th row. Currently only integer values are supported.
:opt_param x: Specifies the x-coordinate of a vertical interposer cut.
:opt_param y: Specifies the y-coordinate of a horizontal interposer cut.

.. note:: Exactly one of the ``x`` or ``y`` attributes must be specified.

.. note:: Interposers are experimental and are currently not supported by VPR and using the related tags will not actually result in any changes to the flow.
Defines an interposer cut for modelling 2.5D interposer-based architectures. An interposer cut will cut all connections at location 'loc' along the axis 'dim' Leaving the two sides completely unconnected.
Expand Down
19 changes: 13 additions & 6 deletions libs/libarchfpga/src/device_grid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,23 @@

#include <utility>

DeviceGrid::DeviceGrid(std::string grid_name, vtr::NdMatrix<t_grid_tile, 3> grid)
: name_(std::move(grid_name))
, grid_(std::move(grid)) {
DeviceGrid::DeviceGrid(std::string_view grid_name,
vtr::NdMatrix<t_grid_tile, 3> grid,
std::vector<std::vector<int>>&& horizontal_interposer_cuts,
std::vector<std::vector<int>>&& vertical_interposer_cuts)
: name_(grid_name)
, grid_(std::move(grid))
, horizontal_interposer_cuts_(std::move(horizontal_interposer_cuts))
, vertical_interposer_cuts_(std::move(vertical_interposer_cuts)) {
count_instances();
}

DeviceGrid::DeviceGrid(std::string grid_name,
DeviceGrid::DeviceGrid(std::string_view grid_name,
vtr::NdMatrix<t_grid_tile, 3> grid,
std::vector<t_logical_block_type_ptr> limiting_res)
: DeviceGrid(std::move(grid_name), std::move(grid)) {
std::vector<t_logical_block_type_ptr> limiting_res,
std::vector<std::vector<int>>&& horizontal_interposer_cuts,
std::vector<std::vector<int>>&& vertical_interposer_cuts)
: DeviceGrid(grid_name, std::move(grid), std::move(horizontal_interposer_cuts), std::move(vertical_interposer_cuts)) {
limiting_resources_ = std::move(limiting_res);
}

Expand Down
43 changes: 38 additions & 5 deletions libs/libarchfpga/src/device_grid.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,16 @@ struct t_grid_tile {
class DeviceGrid {
public:
DeviceGrid() = default;
DeviceGrid(std::string grid_name, vtr::NdMatrix<t_grid_tile, 3> grid);
DeviceGrid(std::string grid_name, vtr::NdMatrix<t_grid_tile, 3> grid, std::vector<t_logical_block_type_ptr> limiting_res);
DeviceGrid(std::string_view grid_name,
vtr::NdMatrix<t_grid_tile, 3> grid,
std::vector<std::vector<int>>&& horizontal_interposer_cuts,
std::vector<std::vector<int>>&& vertical_interposer_cuts);

DeviceGrid(std::string_view grid_name,
vtr::NdMatrix<t_grid_tile, 3> grid,
std::vector<t_logical_block_type_ptr> limiting_res,
std::vector<std::vector<int>>&& horizontal_interposer_cuts,
std::vector<std::vector<int>>&& vertical_interposer_cuts);

const std::string& name() const { return name_; }

Expand Down Expand Up @@ -63,7 +71,7 @@ class DeviceGrid {
* @brief Returns the block types which limits the device size (may be empty if
* resource limits were not considered when selecting the device).
*/
std::vector<t_logical_block_type_ptr> limiting_resources() const { return limiting_resources_; }
const std::vector<t_logical_block_type_ptr>& limiting_resources() const { return limiting_resources_; }

///@brief Return the t_physical_tile_type_ptr at the specified location
inline t_physical_tile_type_ptr get_physical_type(const t_physical_tile_loc& tile_loc) const {
Expand Down Expand Up @@ -189,15 +197,31 @@ class DeviceGrid {
return &grid_.get(n);
}

/// Returns the list of horizontal interposer cut locations for each layer,
/// i.e. y value of the tile row just below each cut
/// Accessed as [layer][cut_idx]
inline const std::vector<std::vector<int>>& get_horizontal_interposer_cuts() const {
return horizontal_interposer_cuts_;
}

/// Returns the list of vertical interposer cut locations for each layer,
/// i.e. x value of the tile column just to the left each cut
/// Accessed as [layer][cut_idx]
inline const std::vector<std::vector<int>>& get_vertical_interposer_cuts() const {
return vertical_interposer_cuts_;
}

private:
///@brief count_instances() counts the number of each tile type on each layer and store it in instance_counts_. It is called in the constructor.
/// @brief Counts the number of each tile type on each layer and store it in instance_counts_.
/// It is called in the constructor.
void count_instances();

std::string name_;

/**
* @brief grid_ is a 3D matrix that represents the grid of the FPGA chip.
* @note The first dimension is the layer number (grid_[0] corresponds to the bottom layer), the second dimension is the x coordinate, and the third dimension is the y coordinate.
* @note The first dimension is the layer number (grid_[0] corresponds to the bottom layer),
* the second dimension is the x coordinate, and the third dimension is the y coordinate.
* @note Note that vtr::Matrix operator[] returns and intermediate type
* @note which can be used for indexing in the second dimension, allowing
* @note traditional 2-d indexing to be used
Expand All @@ -208,4 +232,13 @@ class DeviceGrid {
std::vector<std::map<t_physical_tile_type_ptr, size_t>> instance_counts_; /* [layer_num][physical_tile_type_ptr] */

std::vector<t_logical_block_type_ptr> limiting_resources_;

/// Horizontal interposer cut locations in each layer,
/// i.e. y value of the tile row just below each cut
/// Accessed as [layer][cut_idx]
std::vector<std::vector<int>> horizontal_interposer_cuts_;
/// Vertical interposer cut location in each layer,
/// i.e. x value of the tile column just to the left each cut
/// Accessed as [layer][cut_idx]
std::vector<std::vector<int>> vertical_interposer_cuts_;
};
27 changes: 7 additions & 20 deletions libs/libarchfpga/src/interposer_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,20 @@
* @file interposer_types.h
* @brief This file contains types used for parsing interposer-related tags such as <interposer_cut> and <interdie_wire>
* and converting that information into the device architecture-related data structures.
*
*/

#include <unordered_map>
#include <vector>
#include <string>
#include "grid_types.h"

/**
* @brief Enum for direction of an interposer cut. X means horizontal cut and Y means vertical cut.
*
*/
enum class e_interposer_cut_dim {
X,
Y
/// @brief Enum for direction of an interposer cut.
enum class e_interposer_cut_type {
HORZ,
VERT
};

// Lookup table for converting between a character and an e_interposer_cut_dim
inline const std::unordered_map<char, e_interposer_cut_dim> CHAR_INTERPOSER_DIM_MAP = {
{'X', e_interposer_cut_dim::X},
{'x', e_interposer_cut_dim::X},
{'Y', e_interposer_cut_dim::Y},
{'y', e_interposer_cut_dim::Y}};

/**
* @brief Struct containing information of interdire wires i.e. connections between the dies on an interposer
*
*/
struct t_interdie_wire_inf {
std::string sg_name; ///< Name of the scatter-gather pattern to be used for the interdie connection
Expand All @@ -40,18 +27,18 @@ struct t_interdie_wire_inf {
* Contains starting and ending point (both inclusive) of scatter-gather instantiations and the increment/distance between the instantiations.
* offset_definition.repeat_expr is not relevant for interdie wires and is not set to anything or used.
*
* Locations defined by this offset definition define the starting point or the gathering point of the SG pattern. The end or scatter point of the SG pattern is defined by the sg_link.
* Locations defined by this offset definition define the starting point or the gathering point of the SG pattern.
* The end or scatter point of the SG pattern is defined by the sg_link.
*/
t_grid_loc_spec offset_definition;
int num; ///< Number of scatter-gather instantiations per switchblock location
};

/**
* @brief Struct containing information of an interposer cut
*
*/
struct t_interposer_cut_inf {
e_interposer_cut_dim dim; ///< Dimension or axis of interposer cut.
e_interposer_cut_type dim; ///< Axis of interposer cut location. The cut is perpendicular to this axis. This specifies the dimension of `loc`.
int loc; ///< Location of the cut on the grid. Locations start from zero and cuts will happen above or to the right of the tiles at location=loc.
std::vector<t_interdie_wire_inf> interdie_wires; ///< Connectivity specification between the two sides of the cut.
};
2 changes: 1 addition & 1 deletion libs/libarchfpga/src/physical_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ enum e_power_estimation_method_ {
POWER_METHOD_SPECIFY_SIZES, /* Transistor-level, user-specified buffers/wires */
POWER_METHOD_TOGGLE_PINS, /* Dynamic: Energy per pin toggle, Static: Absolute */
POWER_METHOD_C_INTERNAL, /* Dynamic: Equiv. Internal capacitance, Static: Absolute */
POWER_METHOD_ABSOLUTE /* Dynamic: Aboslute, Static: Absolute */
POWER_METHOD_ABSOLUTE /* Dynamic: Absolute, Static: Absolute */
};
typedef enum e_power_estimation_method_ e_power_estimation_method;
typedef enum e_power_estimation_method_ t_power_estimation_method;
Expand Down
3 changes: 2 additions & 1 deletion libs/libarchfpga/src/read_xml_arch_file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2661,7 +2661,8 @@ static void process_block_type_locs(t_grid_def& grid_def,

t_interposer_cut_inf interposer_cut = parse_interposer_cut_tag(loc_spec_tag, loc_data);

if ((interposer_cut.dim == e_interposer_cut_dim::X && interposer_cut.loc >= grid_def.height) || (interposer_cut.dim == e_interposer_cut_dim::Y && interposer_cut.loc >= grid_def.width)) {
if ((interposer_cut.dim == e_interposer_cut_type::VERT && interposer_cut.loc >= grid_def.width)
|| (interposer_cut.dim == e_interposer_cut_type::HORZ && interposer_cut.loc >= grid_def.height)) {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(loc_spec_tag), "Interposer cut dimensions are outside of device bounds");
}

Expand Down
38 changes: 29 additions & 9 deletions libs/libarchfpga/src/read_xml_arch_file_interposer.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "read_xml_arch_file_interposer.h"

#include <vector>

#include "interposer_types.h"
#include "read_xml_util.h"
#include "pugixml_util.hpp"
Expand All @@ -8,24 +10,37 @@
t_interposer_cut_inf parse_interposer_cut_tag(pugi::xml_node interposer_cut_tag, const pugiutil::loc_data& loc_data) {
t_interposer_cut_inf interposer;

pugiutil::expect_only_attributes(interposer_cut_tag, {"dim", "loc"}, loc_data);
pugiutil::expect_only_attributes(interposer_cut_tag, {"x", "y"}, loc_data);

const int x = pugiutil::get_attribute(interposer_cut_tag, "x", loc_data, pugiutil::ReqOpt::OPTIONAL).as_int(ARCH_FPGA_UNDEFINED_VAL);
const int y = pugiutil::get_attribute(interposer_cut_tag, "y", loc_data, pugiutil::ReqOpt::OPTIONAL).as_int(ARCH_FPGA_UNDEFINED_VAL);

std::string interposer_dim = pugiutil::get_attribute(interposer_cut_tag, "dim", loc_data).as_string();
if (interposer_dim.size() != 1 || !CHAR_INTERPOSER_DIM_MAP.contains(interposer_dim[0])) {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(interposer_cut_tag), "Interposer tag dimension must be a single character of either X, x, Y or y.");
// Both x and y are specified
if (x != ARCH_FPGA_UNDEFINED_VAL && y != ARCH_FPGA_UNDEFINED_VAL) {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(interposer_cut_tag),
"Interposer cut tag must specify where the cut is to appear using only one of `x` or `y` attributes.");
}

interposer.dim = CHAR_INTERPOSER_DIM_MAP.at(interposer_dim[0]);
if (x != ARCH_FPGA_UNDEFINED_VAL) {
interposer.loc = x;
interposer.dim = e_interposer_cut_type::VERT;
} else if (y != ARCH_FPGA_UNDEFINED_VAL) {
interposer.loc = y;
interposer.dim = e_interposer_cut_type::HORZ;
} else {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(interposer_cut_tag),
"Interposer cut tag must specify where the cut is to appear using `x` or `y` attributes.");
}

interposer.loc = pugiutil::get_attribute(interposer_cut_tag, "loc", loc_data).as_int();
if (interposer.loc < 0) {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(interposer_cut_tag), "Interposer location must be positive.");
if (interposer.loc <= 0) {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(interposer_cut_tag),
"Interposer cut location must be a positive number.");
}

pugiutil::expect_only_children(interposer_cut_tag, {"interdie_wire"}, loc_data);

for (pugi::xml_node interdie_wire_tag : interposer_cut_tag.children()) {
const std::vector<std::string> interdie_wire_attributes = {{"sg_name", "sg_link", "offset_start", "offset_end", "offset_increment", "num"}};
const std::vector<std::string> interdie_wire_attributes = {"sg_name", "sg_link", "offset_start", "offset_end", "offset_increment", "num"};
pugiutil::expect_only_attributes(interdie_wire_tag, interdie_wire_attributes, loc_data);

t_interdie_wire_inf interdie_wire;
Expand All @@ -39,6 +54,11 @@ t_interposer_cut_inf parse_interposer_cut_tag(pugi::xml_node interposer_cut_tag,

interdie_wire.num = pugiutil::get_attribute(interdie_wire_tag, "num", loc_data).as_int();

if (interdie_wire.num <= 0) {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(interdie_wire_tag),
"The `num` attribute of an `interdie_wire` must be specified with a positive number.");
}

interposer.interdie_wires.push_back(interdie_wire);
}

Expand Down
Loading