[core] adding rr spatial lookup for clock nodes only
This commit is contained in:
parent
db36f87dfa
commit
87a9146082
|
@ -38,6 +38,36 @@ std::vector<ClockLevelId> ClockNetwork::levels(
|
|||
return ret;
|
||||
}
|
||||
|
||||
std::vector<ClockTreePinId> ClockNetwork::pins(const ClockTreeId& tree_id,
|
||||
const ClockLevelId& level,
|
||||
const t_rr_type& track_type,
|
||||
const Direction& direction) const {
|
||||
std::vector<ClockTreePinId> ret;
|
||||
/* Avoid to repeatedly count the tracks which can be shared by spines
|
||||
* For two or more spines that locate in different coordinates, they can share
|
||||
* the same routing tracks. Therefore, we only ensure that routing tracks in
|
||||
* their demanding direction (INC and DEC) are satisfied
|
||||
*/
|
||||
bool dir_flags = false;
|
||||
for (ClockSpineId curr_spine : spines(tree_id)) {
|
||||
if (spine_levels_[curr_spine] != size_t(level)) {
|
||||
continue;
|
||||
}
|
||||
if (spine_track_type(curr_spine) == track_type) {
|
||||
if (!dir_flags && spine_direction(curr_spine) == direction) {
|
||||
ret.reserve(ret.size() + tree_width(spine_parent_trees_[curr_spine]));
|
||||
for (size_t i = 0; i < tree_width(spine_parent_trees_[curr_spine]); ++i) {
|
||||
ret.push_back(ClockTreePinId(i));
|
||||
}
|
||||
dir_flags = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/************************************************************************
|
||||
* Public Accessors : Basic data query
|
||||
***********************************************************************/
|
||||
|
|
|
@ -53,6 +53,10 @@ class ClockNetwork {
|
|||
std::vector<ClockLevelId> levels(const ClockTreeId& tree_id) const;
|
||||
/* Return a list of spine id under a clock tree */
|
||||
std::vector<ClockSpineId> spines(const ClockTreeId& tree_id) const;
|
||||
/* Return a list of clock pins in a bus of clock tree at a given level and direction */
|
||||
std::vector<ClockTreePinId> pins(const ClockTreeId& tree_id, const ClockLevelId& level,
|
||||
const t_rr_type& track_type,
|
||||
const Direction& direction) const;
|
||||
|
||||
public: /* Public Accessors: Basic data query */
|
||||
/* Return the number of routing tracks required by a selected clock tree at a
|
||||
|
|
|
@ -16,11 +16,13 @@ namespace openfpga { // Begin namespace openfpga
|
|||
|
||||
struct clock_level_id_tag;
|
||||
struct clock_tree_id_tag;
|
||||
struct clock_tree_pin_id_tag;
|
||||
struct clock_spine_id_tag;
|
||||
struct clock_switch_point_id_tag;
|
||||
|
||||
typedef vtr::StrongId<clock_level_id_tag> ClockLevelId;
|
||||
typedef vtr::StrongId<clock_tree_id_tag> ClockTreeId;
|
||||
typedef vtr::StrongId<clock_tree_pin_id_tag> ClockTreePinId;
|
||||
typedef vtr::StrongId<clock_spine_id_tag> ClockSpineId;
|
||||
typedef vtr::StrongId<clock_switch_point_id_tag> ClockSwitchPointId;
|
||||
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
#include "vtr_assert.h"
|
||||
#include "vtr_log.h"
|
||||
#include "rr_clock_spatial_lookup.h"
|
||||
|
||||
namespace openfpga { // begin namespace openfpga
|
||||
|
||||
RRClockSpatialLookup::RRClockSpatialLookup() {
|
||||
}
|
||||
|
||||
RRNodeId RRClockSpatialLookup::find_node(int x,
|
||||
int y,
|
||||
const ClockTreeId& tree,
|
||||
const ClockLevelId& lvl,
|
||||
const ClockTreePinId& pin,
|
||||
const Direction& direction) const {
|
||||
size_t dir = size_t(direction);
|
||||
/* Pre-check: the x, y, side and ptc should be non negative numbers! Otherwise, return an invalid id */
|
||||
if ((x < 0) || (y < 0) || (direction != Direction::INC && direction != Direction::DEC)) {
|
||||
return RRNodeId::INVALID();
|
||||
}
|
||||
|
||||
/* Sanity check to ensure the x, y, side and ptc are in range
|
||||
* - Return an valid id by searching in look-up when all the parameters are in range
|
||||
* - Return an invalid id if any out-of-range is detected
|
||||
*/
|
||||
if (size_t(dir) >= rr_node_indices_.size()) {
|
||||
return RRNodeId::INVALID();
|
||||
}
|
||||
|
||||
if (size_t(x) >= rr_node_indices_[dir].dim_size(0)) {
|
||||
return RRNodeId::INVALID();
|
||||
}
|
||||
|
||||
if (size_t(y) >= rr_node_indices_[dir].dim_size(1)) {
|
||||
return RRNodeId::INVALID();
|
||||
}
|
||||
|
||||
auto result_tree = rr_node_indices_[dir][x][y].find(tree);
|
||||
if (result_tree == rr_node_indices_[dir][x][y].end()) {
|
||||
return RRNodeId::INVALID();
|
||||
}
|
||||
|
||||
auto result_lvl = result_tree->second.find(lvl);
|
||||
if (result_lvl == result_tree->second.end()) {
|
||||
return RRNodeId::INVALID();
|
||||
}
|
||||
|
||||
auto result_pin = result_lvl->second.find(pin);
|
||||
if (result_pin == result_lvl->second.end()) {
|
||||
return RRNodeId::INVALID();
|
||||
}
|
||||
|
||||
return result_pin->second;
|
||||
}
|
||||
|
||||
|
||||
void RRClockSpatialLookup::add_node(RRNodeId node,
|
||||
int x,
|
||||
int y,
|
||||
const ClockTreeId& tree,
|
||||
const ClockLevelId& lvl,
|
||||
const ClockTreePinId& pin,
|
||||
const Direction& direction) {
|
||||
size_t dir = size_t(direction);
|
||||
VTR_ASSERT(node); /* Must have a valid node id to be added */
|
||||
VTR_ASSERT_SAFE(2 == rr_node_indices_[dir].ndims());
|
||||
|
||||
resize_nodes(x, y, direction);
|
||||
|
||||
/* Resize on demand finished; Register the node */
|
||||
rr_node_indices_[dir][x][y][tree][lvl][pin] = node;
|
||||
}
|
||||
|
||||
void RRClockSpatialLookup::resize_nodes(int x,
|
||||
int y,
|
||||
const Direction& direction) {
|
||||
/* Expand the fast look-up if the new node is out-of-range
|
||||
* This may seldom happen because the rr_graph building function
|
||||
* should ensure the fast look-up well organized
|
||||
*/
|
||||
size_t dir = size_t(direction);
|
||||
VTR_ASSERT(dir < rr_node_indices_.size());
|
||||
VTR_ASSERT(x >= 0);
|
||||
VTR_ASSERT(y >= 0);
|
||||
|
||||
if ((x >= int(rr_node_indices_[dir].dim_size(0)))
|
||||
|| (y >= int(rr_node_indices_[dir].dim_size(1)))) {
|
||||
rr_node_indices_[dir].resize({std::max(rr_node_indices_[dir].dim_size(0), size_t(x) + 1),
|
||||
std::max(rr_node_indices_[dir].dim_size(1), size_t(y) + 1)});
|
||||
}
|
||||
}
|
||||
|
||||
void RRClockSpatialLookup::clear() {
|
||||
for (auto& data : rr_node_indices_) {
|
||||
data.clear();
|
||||
}
|
||||
}
|
||||
|
||||
} // end namespace openfpga
|
|
@ -0,0 +1,102 @@
|
|||
#ifndef RR_CLOCK_SPATIAL_LOOKUP_H
|
||||
#define RR_CLOCK_SPATIAL_LOOKUP_H
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief This RRClockSpatialLookup class encapsulates
|
||||
* the node-lookup for clock nodes in a routing resource graph
|
||||
*
|
||||
* A data structure built to find the id of an routing resource node
|
||||
* (rr_node) given information about its physical position and type in a clock network
|
||||
* The data structure is mostly needed during building the clock part of a routing resource graph
|
||||
*
|
||||
* The data structure allows users to
|
||||
*
|
||||
* - Update the look-up with new nodes
|
||||
* - Find the id of a node with given information, e.g., x, y, type etc.
|
||||
*/
|
||||
#include "vtr_geometry.h"
|
||||
#include "vtr_vector.h"
|
||||
#include "physical_types.h"
|
||||
#include "rr_node_types.h"
|
||||
#include "rr_graph_fwd.h"
|
||||
#include "clock_network_fwd.h"
|
||||
|
||||
namespace openfpga { // begin namespace openfpga
|
||||
|
||||
class RRClockSpatialLookup {
|
||||
/* -- Constructors -- */
|
||||
public:
|
||||
/* Explicitly define the only way to create an object */
|
||||
explicit RRClockSpatialLookup();
|
||||
|
||||
/* Disable copy constructors and copy assignment operator
|
||||
* This is to avoid accidental copy because it could be an expensive operation considering that the
|
||||
* memory footprint of the data structure could ~ Gb
|
||||
* Using the following syntax, we prohibit accidental 'pass-by-value' which can be immediately caught
|
||||
* by compiler
|
||||
*/
|
||||
RRClockSpatialLookup(const RRClockSpatialLookup&) = delete;
|
||||
void operator=(const RRClockSpatialLookup&) = delete;
|
||||
|
||||
/* -- Accessors -- */
|
||||
public:
|
||||
/**
|
||||
* @brief Returns the index of the specified routing resource node.
|
||||
*
|
||||
* @param (x, y) are the grid location within the FPGA
|
||||
* @param clk_tree specifies the id of the clock tree in a clock network,
|
||||
* @param clk_level specifies the level of the clock node in a clock network (typically multi-level),
|
||||
* @param clk_pin specifies the pin id of the clock node in a bus of clock tree (consider multiple clock in a tree)
|
||||
* @param direction specifies how the clock node will propagate the signal (either in a horizental or a vertical way)
|
||||
*
|
||||
* @note An invalid id will be returned if the node does not exist
|
||||
*/
|
||||
RRNodeId find_node(int x,
|
||||
int y,
|
||||
const ClockTreeId& tree,
|
||||
const ClockLevelId& lvl,
|
||||
const ClockTreePinId& pin,
|
||||
const Direction& direction) const;
|
||||
|
||||
/* -- Mutators -- */
|
||||
public:
|
||||
/**
|
||||
* @brief Register a node in the fast look-up
|
||||
*
|
||||
* @note You must have a valid node id to register the node in the lookup
|
||||
*
|
||||
* @param (x, y) are the grid location within the FPGA
|
||||
* @param clk_tree specifies the id of the clock tree in a clock network,
|
||||
* @param clk_level specifies the level of the clock node in a clock network (typically multi-level),
|
||||
* @param clk_pin specifies the pin id of the clock node in a bus of clock tree (consider multiple clock in a tree)
|
||||
* @param direction specifies how the clock node will propagate the signal (either in a horizental or a vertical way)
|
||||
|
||||
*
|
||||
* @note a node added with this call will not create a node in the rr_graph node list
|
||||
* You MUST add the node in the rr_graph so that the node is valid
|
||||
*/
|
||||
void add_node(RRNodeId node,
|
||||
int x,
|
||||
int y,
|
||||
const ClockTreeId& clk_tree,
|
||||
const ClockLevelId& clk_lvl,
|
||||
const ClockTreePinId& clk_pin,
|
||||
const Direction& direction);
|
||||
|
||||
/** @brief Clear all the data inside */
|
||||
void clear();
|
||||
|
||||
private: /* Private mutators */
|
||||
/** @brief Resize the nodes upon needs */
|
||||
void resize_nodes(int x, int y, const Direction& direction);
|
||||
|
||||
/* -- Internal data storage -- */
|
||||
private:
|
||||
/* Fast look-up: [INC|DEC][0..grid_width][0..grid_height][tree_id][level_id][clock_pin_id] */
|
||||
std::array<vtr::NdMatrix<std::map<ClockTreeId, std::map<ClockLevelId, std::map<ClockTreePinId, RRNodeId>>>, 2>, 2> rr_node_indices_;
|
||||
};
|
||||
|
||||
} // end namespace openfpga
|
||||
|
||||
#endif
|
|
@ -84,6 +84,7 @@ static size_t estimate_clock_rr_graph_num_nodes(const DeviceGrid& grids,
|
|||
* with direction, ptc and coordinates etc.
|
||||
*******************************************************************/
|
||||
static void add_rr_graph_block_clock_nodes(RRGraphBuilder& rr_graph_builder,
|
||||
RRClockSpatialLookup& clk_rr_lookup,
|
||||
const RRGraphView& rr_graph_view,
|
||||
const ClockNetwork& clk_ntwk,
|
||||
const vtr::Point<size_t> chan_coord,
|
||||
|
@ -98,9 +99,7 @@ static void add_rr_graph_block_clock_nodes(RRGraphBuilder& rr_graph_builder,
|
|||
for (auto itree : clk_ntwk.trees()) {
|
||||
for (auto ilvl : clk_ntwk.levels(itree)) {
|
||||
for (auto node_dir : {Direction::INC, Direction::DEC}) {
|
||||
for (size_t itrack = 0;
|
||||
itrack < clk_ntwk.num_tracks(itree, ilvl, chan_type, node_dir);
|
||||
++itrack) {
|
||||
for (auto ipin : clk_ntwk.pins(itree, ilvl, chan_type, node_dir)) {
|
||||
RRNodeId clk_node = rr_graph_builder.create_node(
|
||||
chan_coord.x(), chan_coord.y(), chan_type, curr_node_ptc);
|
||||
rr_graph_builder.set_node_direction(clk_node, node_dir);
|
||||
|
@ -111,8 +110,8 @@ static void add_rr_graph_block_clock_nodes(RRGraphBuilder& rr_graph_builder,
|
|||
size_t(clk_ntwk.default_segment())));
|
||||
/* FIXME: need to set rc_index and cost_index when building the graph
|
||||
* in VTR */
|
||||
/* TODO: register the node to a dedicated lookup for clock nodes only
|
||||
*/
|
||||
/* register the node to a dedicated lookup */
|
||||
clk_rr_lookup.add_node(clk_node, chan_coord.x(), chan_coord.y(), itree, ilvl, ipin, node_dir);
|
||||
/* Update ptc count and go to next */
|
||||
curr_node_ptc++;
|
||||
}
|
||||
|
@ -123,11 +122,10 @@ static void add_rr_graph_block_clock_nodes(RRGraphBuilder& rr_graph_builder,
|
|||
|
||||
/********************************************************************
|
||||
* Add clock nodes one by one to the routing resource graph.
|
||||
* Assign node-level attributes properly
|
||||
* TODO: consider to have a fast lookup for clock nodes. For example,
|
||||
*find_clock_node(tree_id, level_id, clock_id)
|
||||
* Assign node-level attributes properly and register in dedicated lookup
|
||||
*******************************************************************/
|
||||
static void add_rr_graph_clock_nodes(RRGraphBuilder& rr_graph_builder,
|
||||
RRClockSpatialLookup& clk_rr_lookup,
|
||||
const RRGraphView& rr_graph_view,
|
||||
const DeviceGrid& grids,
|
||||
const bool& through_channel,
|
||||
|
@ -142,7 +140,7 @@ static void add_rr_graph_clock_nodes(RRGraphBuilder& rr_graph_builder,
|
|||
(false == is_chanx_exist(grids, chanx_coord))) {
|
||||
continue;
|
||||
}
|
||||
add_rr_graph_block_clock_nodes(rr_graph_builder, rr_graph_view, clk_ntwk,
|
||||
add_rr_graph_block_clock_nodes(rr_graph_builder, clk_rr_lookup, rr_graph_view, clk_ntwk,
|
||||
chanx_coord, CHANX,
|
||||
CHANX_COST_INDEX_START);
|
||||
}
|
||||
|
@ -159,7 +157,7 @@ static void add_rr_graph_clock_nodes(RRGraphBuilder& rr_graph_builder,
|
|||
continue;
|
||||
}
|
||||
add_rr_graph_block_clock_nodes(
|
||||
rr_graph_builder, rr_graph_view, clk_ntwk, chany_coord, CHANY,
|
||||
rr_graph_builder, clk_rr_lookup, rr_graph_view, clk_ntwk, chany_coord, CHANY,
|
||||
CHANX_COST_INDEX_START + rr_graph_view.num_rr_segments());
|
||||
}
|
||||
}
|
||||
|
@ -168,7 +166,9 @@ static void add_rr_graph_clock_nodes(RRGraphBuilder& rr_graph_builder,
|
|||
/********************************************************************
|
||||
* Add edges for the clock nodes in a given connection block
|
||||
*******************************************************************/
|
||||
static
|
||||
void add_rr_graph_block_clock_edges(RRGraphBuilder& rr_graph_builder,
|
||||
const RRClockSpatialLookup& clk_rr_lookup,
|
||||
const RRGraphView& rr_graph_view,
|
||||
const ClockNetwork& clk_ntwk,
|
||||
const vtr::Point<size_t> chan_coord,
|
||||
|
@ -176,10 +176,10 @@ void add_rr_graph_block_clock_edges(RRGraphBuilder& rr_graph_builder,
|
|||
for (auto itree : clk_ntwk.trees()) {
|
||||
for (auto ilvl : clk_ntwk.levels(itree)) {
|
||||
for (auto node_dir : {Direction::INC, Direction::DEC}) {
|
||||
for (size_t itrack = 0;
|
||||
itrack < clk_ntwk.num_tracks(itree, ilvl, chan_type, node_dir);
|
||||
++itrack) {
|
||||
/* TODO: find the driver clock node through lookup */
|
||||
for (auto ipin : clk_ntwk.pins(itree, ilvl, chan_type, node_dir)) {
|
||||
/* find the driver clock node through lookup */
|
||||
RRNodeId driver_node = clk_rr_lookup.find_node(chan_coord.x(), chan_coord.y(), itree, ilvl, ipin, node_dir);
|
||||
VTR_ASSERT(driver_node);
|
||||
/* TODO: find the fan-out clock node through lookup */
|
||||
/* TODO: Create edges */
|
||||
}
|
||||
|
@ -208,7 +208,9 @@ void add_rr_graph_block_clock_edges(RRGraphBuilder& rr_graph_builder,
|
|||
* v
|
||||
* clk0_lvl1_chany[1][1]
|
||||
*******************************************************************/
|
||||
static
|
||||
void add_rr_graph_clock_edges(RRGraphBuilder& rr_graph_builder,
|
||||
const RRClockSpatialLookup& clk_rr_lookup,
|
||||
const RRGraphView& rr_graph_view,
|
||||
const DeviceGrid& grids,
|
||||
const bool& through_channel,
|
||||
|
@ -223,7 +225,7 @@ void add_rr_graph_clock_edges(RRGraphBuilder& rr_graph_builder,
|
|||
(false == is_chanx_exist(grids, chanx_coord))) {
|
||||
continue;
|
||||
}
|
||||
add_rr_graph_block_clock_edges(rr_graph_builder, rr_graph_view, clk_ntwk,
|
||||
add_rr_graph_block_clock_edges(rr_graph_builder, clk_rr_lookup, rr_graph_view, clk_ntwk,
|
||||
chanx_coord, CHANX);
|
||||
}
|
||||
}
|
||||
|
@ -238,7 +240,7 @@ void add_rr_graph_clock_edges(RRGraphBuilder& rr_graph_builder,
|
|||
(false == is_chany_exist(grids, chany_coord))) {
|
||||
continue;
|
||||
}
|
||||
add_rr_graph_block_clock_edges(rr_graph_builder, rr_graph_view, clk_ntwk,
|
||||
add_rr_graph_block_clock_edges(rr_graph_builder, clk_rr_lookup, rr_graph_view, clk_ntwk,
|
||||
chany_coord, CHANY);
|
||||
}
|
||||
}
|
||||
|
@ -253,7 +255,9 @@ void add_rr_graph_clock_edges(RRGraphBuilder& rr_graph_builder,
|
|||
* - Sanity checks
|
||||
*******************************************************************/
|
||||
int append_clock_rr_graph(DeviceContext& vpr_device_ctx,
|
||||
const ClockNetwork& clk_ntwk, const bool& verbose) {
|
||||
RRClockSpatialLookup& clk_rr_lookup,
|
||||
const ClockNetwork& clk_ntwk,
|
||||
const bool& verbose) {
|
||||
vtr::ScopedStartFinishTimer timer(
|
||||
"Appending programmable clock network to routing resource graph");
|
||||
|
||||
|
@ -282,6 +286,7 @@ int append_clock_rr_graph(DeviceContext& vpr_device_ctx,
|
|||
|
||||
/* Add clock nodes */
|
||||
add_rr_graph_clock_nodes(vpr_device_ctx.rr_graph_builder,
|
||||
clk_rr_lookup,
|
||||
vpr_device_ctx.rr_graph, vpr_device_ctx.grid,
|
||||
vpr_device_ctx.arch->through_channel, clk_ntwk);
|
||||
VTR_ASSERT(num_clock_nodes + orig_num_nodes ==
|
||||
|
@ -290,6 +295,7 @@ int append_clock_rr_graph(DeviceContext& vpr_device_ctx,
|
|||
/* TODO: Add edges between clock nodes*/
|
||||
size_t num_clock_edges = 0;
|
||||
add_rr_graph_clock_edges(vpr_device_ctx.rr_graph_builder,
|
||||
static_cast<const RRClockSpatialLookup&>(clk_rr_lookup),
|
||||
vpr_device_ctx.rr_graph, vpr_device_ctx.grid,
|
||||
vpr_device_ctx.arch->through_channel, clk_ntwk);
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* Include header files that are required by function declaration
|
||||
*******************************************************************/
|
||||
#include "clock_network.h"
|
||||
#include "rr_clock_spatial_lookup.h"
|
||||
#include "vpr_context.h"
|
||||
|
||||
/********************************************************************
|
||||
|
@ -15,7 +16,9 @@
|
|||
namespace openfpga {
|
||||
|
||||
int append_clock_rr_graph(DeviceContext& vpr_device_ctx,
|
||||
const ClockNetwork& clk_ntwk, const bool& verbose);
|
||||
RRClockSpatialLookup& clk_rr_lookup,
|
||||
const ClockNetwork& clk_ntwk,
|
||||
const bool& verbose);
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "bitstream_manager.h"
|
||||
#include "bitstream_setting.h"
|
||||
#include "clock_network.h"
|
||||
#include "rr_clock_spatial_lookup.h"
|
||||
#include "decoder_library.h"
|
||||
#include "device_rr_gsb.h"
|
||||
#include "fabric_bitstream.h"
|
||||
|
@ -63,6 +64,7 @@ class OpenfpgaContext : public Context {
|
|||
return bitstream_setting_;
|
||||
}
|
||||
const openfpga::ClockNetwork& clock_arch() const { return clock_arch_; }
|
||||
const openfpga::RRClockSpatialLookup& clock_rr_lookup() const { return clock_rr_lookup_; }
|
||||
const openfpga::VprDeviceAnnotation& vpr_device_annotation() const {
|
||||
return vpr_device_annotation_;
|
||||
}
|
||||
|
@ -119,6 +121,7 @@ class OpenfpgaContext : public Context {
|
|||
return bitstream_setting_;
|
||||
}
|
||||
openfpga::ClockNetwork& mutable_clock_arch() { return clock_arch_; }
|
||||
openfpga::RRClockSpatialLookup& mutable_clock_rr_lookup() { return clock_rr_lookup_; }
|
||||
openfpga::VprDeviceAnnotation& mutable_vpr_device_annotation() {
|
||||
return vpr_device_annotation_;
|
||||
}
|
||||
|
@ -169,6 +172,7 @@ class OpenfpgaContext : public Context {
|
|||
openfpga::SimulationSetting sim_setting_;
|
||||
openfpga::BitstreamSetting bitstream_setting_;
|
||||
openfpga::ClockNetwork clock_arch_;
|
||||
openfpga::RRClockSpatialLookup clock_rr_lookup_;
|
||||
|
||||
/* Annotation to pb_type of VPR */
|
||||
openfpga::VprDeviceAnnotation vpr_device_annotation_;
|
||||
|
|
|
@ -199,6 +199,7 @@ int append_clock_rr_graph_template(T& openfpga_ctx, const Command& cmd,
|
|||
CommandOptionId opt_verbose = cmd.option("verbose");
|
||||
|
||||
return append_clock_rr_graph(g_vpr_ctx.mutable_device(),
|
||||
openfpga_ctx.mutable_clock_rr_lookup(),
|
||||
openfpga_ctx.clock_arch(),
|
||||
cmd_context.option_enable(cmd, opt_verbose));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue