From e7fc065032d711383bc45d1011d840ea49bd4696 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 21 Feb 2023 15:06:35 -0800 Subject: [PATCH 001/166] [lib] start developing clock arch data structure and I/O --- libs/libclkarchopenfpga/CMakeLists.txt | 36 ++++++++++++++++++++++++ libs/libclkarchopenfpga/arch/example.xml | 19 +++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 libs/libclkarchopenfpga/CMakeLists.txt create mode 100644 libs/libclkarchopenfpga/arch/example.xml diff --git a/libs/libclkarchopenfpga/CMakeLists.txt b/libs/libclkarchopenfpga/CMakeLists.txt new file mode 100644 index 000000000..6db47eff5 --- /dev/null +++ b/libs/libclkarchopenfpga/CMakeLists.txt @@ -0,0 +1,36 @@ +cmake_minimum_required(VERSION 3.9) + +project("libclkarchopenfpga") + +file(GLOB_RECURSE EXEC_SOURCES test/*.cpp) +file(GLOB_RECURSE LIB_SOURCES src/*.cpp) +file(GLOB_RECURSE LIB_HEADERS src/*.h) +files_to_dirs(LIB_HEADERS LIB_INCLUDE_DIRS) + +#Remove test executable from library +list(REMOVE_ITEM LIB_SOURCES ${EXEC_SOURCES}) + +#Create the library +add_library(libclkarchopenfpga STATIC + ${LIB_HEADERS} + ${LIB_SOURCES}) +target_include_directories(libclkarchopenfpga PUBLIC ${LIB_INCLUDE_DIRS}) +set_target_properties(libclkarchopenfpga PROPERTIES PREFIX "") #Avoid extra 'lib' prefix + +#Specify link-time dependancies +target_link_libraries(libclkarchopenfpga + libopenfpgautil + libvtrutil + libarchfpga + libpugiutil) + +#Create the test executable +foreach(testsourcefile ${EXEC_SOURCES}) + # Use a simple string replace, to cut off .cpp. + get_filename_component(testname ${testsourcefile} NAME_WE) + add_executable(${testname} ${testsourcefile}) + # Make sure the library is linked to each test executable + target_link_libraries(${testname} libclkarchopenfpga) +endforeach(testsourcefile ${EXEC_SOURCES}) + +install(TARGETS libclkarchopenfpga DESTINATION bin) diff --git a/libs/libclkarchopenfpga/arch/example.xml b/libs/libclkarchopenfpga/arch/example.xml new file mode 100644 index 000000000..452e6942b --- /dev/null +++ b/libs/libclkarchopenfpga/arch/example.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + From fe594acab1183c0cdf45a4d35f3993169552581a Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 21 Feb 2023 16:53:05 -0800 Subject: [PATCH 002/166] [lib] adding clock network data structure --- .../src/base/clock_network.h | 108 ++++++++++++++++++ .../src/base/clock_network_fwd.h | 28 +++++ 2 files changed, 136 insertions(+) create mode 100644 libs/libclkarchopenfpga/src/base/clock_network.h create mode 100644 libs/libclkarchopenfpga/src/base/clock_network_fwd.h diff --git a/libs/libclkarchopenfpga/src/base/clock_network.h b/libs/libclkarchopenfpga/src/base/clock_network.h new file mode 100644 index 000000000..4ff964182 --- /dev/null +++ b/libs/libclkarchopenfpga/src/base/clock_network.h @@ -0,0 +1,108 @@ +#ifndef CLOCK_NETWORK_H +#define CLOCK_NETWORK_H + +/******************************************************************** + * This file include the declaration of pin constraints + *******************************************************************/ +#include +#include +#include + +/* Headers from vtrutil library */ +#include "vtr_vector.h" + +/* Headers from openfpgautil library */ +#include "clock_network_fwd.h" +#include "openfpga_port.h" + +namespace openfpga { // Begin namespace openfpga + +/******************************************************************** + * A data structure to describe a clock network + * A clock network consists of a number of clock trees + * each of which has: + * - a unique id + * - different entry point + * + * Typical usage: + * -------------- + * // Create an object of clock network + * ClockNetwork clk_ntwk; + * // Create a new clock tree which contains 8 clock pins + * ClockTreeId clk_tree_id = clk_ntwk.create_tree("tree1") + * // Add a spine to the clock tree + * ClockSpineId clk_spine_id = clk_ntwk.create_spine("tree1_spine0"); + * + *******************************************************************/ +class ClockNetwork { + public: /* Types */ + typedef vtr::vector::const_iterator + clock_tree_iterator; + /* Create range */ + typedef vtr::Range clock_tree_range; + + public: /* Constructors */ + ClockNetwork(); + + public: /* Accessors: aggregates */ + clock_tree_range trees() const; + + public: /* Public Accessors: Basic data query */ + /* Find a spine by name, return a valid id if found, otherwise return an invalid id */ + ClockSpineId spine(const std::string& name) const; + + /* Check if there are clock tree */ + bool empty() const; + + public: /* Public Mutators */ + /* Reserve a number of spines to be memory efficent */ + void reserve_spines(const size_t& num_spines); + + /* Reserve a number of trees to be memory efficent */ + void reserve_trees(const size_t& num_trees); + + /* Create a new tree, by default the tree can accomodate only 1 clock signal; use width to adjust the size */ + ClockTreeId create_tree(const std::string& name, const size_t& width = 1); + + /* Create a new spine, if the spine is already created, return an invalid id */ + ClockSpineId create_spine(const std::string& name); + + /* Set the parent tree for a given spine. It is illegal that a spine which does not belong to any tree */ + void set_spine_parent_tree(const ClockSpineId& spine, const ClockTreeId& parent_tree); + void set_spine_start_point(const ClockSpineId& spine, const vtr::Point& point); + void set_spine_end_point(const ClockSpineId& spine, const vtr::Point& point); + void add_spine_switch_point(const ClockSpineId& spine, const ClockSpineId& drive_spine, const vtr::Point& coord); + + public: /* Public invalidators/validators */ + /* Show if the tree id is a valid for data queries */ + bool valid_tree_id(const ClockTreeId& tree_id) const; + + /* Show if the tree id is a valid for data queries */ + bool valid_spine_id(const ClockSpineId& spine_id) const; + + private: /* Internal data */ + /* Basic information of each tree */ + vtr::vector clk_tree_ids_; + vtr::vector clk_tree_names_; + vtr::vector> clk_tree_top_spines_; + + /* Basic information of each spine */ + vtr::vector clk_spines_; + vtr::vector clk_spine_names_; + vtr::vector clk_spine_levels_; + vtr::vector> clk_spine_start_points_; + vtr::vector> clk_spine_end_points_; + vtr::vector> clk_spine_switch_points_; + vtr::vector>> clk_spine_switch_coords_; + vtr::vector clk_spine_parent_; + vtr::vector clk_spine_parent_tree_; + + /* Fast lookup */ + std::map spine_name2ids_; + + /* Flags */ + bool is_dirty_; +}; + +} // End of namespace openfpga +#endif diff --git a/libs/libclkarchopenfpga/src/base/clock_network_fwd.h b/libs/libclkarchopenfpga/src/base/clock_network_fwd.h new file mode 100644 index 000000000..d936bbb9c --- /dev/null +++ b/libs/libclkarchopenfpga/src/base/clock_network_fwd.h @@ -0,0 +1,28 @@ +/************************************************************************ + * A header file for ClockNetwork class, including critical data declaration + * Please include this file only for using any PinConstraints data structure + * Refer to clock_network.h for more details + ***********************************************************************/ + +/************************************************************************ + * Create strong id for ClockNetwork to avoid illegal type casting + ***********************************************************************/ +#ifndef CLOCK_NETWORK_FWD_H +#define CLOCK_NETWORK_FWD_H + +#include "vtr_strong_id.h" + +namespace openfpga { // Begin namespace openfpga + +struct clock_tree_id_tag; +struct clock_spine_id_tag; + +typedef vtr::StrongId ClockTreeId; +typedef vtr::StrongId ClockSpineId; + +/* Short declaration of class */ +class ClockNetwork; + +} // End of namespace openfpga + +#endif From 9eb2374bc669c3ff3c4221dbb8f1b2b93c1fdcab Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 21 Feb 2023 22:29:25 -0800 Subject: [PATCH 003/166] [lib] developing --- .../src/base/clock_network.cpp | 195 ++++++++++++++++++ .../src/base/clock_network.h | 33 +-- 2 files changed, 212 insertions(+), 16 deletions(-) create mode 100644 libs/libclkarchopenfpga/src/base/clock_network.cpp diff --git a/libs/libclkarchopenfpga/src/base/clock_network.cpp b/libs/libclkarchopenfpga/src/base/clock_network.cpp new file mode 100644 index 000000000..a5d6dfd05 --- /dev/null +++ b/libs/libclkarchopenfpga/src/base/clock_network.cpp @@ -0,0 +1,195 @@ +#include "clock_network.h" + +#include + +#include "vtr_assert.h" +#include "vtr_log.h" + +namespace openfpga { // Begin namespace openfpga + +/************************************************************************ + * Member functions for class ClockNetwork + ***********************************************************************/ + +/************************************************************************ + * Constructors + ***********************************************************************/ +ClockNetwork::ClockNetwork() { return; } + +/************************************************************************ + * Public Accessors : aggregates + ***********************************************************************/ +ClockNetwork::bus_group_range ClockNetwork::buses() const { + return vtr::make_range(bus_ids_.begin(), bus_ids_.end()); +} + +/************************************************************************ + * Public Accessors : Basic data query + ***********************************************************************/ +openfpga::BasicPort ClockNetwork::bus_port(const ClockNetworkId& bus_id) const { + VTR_ASSERT(valid_bus_id(bus_id)); + return bus_ports_[bus_id]; +} + +bool ClockNetwork::is_big_endian(const ClockNetworkId& bus_id) const { + VTR_ASSERT(valid_bus_id(bus_id)); + return bus_big_endians_[bus_id]; +} + +std::vector ClockNetwork::bus_pins(const ClockNetworkId& bus_id) const { + VTR_ASSERT(valid_bus_id(bus_id)); + return bus_pin_ids_[bus_id]; +} + +int ClockNetwork::pin_index(const BusPinId& pin_id) const { + VTR_ASSERT(valid_pin_id(pin_id)); + return pin_indices_[pin_id]; +} + +std::string ClockNetwork::pin_name(const BusPinId& pin_id) const { + VTR_ASSERT(valid_pin_id(pin_id)); + return pin_names_[pin_id]; +} + +ClockNetworkId ClockNetwork::find_pin_bus(const std::string& pin_name) const { + std::map::const_iterator result = + pin_name2id_map_.find(pin_name); + if (result == pin_name2id_map_.end()) { + /* Not found, return an invalid id */ + return ClockNetworkId::INVALID(); + } + /* Found, we should get the parent bus */ + BusPinId pin_id = result->second; + return pin_parent_bus_ids_[pin_id]; +} + +ClockNetworkId ClockNetwork::find_bus(const std::string& bus_name) const { + std::map::const_iterator result = + bus_name2id_map_.find(bus_name); + if (result == bus_name2id_map_.end()) { + /* Not found, return an invalid id */ + return ClockNetworkId::INVALID(); + } + /* Found, we should get the parent bus */ + return result->second; +} + +BusPinId ClockNetwork::find_pin(const std::string& pin_name) const { + std::map::const_iterator result = + pin_name2id_map_.find(pin_name); + if (result == pin_name2id_map_.end()) { + /* Not found, return an invalid id */ + return BusPinId::INVALID(); + } + /* Found, we should get the parent bus */ + return result->second; +} + +bool ClockNetwork::empty() const { return 0 == bus_ids_.size(); } + +/************************************************************************ + * Public Mutators + ***********************************************************************/ +void ClockNetwork::reserve_buses(const size_t& num_buses) { + bus_ids_.reserve(num_buses); + bus_ports_.reserve(num_buses); + bus_big_endians_.reserve(num_buses); + bus_pin_ids_.reserve(num_buses); +} + +void ClockNetwork::reserve_pins(const size_t& num_pins) { + pin_ids_.reserve(num_pins); + pin_indices_.reserve(num_pins); + pin_names_.reserve(num_pins); + pin_parent_bus_ids_.reserve(num_pins); +} + +ClockNetworkId ClockNetwork::create_bus(const openfpga::BasicPort& bus_port) { + /* Create a new id */ + ClockNetworkId bus_id = ClockNetworkId(bus_ids_.size()); + + bus_ids_.push_back(bus_id); + bus_ports_.push_back(bus_port); + bus_big_endians_.push_back(true); + bus_pin_ids_.emplace_back(); + + /* Register to fast look-up */ + auto result = bus_name2id_map_.find(bus_port.get_name()); + if (result == bus_name2id_map_.end()) { + bus_name2id_map_[bus_port.get_name()] = bus_id; + } else { + VTR_LOG_ERROR("Duplicated bus name '%s' in bus group", + bus_port.get_name().c_str()); + exit(1); + } + + return bus_id; +} + +void ClockNetwork::set_bus_big_endian(const ClockNetworkId& bus_id, + const bool& big_endian) { + VTR_ASSERT(valid_bus_id(bus_id)); + bus_big_endians_[bus_id] = big_endian; +} + +ClockSpineId ClockNetwork::create_spine(const std::string& name) { + /* Check if the name is already used or not */ + auto result = spine_name2ids_.find(name); + if (result != spine_name2ids_.end()) { + return ClockSpineId::INVALID(); + } + + /* Create a new id */ + ClockSpineId spine_id = ClockSpineId(spine_ids_.size()); + VTR_ASSERT(valid_spine_id(spine_id)); + + spine_ids_.push_back(spine_id); + spine_names_.push_back(name); + spine_levels_.emplace_back(); + spine_start_points_.emplace_back(); + spine_end_points_.emplace_back(); + spine_switch_points_.emplace_back(); + spine_switch_coords_.emplace_back(); + spine_parent_.emplace_back(); + spine_parent_tree_.emplace_back(); + + /* Register to the lookup */ + spine_name2ids_[name] = spine_id; + + return spine_id; +} + +void ClockNetwork::set_spine_parent_tree(const ClockSpineId& spine_id, const ClockTreeId& tree_id) { + VTR_ASSERT(valid_spine_id(spine_id)); + VTR_ASSERT(valid_tree_id(tree_id)); + spine_parent_tree_[spine_id] = tree_id; +} + +void ClockNetwork::set_spine_start_point(const ClockSpineId& spine_id, const vtr::Point& coord) { + VTR_ASSERT(valid_spine_id(spine_id)); + spine_start_points_[spine_id] = coord; +} + +void ClockNetwork::set_spine_end_point(const ClockSpineId& spine_id, const vtr::Point& coord) { + VTR_ASSERT(valid_spine_id(spine_id)); + spine_end_points_[spine_id] = coord; +} + +void ClockNetwork::add_spine_switch_point(const ClockSpineId& spine_id, const ClockSpineId& drive_spine, const vtr::Point& coord) { + VTR_ASSERT(valid_spine_id(spine_id)); + spine_switch_points_[spine_id].push_back(drive_spine); + spine_switch_coords_[spine_id].push_back(coord); +} + +/************************************************************************ + * Internal invalidators/validators + ***********************************************************************/ +bool ClockNetwork::valid_tree_id(const ClockTreeId& tree_id) const { + return (size_t(tree_id) < tree_ids_.size()) && (tree_id == tree_ids_[tree_id]); +} + +bool ClockNetwork::valid_spine_id(const ClockSpineId& spine_id) const { + return (size_t(spine_id) < spine_ids_.size()) && (spine_id == spine_ids_[spine_id]); +} + +} // End of namespace openfpga diff --git a/libs/libclkarchopenfpga/src/base/clock_network.h b/libs/libclkarchopenfpga/src/base/clock_network.h index 4ff964182..cc2811216 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.h +++ b/libs/libclkarchopenfpga/src/base/clock_network.h @@ -10,6 +10,7 @@ /* Headers from vtrutil library */ #include "vtr_vector.h" +#include "vtr_geometry.h" /* Headers from openfpgautil library */ #include "clock_network_fwd.h" @@ -68,10 +69,10 @@ class ClockNetwork { ClockSpineId create_spine(const std::string& name); /* Set the parent tree for a given spine. It is illegal that a spine which does not belong to any tree */ - void set_spine_parent_tree(const ClockSpineId& spine, const ClockTreeId& parent_tree); - void set_spine_start_point(const ClockSpineId& spine, const vtr::Point& point); - void set_spine_end_point(const ClockSpineId& spine, const vtr::Point& point); - void add_spine_switch_point(const ClockSpineId& spine, const ClockSpineId& drive_spine, const vtr::Point& coord); + void set_spine_parent_tree(const ClockSpineId& spine_id, const ClockTreeId& tree_id); + void set_spine_start_point(const ClockSpineId& spine_id, const vtr::Point& coord); + void set_spine_end_point(const ClockSpineId& spine_id, const vtr::Point& coord); + void add_spine_switch_point(const ClockSpineId& spine_id, const ClockSpineId& drive_spine, const vtr::Point& coord); public: /* Public invalidators/validators */ /* Show if the tree id is a valid for data queries */ @@ -82,20 +83,20 @@ class ClockNetwork { private: /* Internal data */ /* Basic information of each tree */ - vtr::vector clk_tree_ids_; - vtr::vector clk_tree_names_; - vtr::vector> clk_tree_top_spines_; + vtr::vector tree_ids_; + vtr::vector tree_names_; + vtr::vector> tree_top_spines_; /* Basic information of each spine */ - vtr::vector clk_spines_; - vtr::vector clk_spine_names_; - vtr::vector clk_spine_levels_; - vtr::vector> clk_spine_start_points_; - vtr::vector> clk_spine_end_points_; - vtr::vector> clk_spine_switch_points_; - vtr::vector>> clk_spine_switch_coords_; - vtr::vector clk_spine_parent_; - vtr::vector clk_spine_parent_tree_; + vtr::vector spine_ids_; + vtr::vector spine_names_; + vtr::vector spine_levels_; + vtr::vector> spine_start_points_; + vtr::vector> spine_end_points_; + vtr::vector> spine_switch_points_; + vtr::vector>> spine_switch_coords_; + vtr::vector spine_parent_; + vtr::vector spine_parent_tree_; /* Fast lookup */ std::map spine_name2ids_; From 25e43b47daf712a4bc2bdbc86847873c91cc9cfe Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 22 Feb 2023 12:18:44 -0800 Subject: [PATCH 004/166] [lib] first round of data structure on clock arch --- .../src/base/clock_network.cpp | 132 +++++------------- .../src/base/clock_network.h | 7 +- 2 files changed, 41 insertions(+), 98 deletions(-) diff --git a/libs/libclkarchopenfpga/src/base/clock_network.cpp b/libs/libclkarchopenfpga/src/base/clock_network.cpp index a5d6dfd05..3e1b6eeaf 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.cpp +++ b/libs/libclkarchopenfpga/src/base/clock_network.cpp @@ -14,128 +14,72 @@ namespace openfpga { // Begin namespace openfpga /************************************************************************ * Constructors ***********************************************************************/ -ClockNetwork::ClockNetwork() { return; } +ClockNetwork::ClockNetwork() { + is_dirty_ = true; +} /************************************************************************ * Public Accessors : aggregates ***********************************************************************/ -ClockNetwork::bus_group_range ClockNetwork::buses() const { - return vtr::make_range(bus_ids_.begin(), bus_ids_.end()); +ClockNetwork::clock_tree_range ClockNetwork::trees() const { + return vtr::make_range(tree_ids_.begin(), tree_ids_.end()); } /************************************************************************ * Public Accessors : Basic data query ***********************************************************************/ -openfpga::BasicPort ClockNetwork::bus_port(const ClockNetworkId& bus_id) const { - VTR_ASSERT(valid_bus_id(bus_id)); - return bus_ports_[bus_id]; -} - -bool ClockNetwork::is_big_endian(const ClockNetworkId& bus_id) const { - VTR_ASSERT(valid_bus_id(bus_id)); - return bus_big_endians_[bus_id]; -} - -std::vector ClockNetwork::bus_pins(const ClockNetworkId& bus_id) const { - VTR_ASSERT(valid_bus_id(bus_id)); - return bus_pin_ids_[bus_id]; -} - -int ClockNetwork::pin_index(const BusPinId& pin_id) const { - VTR_ASSERT(valid_pin_id(pin_id)); - return pin_indices_[pin_id]; -} - -std::string ClockNetwork::pin_name(const BusPinId& pin_id) const { - VTR_ASSERT(valid_pin_id(pin_id)); - return pin_names_[pin_id]; -} - -ClockNetworkId ClockNetwork::find_pin_bus(const std::string& pin_name) const { - std::map::const_iterator result = - pin_name2id_map_.find(pin_name); - if (result == pin_name2id_map_.end()) { - /* Not found, return an invalid id */ - return ClockNetworkId::INVALID(); - } - /* Found, we should get the parent bus */ - BusPinId pin_id = result->second; - return pin_parent_bus_ids_[pin_id]; -} - -ClockNetworkId ClockNetwork::find_bus(const std::string& bus_name) const { - std::map::const_iterator result = - bus_name2id_map_.find(bus_name); - if (result == bus_name2id_map_.end()) { - /* Not found, return an invalid id */ - return ClockNetworkId::INVALID(); - } - /* Found, we should get the parent bus */ - return result->second; -} - -BusPinId ClockNetwork::find_pin(const std::string& pin_name) const { - std::map::const_iterator result = - pin_name2id_map_.find(pin_name); - if (result == pin_name2id_map_.end()) { - /* Not found, return an invalid id */ - return BusPinId::INVALID(); - } - /* Found, we should get the parent bus */ - return result->second; -} - -bool ClockNetwork::empty() const { return 0 == bus_ids_.size(); } +bool ClockNetwork::empty() const { return 0 == tree_ids_.size(); } /************************************************************************ * Public Mutators ***********************************************************************/ -void ClockNetwork::reserve_buses(const size_t& num_buses) { - bus_ids_.reserve(num_buses); - bus_ports_.reserve(num_buses); - bus_big_endians_.reserve(num_buses); - bus_pin_ids_.reserve(num_buses); +void ClockNetwork::reserve_spines(const size_t& num_spines) { + spine_ids_.reserve(num_spines); + spine_names_.reserve(num_spines); + spine_levels_.reserve(num_spines); + spine_start_points_.reserve(num_spines); + spine_end_points_.reserve(num_spines); + spine_switch_points_.reserve(num_spines); + spine_switch_coords_.reserve(num_spines); + spine_parent_.reserve(num_spines); + spine_parent_tree_.reserve(num_spines); } -void ClockNetwork::reserve_pins(const size_t& num_pins) { - pin_ids_.reserve(num_pins); - pin_indices_.reserve(num_pins); - pin_names_.reserve(num_pins); - pin_parent_bus_ids_.reserve(num_pins); +void ClockNetwork::reserve_trees(const size_t& num_trees) { + tree_ids_.reserve(num_trees); + tree_names_.reserve(num_trees); + tree_widths_.reserve(num_trees); + tree_top_spines_.reserve(num_trees); } -ClockNetworkId ClockNetwork::create_bus(const openfpga::BasicPort& bus_port) { +ClockTreeId ClockNetwork::create_tree(const std::string& name, const size_t& width = 1) { /* Create a new id */ - ClockNetworkId bus_id = ClockNetworkId(bus_ids_.size()); + ClockTreeId tree_id = ClockTreeId(tree_ids_.size()); - bus_ids_.push_back(bus_id); - bus_ports_.push_back(bus_port); - bus_big_endians_.push_back(true); - bus_pin_ids_.emplace_back(); + tree_ids_.push_back(tree_id); + tree_names_.push_back(name); + tree_widths_.push_back(width); + tree_top_spines_.emplace_back(); /* Register to fast look-up */ - auto result = bus_name2id_map_.find(bus_port.get_name()); - if (result == bus_name2id_map_.end()) { - bus_name2id_map_[bus_port.get_name()] = bus_id; + auto result = tree_name2id_map_.find(name); + if (result == tree_name2id_map_.end()) { + tree_name2id_map_[name] = tree_id; } else { - VTR_LOG_ERROR("Duplicated bus name '%s' in bus group", - bus_port.get_name().c_str()); + VTR_LOG_ERROR("Duplicated clock tree name '%s' in clock network\n", + name.c_str()); exit(1); } - return bus_id; -} - -void ClockNetwork::set_bus_big_endian(const ClockNetworkId& bus_id, - const bool& big_endian) { - VTR_ASSERT(valid_bus_id(bus_id)); - bus_big_endians_[bus_id] = big_endian; + return tree_id; } ClockSpineId ClockNetwork::create_spine(const std::string& name) { /* Check if the name is already used or not */ - auto result = spine_name2ids_.find(name); - if (result != spine_name2ids_.end()) { + auto result = spine_name2id_map_.find(name); + if (result != spine_name2id_map_.end()) { + VTR_LOG_WARN("Unable to create a spine with duplicated name '%s' in clock network\nPlease use the existing spine or rename\n", + name.c_str()); return ClockSpineId::INVALID(); } @@ -154,7 +98,7 @@ ClockSpineId ClockNetwork::create_spine(const std::string& name) { spine_parent_tree_.emplace_back(); /* Register to the lookup */ - spine_name2ids_[name] = spine_id; + spine_name2id_map_[name] = spine_id; return spine_id; } diff --git a/libs/libclkarchopenfpga/src/base/clock_network.h b/libs/libclkarchopenfpga/src/base/clock_network.h index cc2811216..30c2d6bde 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.h +++ b/libs/libclkarchopenfpga/src/base/clock_network.h @@ -49,9 +49,6 @@ class ClockNetwork { clock_tree_range trees() const; public: /* Public Accessors: Basic data query */ - /* Find a spine by name, return a valid id if found, otherwise return an invalid id */ - ClockSpineId spine(const std::string& name) const; - /* Check if there are clock tree */ bool empty() const; @@ -85,6 +82,7 @@ class ClockNetwork { /* Basic information of each tree */ vtr::vector tree_ids_; vtr::vector tree_names_; + vtr::vector tree_widths_; vtr::vector> tree_top_spines_; /* Basic information of each spine */ @@ -99,7 +97,8 @@ class ClockNetwork { vtr::vector spine_parent_tree_; /* Fast lookup */ - std::map spine_name2ids_; + std::map tree_name2id_map_; + std::map spine_name2id_map_; /* Flags */ bool is_dirty_; From 7bc843b74a3a3f4f6a0097c8d3a60e9e5d60529b Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 22 Feb 2023 13:23:09 -0800 Subject: [PATCH 005/166] [lib] developing xml parser for clk arch --- .../src/io/clock_network_xml_constants.h | 21 ++ .../src/io/read_xml_clock_network.cpp | 182 ++++++++++++++++++ .../src/io/read_xml_clock_network.h | 21 ++ 3 files changed, 224 insertions(+) create mode 100644 libs/libclkarchopenfpga/src/io/clock_network_xml_constants.h create mode 100644 libs/libclkarchopenfpga/src/io/read_xml_clock_network.cpp create mode 100644 libs/libclkarchopenfpga/src/io/read_xml_clock_network.h diff --git a/libs/libclkarchopenfpga/src/io/clock_network_xml_constants.h b/libs/libclkarchopenfpga/src/io/clock_network_xml_constants.h new file mode 100644 index 000000000..8d96330b4 --- /dev/null +++ b/libs/libclkarchopenfpga/src/io/clock_network_xml_constants.h @@ -0,0 +1,21 @@ +#ifndef CLOCK_NETWORK_XML_CONSTANTS_H +#define CLOCK_NETWORK_XML_CONSTANTS_H + +/* Constants required by XML parser */ + +constexpr const char* XML_CLOCK_NETWORK_ROOT_NAME = "clock_networks"; +constexpr const char* XML_CLOCK_TREE_NODE_NAME = "clock_network"; +constexpr const char* XML_CLOCK_TREE_ATTRIBUTE_NAME = "name"; +constexpr const char* XML_CLOCK_TREE_ATTRIBUTE_WIDTH = "width"; +constexpr const char* XML_CLOCK_SPINE_NODE_NAME = "spine"; +constexpr const char* XML_CLOCK_SPINE_ATTRIBUTE_NAME = "name"; +constexpr const char* XML_CLOCK_SPINE_ATTRIBUTE_START_X = "start_x"; +constexpr const char* XML_CLOCK_SPINE_ATTRIBUTE_START_Y = "start_y"; +constexpr const char* XML_CLOCK_SPINE_ATTRIBUTE_END_X = "end_x"; +constexpr const char* XML_CLOCK_SPINE_ATTRIBUTE_END_Y = "end_y"; +constexpr const char* XML_CLOCK_SPINE_SWITCH_POINT_NODE_NAME = "switch_point"; +constexpr const char* XML_CLOCK_SPINE_SWITCH_POINT_ATTRIBUTE_TAP = "tap"; +constexpr const char* XML_CLOCK_SPINE_SWITCH_POINT_ATTRIBUTE_X = "x"; +constexpr const char* XML_CLOCK_SPINE_SWITCH_POINT_ATTRIBUTE_Y = "y"; + +#endif diff --git a/libs/libclkarchopenfpga/src/io/read_xml_clock_network.cpp b/libs/libclkarchopenfpga/src/io/read_xml_clock_network.cpp new file mode 100644 index 000000000..5f349f39e --- /dev/null +++ b/libs/libclkarchopenfpga/src/io/read_xml_clock_network.cpp @@ -0,0 +1,182 @@ +/******************************************************************** + * This file includes the top-level function of this library + * which reads an XML of clock network file to the associated + * data structures + *******************************************************************/ +#include + +/* Headers from pugi XML library */ +#include "pugixml.hpp" +#include "pugixml_util.hpp" + +/* Headers from vtr util library */ +#include "vtr_assert.h" +#include "vtr_time.h" + +/* Headers from libopenfpga util library */ +#include "openfpga_port_parser.h" + +/* Headers from libarchfpga */ +#include "arch_error.h" +#include "clock_network_xml_constants.h" +#include "read_xml_clock_network.h" +#include "read_xml_util.h" + +namespace openfpga { // Begin namespace openfpga + +/******************************************************************** + * Parse XML codes of a to an object of ClockNetwork + *******************************************************************/ +static void read_xml_clock_spine_switch_point(pugi::xml_node& xml_switch_point, + const pugiutil::loc_data& loc_data, + ClockNetwork& clk_ntwk, const ClockSpineId& spine_id) { + if (!clk_ntwk.valid_spine_id(spine_id)) { + archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_switch_point), + "Invalid id of a clock spine!\n"); + } + + std::string tap_spine_name = + get_attribute(xml_switch_point, XML_CLOCK_SPINE_SWITCH_POINT_ATTRIBUTE_TAP, loc_data).as_string(); + + /* Try to find an existing spine, if not, create one */ + ClockSpineId tap_spine_id = clk_ntwk.find_spine(tap_spine_name); + if (!tap_spine_id) { + tap_spine_id = clk_ntwk.create_spine(tap_spine_name); + } + + if (false == clk_ntwk.valid_spine_id(tap_spine_id)) { + archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_switch_point), + "Fail to create a clock spine!\n"); + } + + int tap_x = + get_attribute(xml_switch_point, XML_CLOCK_SPINE_SWITCH_POINT_ATTRIBUTE_X, loc_data).as_int(); + int tap_y = + get_attribute(xml_switch_point, XML_CLOCK_SPINE_SWITCH_POINT_ATTRIBUTE_Y, loc_data).as_int(); + + clk_ntwk.add_spine_switch_point(spine_id, tap_spine_id, vtr::Point(tap_x, tap_y)); +} + +/******************************************************************** + * Parse XML codes of a to an object of ClockNetwork + *******************************************************************/ +static void read_xml_clock_spine(pugi::xml_node& xml_spine, + const pugiutil::loc_data& loc_data, + ClockNetwork& clk_ntwk, const ClockTreeId& tree_id) { + if (!clk_ntwk.valid_tree_id(tree_id)) { + archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_spine), + "Invalid id of a clock tree!\n"); + } + + std::string clk_spine_name = + get_attribute(xml_spine, XML_CLOCK_SPINE_ATTRIBUTE_NAME, loc_data).as_string(); + + /* Try to find an existing spine, if not, create one */ + ClockSpineId spine_id = clk_ntwk.find_spine(clk_spine_name); + if (!spine_id) { + spine_id = clk_ntwk.create_spine(clk_spine_name); + } + + if (false == clk_ntwk.valid_spine_id(spine_id)) { + archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_spine), + "Fail to create a clock spine!\n"); + } + + clk_ntwk.set_spine_parent_tree(spine_id, tree_id); + + int start_x = + get_attribute(xml_spine, XML_CLOCK_SPINE_ATTRIBUTE_START_X, loc_data).as_int(); + int start_y = + get_attribute(xml_spine, XML_CLOCK_SPINE_ATTRIBUTE_START_Y, loc_data).as_int(); + clk_ntwk.set_spine_start_point(spine_id, vtr::Point(start_x, start_y)); + + int end_x = + get_attribute(xml_spine, XML_CLOCK_SPINE_ATTRIBUTE_END_X, loc_data).as_int(); + int end_y = + get_attribute(xml_spine, XML_CLOCK_SPINE_ATTRIBUTE_END_Y, loc_data).as_int(); + clk_ntwk.set_spine_end_point(spine_id, vtr::Point(end_x, end_y)); + + for (pugi::xml_node xml_switch_point : xml_spine.children()) { + /* Error out if the XML child has an invalid name! */ + if (xml_switch_point.name() != std::string(XML_CLOCK_SPINE_SWITCH_POINT_NODE_NAME)) { + bad_tag(xml_switch_point, loc_data, xml_spine, {XML_CLOCK_SPINE_SWITCH_POINT_NODE_NAME}); + } + read_xml_clock_spine_switch_point(xml_switch_point, loc_data, clk_ntwk, spine_id); + } +} + +/******************************************************************** + * Parse XML codes of a to an object of ClockNetwork + *******************************************************************/ +static void read_xml_clock_tree(pugi::xml_node& xml_clk_tree, + const pugiutil::loc_data& loc_data, + ClockNetwork& clk_ntwk) { + std::string clk_tree_name = + get_attribute(xml_clk_tree, XML_CLOCK_TREE_ATTRIBUTE_NAME, loc_data).as_string(); + int clk_tree_width = + get_attribute(xml_clk_tree, XML_CLOCK_TREE_ATTRIBUTE_WIDTH, loc_data).as_int(); + + /* Create a new tree in the storage */ + ClockTreeId tree_id = clk_ntwk.create_tree(clk_tree_name, clk_tree_width); + + if (false == clk_ntwk.valid_tree_id(tree_id)) { + archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_clk_tree), + "Fail to create a clock tree!\n"); + } + + for (pugi::xml_node xml_spine : xml_clk_tree.children()) { + /* Error out if the XML child has an invalid name! */ + if (xml_spine.name() != std::string(XML_CLOCK_SPINE_NODE_NAME)) { + bad_tag(xml_spine, loc_data, xml_clk_tree, {XML_CLOCK_SPINE_NODE_NAME}); + } + read_xml_clock_spine(xml_spine, loc_data, clk_ntwk, tree_id); + } +} + +/******************************************************************** + * Parse XML codes about to an object of ClockNetwork + *******************************************************************/ +ClockNetwork read_xml_clock_network(const char* fname) { + vtr::ScopedStartFinishTimer timer("Read clock network"); + + ClockNetwork clk_ntwk; + + /* Parse the file */ + pugi::xml_document doc; + pugiutil::loc_data loc_data; + + try { + loc_data = pugiutil::load_xml(doc, fname); + + pugi::xml_node xml_root = + get_single_child(doc, XML_CLOCK_NETWORK_ROOT_NAME, loc_data); + + size_t num_trees = + std::distance(xml_root.children().begin(), xml_root.children().end()); + + /* Count the total number of spines */ + size_t num_spines = 0; + for (pugi::xml_node xml_tree : xml_root.children()) { + num_spines += + std::distance(xml_tree.children().begin(), xml_tree.children().end()); + } + + /* Reserve memory space */ + clk_ntwk.reserve_trees(num_trees); + clk_ntwk.reserve_spines(num_spines); + + for (pugi::xml_node xml_tree : xml_root.children()) { + /* Error out if the XML child has an invalid name! */ + if (xml_tree.name() != std::string(XML_CLOCK_NETWORK_NODE_NAME)) { + bad_tag(xml_tree, loc_data, xml_root, {XML_CLOCK_NETWORK_NODE_NAME}); + } + read_xml_clock_tree(xml_tree, loc_data, clk_ntwk); + } + } catch (pugiutil::XmlError& e) { + archfpga_throw(fname, e.line(), "%s", e.what()); + } + + return clk_ntwk; +} + +} // End of namespace openfpga diff --git a/libs/libclkarchopenfpga/src/io/read_xml_clock_network.h b/libs/libclkarchopenfpga/src/io/read_xml_clock_network.h new file mode 100644 index 000000000..29e2f8f06 --- /dev/null +++ b/libs/libclkarchopenfpga/src/io/read_xml_clock_network.h @@ -0,0 +1,21 @@ +#ifndef READ_XML_CLOCK_NETWORK_H +#define READ_XML_CLOCK_NETWORK_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +#include "clock_network.h" +#include "pugixml.hpp" +#include "pugixml_util.hpp" + +/******************************************************************** + * Function declaration + *******************************************************************/ + +namespace openfpga { // Begin namespace openfpga + +ClockNetwork read_xml_clock_network(const char* fname); + +} // End of namespace openfpga + +#endif From 5cd310c4cce98cfdc57f0614bf27728d16eb2631 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 22 Feb 2023 15:04:52 -0800 Subject: [PATCH 006/166] [lib] adding missing apis --- .../src/base/clock_network.cpp | 16 ++++++++++++++++ libs/libclkarchopenfpga/src/base/clock_network.h | 5 +++++ 2 files changed, 21 insertions(+) diff --git a/libs/libclkarchopenfpga/src/base/clock_network.cpp b/libs/libclkarchopenfpga/src/base/clock_network.cpp index 3e1b6eeaf..c4bd0584d 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.cpp +++ b/libs/libclkarchopenfpga/src/base/clock_network.cpp @@ -28,6 +28,14 @@ ClockNetwork::clock_tree_range ClockNetwork::trees() const { /************************************************************************ * Public Accessors : Basic data query ***********************************************************************/ +bool ClockNetwork::find_spine(const std::string& name) const { + auto result = spine_name2id_map_.find(name); + if (result == spine_name2id_map_.end()) { + return ClockSpineId::INVALID(); + } + return result->second; +} + bool ClockNetwork::empty() const { return 0 == tree_ids_.size(); } /************************************************************************ @@ -103,6 +111,14 @@ ClockSpineId ClockNetwork::create_spine(const std::string& name) { return spine_id; } +ClockSpineId ClockNetwork::try_create_spine(const std::string& name) { + ClockSpineId spine_id = find_spine(name); + if (!spine_id) { + spine_id = create_spine(name); + } + return spine_id; +} + void ClockNetwork::set_spine_parent_tree(const ClockSpineId& spine_id, const ClockTreeId& tree_id) { VTR_ASSERT(valid_spine_id(spine_id)); VTR_ASSERT(valid_tree_id(tree_id)); diff --git a/libs/libclkarchopenfpga/src/base/clock_network.h b/libs/libclkarchopenfpga/src/base/clock_network.h index 30c2d6bde..ba2f90b1b 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.h +++ b/libs/libclkarchopenfpga/src/base/clock_network.h @@ -49,6 +49,9 @@ class ClockNetwork { clock_tree_range trees() const; public: /* Public Accessors: Basic data query */ + /* Find a spine with a given name, if not found, return an valid id, otherwise return an invalid one */ + ClockSpineId find_spine(const std::string& name) const; + /* Check if there are clock tree */ bool empty() const; @@ -64,6 +67,8 @@ class ClockNetwork { /* Create a new spine, if the spine is already created, return an invalid id */ ClockSpineId create_spine(const std::string& name); + /* Try to create a new spine, if the spine is already existing, return the id. If not, create a new spine and return its id */ + ClockSpineId try_create_spine(const std::string& name); /* Set the parent tree for a given spine. It is illegal that a spine which does not belong to any tree */ void set_spine_parent_tree(const ClockSpineId& spine_id, const ClockTreeId& tree_id); From b37deb4b022112d8659970e0feb8d3b1ef954da2 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 22 Feb 2023 18:21:28 -0800 Subject: [PATCH 007/166] [lib] adding writer --- .../src/base/clock_network.cpp | 67 +++++++- .../src/base/clock_network.h | 20 ++- .../src/base/clock_network_fwd.h | 2 + .../src/io/write_xml_clock_network.cpp | 162 ++++++++++++++++++ .../src/io/write_xml_clock_network.h | 20 +++ 5 files changed, 263 insertions(+), 8 deletions(-) create mode 100644 libs/libclkarchopenfpga/src/io/write_xml_clock_network.cpp create mode 100644 libs/libclkarchopenfpga/src/io/write_xml_clock_network.h diff --git a/libs/libclkarchopenfpga/src/base/clock_network.cpp b/libs/libclkarchopenfpga/src/base/clock_network.cpp index c4bd0584d..3bfc16f40 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.cpp +++ b/libs/libclkarchopenfpga/src/base/clock_network.cpp @@ -28,6 +28,62 @@ ClockNetwork::clock_tree_range ClockNetwork::trees() const { /************************************************************************ * Public Accessors : Basic data query ***********************************************************************/ +std::string ClockNetwork::tree_name(const ClockTreeId& tree_id) const { + VTR_ASSERT(valid_tree_id(tree_id)); + return tree_names_[tree_id]; +} + +size_t ClockNetwork::tree_width(const ClockTreeId& tree_id) const { + VTR_ASSERT(valid_tree_id(tree_id)); + return tree_widths_[tree_id]; +} + +std::vector ClockNetwork::spines(const ClockTreeId& tree_id) const { + std::vector ret; + for (ClockSpineId spine_id : spine_ids_) { + if (spine_parent_tree_[spine_id] == tree_id) { + ret.push_back(spine_id); + } + } + return ret; +} + +std::string ClockNetwork::spine_name(const ClockSpineId& spine_id) const { + VTR_ASSERT(valid_spine_id(spine_id)); + return spine_names_[spine_id]; +} + +vtr::Point ClockNetwork::spine_start_point(const ClockSpineId& spine_id) const { + VTR_ASSERT(valid_spine_id(spine_id)); + return spine_start_points_[spine_id]; +} + +vtr::Point ClockNetwork::spine_end_point(const ClockSpineId& spine_id) const { + VTR_ASSERT(valid_spine_id(spine_id)); + return spine_end_points_[spine_id]; +} + +std::vector ClockNetwork::spine_switch_points(const ClockSpineId& spine_id) const { + VTR_ASSERT(valid_spine_id(spine_id)); + std::vector ret; + ret.reserve(spine_switch_points_[spine_id].size()); + for (size_t i = 0; i < spine_switch_points_[spine_id].size(); ++i) { + ret.push_back(ClockSwitchPointId(i)); + } + + return ret; +} + +ClockSpineId ClockNetwork::spine_switch_point_tap(const ClockSpineId& spine_id, const ClockSwitchPointId& switch_point_id) const { + VTR_ASSERT(valid_spine_switch_point_id(spine_id, switch_point_id)); + return spine_switch_points_[spine_id][size_t(switch_point_id)]; +} + +vtr::Point ClockNetwork::spine_switch_point(const ClockSpineId& spine_id, const ClockSwitchPointId& switch_point_id) const { + VTR_ASSERT(valid_spine_switch_point_id(spine_id, switch_point_id)); + return spine_switch_coords_[spine_id][size_t(switch_point_id)]; +} + bool ClockNetwork::find_spine(const std::string& name) const { auto result = spine_name2id_map_.find(name); if (result == spine_name2id_map_.end()) { @@ -135,10 +191,12 @@ void ClockNetwork::set_spine_end_point(const ClockSpineId& spine_id, const vtr:: spine_end_points_[spine_id] = coord; } -void ClockNetwork::add_spine_switch_point(const ClockSpineId& spine_id, const ClockSpineId& drive_spine, const vtr::Point& coord) { +void ClockNetwork::add_spine_switch_point(const ClockSpineId& spine_id, const ClockSpineId& drive_spine_id, const vtr::Point& coord) { VTR_ASSERT(valid_spine_id(spine_id)); + VTR_ASSERT(valid_spine_id(drive_spine_id)); spine_switch_points_[spine_id].push_back(drive_spine); spine_switch_coords_[spine_id].push_back(coord); + spine_parent_[drive_spine_id] = spine_id; } /************************************************************************ @@ -152,4 +210,11 @@ bool ClockNetwork::valid_spine_id(const ClockSpineId& spine_id) const { return (size_t(spine_id) < spine_ids_.size()) && (spine_id == spine_ids_[spine_id]); } +bool valid_spine_switch_point_id(const ClockSpineId& spine_id, const ClockSwitchPointId& switch_point_id) const { + if (!valid_spine_id(spine_id)) { + return false; + } + return size_t(switch_point_id) < spine_switch_points_[spine_id].size(); +} + } // End of namespace openfpga diff --git a/libs/libclkarchopenfpga/src/base/clock_network.h b/libs/libclkarchopenfpga/src/base/clock_network.h index ba2f90b1b..c22a7bb93 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.h +++ b/libs/libclkarchopenfpga/src/base/clock_network.h @@ -47,41 +47,47 @@ class ClockNetwork { public: /* Accessors: aggregates */ clock_tree_range trees() const; + /* Return a list of spine id under a clock tree */ + std::vector spines(const ClockTreeId& tree_id) const; public: /* Public Accessors: Basic data query */ + std::string tree_name(const ClockTreeId& tree_id) const; + size_t tree_width(const ClockTreeId& tree_id) const; + std::string spine_name(const ClockSpineId& spine_id) const; + vtr::Point spine_start_point(const ClockSpineId& spine_id) const; + vtr::Point spine_end_point(const ClockSpineId& spine_id) const; + /* Return the unique id of switch points under a clock spine*/ + std::vector spine_switch_points(const ClockSpineId& spine_id) const; + ClockSpineId spine_switch_point_tap(const ClockSpineId& spine_id, const ClockSwitchPointId& switch_point_id) const; + vtr::Point spine_switch_point(const ClockSpineId& spine_id, const ClockSwitchPointId& switch_point_id) const; /* Find a spine with a given name, if not found, return an valid id, otherwise return an invalid one */ ClockSpineId find_spine(const std::string& name) const; - /* Check if there are clock tree */ bool empty() const; public: /* Public Mutators */ /* Reserve a number of spines to be memory efficent */ void reserve_spines(const size_t& num_spines); - /* Reserve a number of trees to be memory efficent */ void reserve_trees(const size_t& num_trees); - /* Create a new tree, by default the tree can accomodate only 1 clock signal; use width to adjust the size */ ClockTreeId create_tree(const std::string& name, const size_t& width = 1); - /* Create a new spine, if the spine is already created, return an invalid id */ ClockSpineId create_spine(const std::string& name); /* Try to create a new spine, if the spine is already existing, return the id. If not, create a new spine and return its id */ ClockSpineId try_create_spine(const std::string& name); - /* Set the parent tree for a given spine. It is illegal that a spine which does not belong to any tree */ void set_spine_parent_tree(const ClockSpineId& spine_id, const ClockTreeId& tree_id); void set_spine_start_point(const ClockSpineId& spine_id, const vtr::Point& coord); void set_spine_end_point(const ClockSpineId& spine_id, const vtr::Point& coord); - void add_spine_switch_point(const ClockSpineId& spine_id, const ClockSpineId& drive_spine, const vtr::Point& coord); + void add_spine_switch_point(const ClockSpineId& spine_id, const ClockSpineId& drive_spine_id, const vtr::Point& coord); public: /* Public invalidators/validators */ /* Show if the tree id is a valid for data queries */ bool valid_tree_id(const ClockTreeId& tree_id) const; - /* Show if the tree id is a valid for data queries */ bool valid_spine_id(const ClockSpineId& spine_id) const; + bool valid_spine_switch_point_id(const ClockSpineId& spine_id, const ClockSwitchPointId& switch_point_id) const; private: /* Internal data */ /* Basic information of each tree */ diff --git a/libs/libclkarchopenfpga/src/base/clock_network_fwd.h b/libs/libclkarchopenfpga/src/base/clock_network_fwd.h index d936bbb9c..cc4af5f70 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network_fwd.h +++ b/libs/libclkarchopenfpga/src/base/clock_network_fwd.h @@ -16,9 +16,11 @@ namespace openfpga { // Begin namespace openfpga struct clock_tree_id_tag; struct clock_spine_id_tag; +struct clock_switch_point_id_tag; typedef vtr::StrongId ClockTreeId; typedef vtr::StrongId ClockSpineId; +typedef vtr::StrongId ClockSwitchPointId; /* Short declaration of class */ class ClockNetwork; diff --git a/libs/libclkarchopenfpga/src/io/write_xml_clock_network.cpp b/libs/libclkarchopenfpga/src/io/write_xml_clock_network.cpp new file mode 100644 index 000000000..cdd58686e --- /dev/null +++ b/libs/libclkarchopenfpga/src/io/write_xml_clock_network.cpp @@ -0,0 +1,162 @@ +/******************************************************************** + * This file includes functions that outputs a clock network object to XML format + *******************************************************************/ +/* Headers from system goes first */ +#include +#include + +/* Headers from vtr util library */ +#include "vtr_assert.h" +#include "vtr_log.h" +#include "vtr_time.h" + +/* Headers from openfpga util library */ +#include "openfpga_digest.h" + +/* Headers from arch openfpga library */ +#include "write_xml_utils.h" + +/* Headers from pin constraint library */ +#include "clock_network_xml_constants.h" +#include "write_xml_clock_network.h" + +namespace openfpga { // Begin namespace openfpga + +static int write_xml_clock_spine_switch_point(std::fstream& fp, const ClockNetwork& clk_ntwk, + const ClockSpineId& spine_id, const ClockSwitchPointId& switch_point_id) { + openfpga::write_tab_to_file(fp, 3); + fp << "<" << XML_CLOCK_SPINE_SWITCH_POINT_NODE_NAME << ""; + + write_xml_attribute(fp, XML_CLOCK_SPINE_SWITCH_POINT_ATTRIBUTE_TAP, + clk_ntwk.spine_switch_point_tap(spine_id, switch_point_id)); + vtr::Point coord = clk_ntwk.spine_switch_point(spine_id); + write_xml_attribute(fp, XML_CLOCK_SPINE_SWITCH_POINT_ATTRIBUTE_X, + coord.x()); + write_xml_attribute(fp, XML_CLOCK_SPINE_SWITCH_POINT_ATTRIBUTE_Y, + coord.y()); + + fp << "/>" + << "\n"; + + return 0; +} + +static int write_xml_clock_spine(std::fstream& fp, const ClockNetwork& clk_ntwk, + const ClockSpineId& spine_id) { + openfpga::write_tab_to_file(fp, 2); + fp << "<" << XML_CLOCK_SPINE_NODE_NAME << ""; + + write_xml_attribute(fp, XML_CLOCK_SPINE_ATTRIBUTE_NAME, + clk_ntwk.spine_name(spine_id)); + vtr::Point start_coord = clk_ntwk.spine_start_point(spine_id); + write_xml_attribute(fp, XML_CLOCK_SPINE_ATTRIBUTE_START_X, + start_coord.x()); + write_xml_attribute(fp, XML_CLOCK_SPINE_ATTRIBUTE_START_Y, + start_coord.y()); + vtr::Point end_coord = clk_ntwk.spine_end_point(spine_id); + write_xml_attribute(fp, XML_CLOCK_SPINE_ATTRIBUTE_END_X, + end_coord.x()); + write_xml_attribute(fp, XML_CLOCK_SPINE_ATTRIBUTE_END_Y, + end_coord.y()); + + fp << ">" + << "\n"; + + for (const ClockSwitchPointId& switch_point_id : clk_ntwk.spine_switch_points(spine_id)) { + write_xml_clock_spine_switch_point(fp, clk_ntwk, spine_id, switch_point_id); + } + + openfpga::write_tab_to_file(fp, 2); + fp << "" + << "\n"; + + return 0; +} + +/******************************************************************** + * A writer to output a clock tree to XML format + * + * Return 0 if successful + * Return 1 if there are more serious bugs in the architecture + * Return 2 if fail when creating files + *******************************************************************/ +static int write_xml_clock_tree(std::fstream& fp, const ClockNetwork& clk_ntwk, + const ClockTreeId& tree_id) { + /* Validate the file stream */ + if (false == openfpga::valid_file_stream(fp)) { + return 2; + } + + openfpga::write_tab_to_file(fp, 1); + fp << "<" << XML_CLOCK_TREE_NODE_NAME << ""; + + if (false == clk_ntwk.valid_tree_id(tree_id)) { + return 1; + } + + write_xml_attribute( + fp, XML_CLOCK_TREE_ATTRIBUTE_NAME, + clk_ntwk.tree_name(tree_id).c_str()); + write_xml_attribute(fp, XML_CLOCK_TREE_ATTRIBUTE_WIDTH, + clk_ntwk.tree_width(tree_id)); + fp << ">" + << "\n"; + + /* Output all the pins under this bus */ + for (const ClockSpineId& spine_id : clk_ntwk.spines(tree_id)) { + write_xml_clock_spine(fp, clk_ntwk, spine_id); + } + + openfpga::write_tab_to_file(fp, 1); + fp << "" + << "\n"; + + return 0; +} + +/******************************************************************** + * A writer to output a bus group object to XML format + * + * Return 0 if successful + * Return 1 if there are more serious bugs in the architecture + * Return 2 if fail when creating files + *******************************************************************/ +int write_xml_clock_network(const char* fname, const ClockNetwork& clk_ntwk) { + vtr::ScopedStartFinishTimer timer("Write Clock Network"); + + /* Create a file handler */ + std::fstream fp; + /* Open the file stream */ + fp.open(std::string(fname), std::fstream::out | std::fstream::trunc); + + /* Validate the file stream */ + openfpga::check_file_stream(fname, fp); + + /* Write the root node */ + fp << "<" << XML_CLOCK_NETWORK_ROOT_NAME << ">" + << "\n"; + + int err_code = 0; + + /* Write each bus */ + for (const ClockTreeId& tree_id : clk_ntwk.trees()) { + /* Write bus */ + err_code = write_xml_clock_tree(fp, clk_ntwk, tree_id); + if (0 != err_code) { + return err_code; + } + } + + /* Finish writing the root node */ + fp << "" + << "\n"; + + /* Close the file stream */ + fp.close(); + + return err_code; +} + +} // End of namespace openfpga diff --git a/libs/libclkarchopenfpga/src/io/write_xml_clock_network.h b/libs/libclkarchopenfpga/src/io/write_xml_clock_network.h new file mode 100644 index 000000000..3019b414a --- /dev/null +++ b/libs/libclkarchopenfpga/src/io/write_xml_clock_network.h @@ -0,0 +1,20 @@ +#ifndef WRITE_XML_CLOCK_NETWORK_H +#define WRITE_XML_CLOCK_NETWORK_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +#include + +#include "clock_network.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ +namespace openfpga { // Begin namespace openfpga + +int write_xml_clock_network(const char* fname, const ClockNetwork& clk_ntwk); + +} // End of namespace openfpga + +#endif From ce20a16aad2a31abeed7be1438972631809bafc1 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 22 Feb 2023 18:26:18 -0800 Subject: [PATCH 008/166] [lib] adding unit test --- .../test/xml_io_clock_network.cpp | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 libs/libclkarchopenfpga/test/xml_io_clock_network.cpp diff --git a/libs/libclkarchopenfpga/test/xml_io_clock_network.cpp b/libs/libclkarchopenfpga/test/xml_io_clock_network.cpp new file mode 100644 index 000000000..60655bdd0 --- /dev/null +++ b/libs/libclkarchopenfpga/test/xml_io_clock_network.cpp @@ -0,0 +1,39 @@ +/******************************************************************** + * Unit test functions to validate the correctness of + * 1. parser of data structures + * 2. writer of data structures + *******************************************************************/ +/* Headers from vtrutils */ +#include "vtr_assert.h" +#include "vtr_log.h" + +/* Headers from readarchopenfpga */ +#include "read_xml_clock_network.h" +#include "write_xml_clock_network.h" + +int main(int argc, const char** argv) { + /* Ensure we have only one or two argument */ + VTR_ASSERT((2 == argc) || (3 == argc)); + + /* Parse the circuit library from an XML file */ + const openfpga::ClockNetwork& clk_ntwk = openfpga::read_xml_clock_network(argv[1]); + VTR_LOG("Parsed %lu clock tree(s) from XML into clock network.\n", + clk_ntwk.trees().size()); + + /* Validate before write out */ + clk_ntwk.validate(); + if (!clk_ntwk.is_valid()) { + VTR_LOG_ERROR("Invalid clock network.\n"); + exit(1); + } + + /* Output the bus group to an XML file + * This is optional only used when there is a second argument + */ + if (3 <= argc) { + openfpga::write_xml_clock_network(argv[2], clk_ntwk); + VTR_LOG("Write the clock network to an XML file: %s.\n", argv[2]); + } + + return 0; +} From bf2876c60e37e139adc0afda7ccf2b443f65a384 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 22 Feb 2023 18:36:22 -0800 Subject: [PATCH 009/166] [lib] developing linker --- .../src/base/clock_network.cpp | 21 +++++++++++++++++++ .../src/base/clock_network.h | 6 ++++++ 2 files changed, 27 insertions(+) diff --git a/libs/libclkarchopenfpga/src/base/clock_network.cpp b/libs/libclkarchopenfpga/src/base/clock_network.cpp index 3bfc16f40..808286911 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.cpp +++ b/libs/libclkarchopenfpga/src/base/clock_network.cpp @@ -199,6 +199,27 @@ void ClockNetwork::add_spine_switch_point(const ClockSpineId& spine_id, const Cl spine_parent_[drive_spine_id] = spine_id; } +bool ClockNetwork::link() { + for (ClockTreeId& tree_id : trees()) { + if (!link_tree(tree_id)) { + return false; + } + } + return true; +} + +bool ClockNetwork::link_tree(const ClockTreeId& tree_id) { + tree_top_spines_[tree_id].clear(); + /* Sort the spines under a tree; assign levels and identify top-level spines */ + for (ClockSpineId spine_id : spines(tree_id)) { + /* Spines that have no parent are the top-level spines*/ + if (!spine_parent_[spine_id]) { + tree_top_spines_[tree_id].push_back(spine_id); + } + } + return true; +} + /************************************************************************ * Internal invalidators/validators ***********************************************************************/ diff --git a/libs/libclkarchopenfpga/src/base/clock_network.h b/libs/libclkarchopenfpga/src/base/clock_network.h index c22a7bb93..c566f045f 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.h +++ b/libs/libclkarchopenfpga/src/base/clock_network.h @@ -81,6 +81,8 @@ class ClockNetwork { void set_spine_start_point(const ClockSpineId& spine_id, const vtr::Point& coord); void set_spine_end_point(const ClockSpineId& spine_id, const vtr::Point& coord); void add_spine_switch_point(const ClockSpineId& spine_id, const ClockSpineId& drive_spine_id, const vtr::Point& coord); + /* Build internal links between clock tree, spines etc. This is also an validator to verify the correctness of the clock network. Must run before using the data! */ + bool link(); public: /* Public invalidators/validators */ /* Show if the tree id is a valid for data queries */ @@ -89,6 +91,10 @@ class ClockNetwork { bool valid_spine_id(const ClockSpineId& spine_id) const; bool valid_spine_switch_point_id(const ClockSpineId& spine_id, const ClockSwitchPointId& switch_point_id) const; + private: /* Private mutators */ + /* Build internal links between spines under a given tree */ + bool link_tree(const ClockTreeId& tree_id); + private: /* Internal data */ /* Basic information of each tree */ vtr::vector tree_ids_; From 1c8a5eb0987ec2abed9b4a2ef7b4fef0f83caef5 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 22 Feb 2023 20:29:32 -0800 Subject: [PATCH 010/166] [lib] adding linker --- .../src/base/clock_network.cpp | 54 +++++++++++++++---- .../src/base/clock_network.h | 9 +++- 2 files changed, 52 insertions(+), 11 deletions(-) diff --git a/libs/libclkarchopenfpga/src/base/clock_network.cpp b/libs/libclkarchopenfpga/src/base/clock_network.cpp index 808286911..244a1a9c0 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.cpp +++ b/libs/libclkarchopenfpga/src/base/clock_network.cpp @@ -41,7 +41,7 @@ size_t ClockNetwork::tree_width(const ClockTreeId& tree_id) const { std::vector ClockNetwork::spines(const ClockTreeId& tree_id) const { std::vector ret; for (ClockSpineId spine_id : spine_ids_) { - if (spine_parent_tree_[spine_id] == tree_id) { + if (spine_parent_trees_[spine_id] == tree_id) { ret.push_back(spine_id); } } @@ -105,8 +105,9 @@ void ClockNetwork::reserve_spines(const size_t& num_spines) { spine_end_points_.reserve(num_spines); spine_switch_points_.reserve(num_spines); spine_switch_coords_.reserve(num_spines); - spine_parent_.reserve(num_spines); - spine_parent_tree_.reserve(num_spines); + spine_parents_.reserve(num_spines); + spine_children_.reserve(num_spines); + spine_parent_trees_.reserve(num_spines); } void ClockNetwork::reserve_trees(const size_t& num_trees) { @@ -153,13 +154,14 @@ ClockSpineId ClockNetwork::create_spine(const std::string& name) { spine_ids_.push_back(spine_id); spine_names_.push_back(name); - spine_levels_.emplace_back(); + spine_levels_.emplace_back(0); spine_start_points_.emplace_back(); spine_end_points_.emplace_back(); spine_switch_points_.emplace_back(); spine_switch_coords_.emplace_back(); - spine_parent_.emplace_back(); - spine_parent_tree_.emplace_back(); + spine_parents_.emplace_back(); + spine_children_.emplace_back(); + spine_parent_trees_.emplace_back(); /* Register to the lookup */ spine_name2id_map_[name] = spine_id; @@ -178,7 +180,7 @@ ClockSpineId ClockNetwork::try_create_spine(const std::string& name) { void ClockNetwork::set_spine_parent_tree(const ClockSpineId& spine_id, const ClockTreeId& tree_id) { VTR_ASSERT(valid_spine_id(spine_id)); VTR_ASSERT(valid_tree_id(tree_id)); - spine_parent_tree_[spine_id] = tree_id; + spine_parent_trees_[spine_id] = tree_id; } void ClockNetwork::set_spine_start_point(const ClockSpineId& spine_id, const vtr::Point& coord) { @@ -196,7 +198,17 @@ void ClockNetwork::add_spine_switch_point(const ClockSpineId& spine_id, const Cl VTR_ASSERT(valid_spine_id(drive_spine_id)); spine_switch_points_[spine_id].push_back(drive_spine); spine_switch_coords_[spine_id].push_back(coord); - spine_parent_[drive_spine_id] = spine_id; + /* Do not allow any spine has different parents */ + if (spine_parents_[drive_spine_id]) { + VTR_LOG_ERROR("Detect a spine %s' has two parents '%s' and '%s'. Not allowed in a clock tree!\n", + spine_name(drive_spine_id).c_str(), + spine_name(spine_parents_[drive_spine_id]).c_str(), + spine_name(spine_id).c_str() + ); + exit(1); + } + spine_parents_[drive_spine_id] = spine_id; + spine_children_[spine_id].push_back(drive_spine_id); } bool ClockNetwork::link() { @@ -209,17 +221,41 @@ bool ClockNetwork::link() { } bool ClockNetwork::link_tree(const ClockTreeId& tree_id) { + if (!link_tree_top_spines(tree_id)) { + return false; + } + if (!sort_tree_spines(tree_id)) { + return false; + } + return true; +} + +bool ClockNetwork::link_tree_top_spines(const ClockTreeId& tree_id) { tree_top_spines_[tree_id].clear(); /* Sort the spines under a tree; assign levels and identify top-level spines */ for (ClockSpineId spine_id : spines(tree_id)) { /* Spines that have no parent are the top-level spines*/ - if (!spine_parent_[spine_id]) { + if (!spine_parents_[spine_id]) { tree_top_spines_[tree_id].push_back(spine_id); } } return true; } +bool ClockNetwork::sort_tree_spines(const ClockTreeId& tree_id) { + for (ClockSpineId spine_id : tree_top_spines_[tree_id]) { + spine_levels_[spine_id] = 0; + rec_update_spine_level(spine_id); + } +} + +bool ClockNetwork::rec_update_spine_level(const ClockSpineId& spine_id) { + for (ClockSpineId child_spine_id : spine_children_[spine_id]) { + spine_levels_[child_spine_id] = spine_levels_[spine_id] + 1; + rec_update_spine_level(child_spine_id); + } +} + /************************************************************************ * Internal invalidators/validators ***********************************************************************/ diff --git a/libs/libclkarchopenfpga/src/base/clock_network.h b/libs/libclkarchopenfpga/src/base/clock_network.h index c566f045f..7a7e33616 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.h +++ b/libs/libclkarchopenfpga/src/base/clock_network.h @@ -94,6 +94,10 @@ class ClockNetwork { private: /* Private mutators */ /* Build internal links between spines under a given tree */ bool link_tree(const ClockTreeId& tree_id); + bool link_tree_top_spines(const ClockTreeId& tree_id); + /* Require link_tree_top_spines() to called before! */ + bool sort_tree_spines(const ClockTreeId& tree_id); + bool rec_update_spine_level(const ClockSpineId& spine_id); private: /* Internal data */ /* Basic information of each tree */ @@ -110,8 +114,9 @@ class ClockNetwork { vtr::vector> spine_end_points_; vtr::vector> spine_switch_points_; vtr::vector>> spine_switch_coords_; - vtr::vector spine_parent_; - vtr::vector spine_parent_tree_; + vtr::vector spine_parents_; + vtr::vector> spine_children_; + vtr::vector spine_parent_trees_; /* Fast lookup */ std::map tree_name2id_map_; From b2ef1db5f499c87628928da1a32f4999e938f63a Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 22 Feb 2023 20:46:18 -0800 Subject: [PATCH 011/166] [lib] finishing up code changes; start debugging --- libs/CMakeLists.txt | 1 + .../src/base/clock_network.cpp | 28 +++++++++++++++++++ .../src/base/clock_network.h | 5 ++++ .../test/xml_io_clock_network.cpp | 7 +++-- 4 files changed, 39 insertions(+), 2 deletions(-) diff --git a/libs/CMakeLists.txt b/libs/CMakeLists.txt index 2c043b5ef..a871fa27e 100644 --- a/libs/CMakeLists.txt +++ b/libs/CMakeLists.txt @@ -1,6 +1,7 @@ # OpenFPGA-related libraries add_subdirectory(libini) add_subdirectory(libopenfpgashell) +add_subdirectory(libclkarchopenfpga) add_subdirectory(libarchopenfpga) add_subdirectory(libopenfpgautil) add_subdirectory(libfabrickey) diff --git a/libs/libclkarchopenfpga/src/base/clock_network.cpp b/libs/libclkarchopenfpga/src/base/clock_network.cpp index 244a1a9c0..3c2915f78 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.cpp +++ b/libs/libclkarchopenfpga/src/base/clock_network.cpp @@ -38,6 +38,15 @@ size_t ClockNetwork::tree_width(const ClockTreeId& tree_id) const { return tree_widths_[tree_id]; } +size_t ClockNetwork::tree_depth(const ClockTreeId& tree_id) const { + VTR_ASSERT(valid_tree_id(tree_id)); + if (is_dirty_) { + VTR_LOG_ERROR("Unable to identify tree depth when data is still dirty!\n"); + exit(1); + } + return tree_depths_[tree_id]; +} + std::vector ClockNetwork::spines(const ClockTreeId& tree_id) const { std::vector ret; for (ClockSpineId spine_id : spine_ids_) { @@ -94,6 +103,8 @@ bool ClockNetwork::find_spine(const std::string& name) const { bool ClockNetwork::empty() const { return 0 == tree_ids_.size(); } +bool ClockNetwork::is_valid() const { return !is_dirty_; } + /************************************************************************ * Public Mutators ***********************************************************************/ @@ -124,6 +135,7 @@ ClockTreeId ClockNetwork::create_tree(const std::string& name, const size_t& wid tree_ids_.push_back(tree_id); tree_names_.push_back(name); tree_widths_.push_back(width); + tree_depths_.emplace_back(); tree_top_spines_.emplace_back(); /* Register to fast look-up */ @@ -212,11 +224,13 @@ void ClockNetwork::add_spine_switch_point(const ClockSpineId& spine_id, const Cl } bool ClockNetwork::link() { + is_dirty_ = true; for (ClockTreeId& tree_id : trees()) { if (!link_tree(tree_id)) { return false; } } + is_dirty_ = false; return true; } @@ -227,6 +241,9 @@ bool ClockNetwork::link_tree(const ClockTreeId& tree_id) { if (!sort_tree_spines(tree_id)) { return false; } + if (!update_tree_depth(tree_id)) { + return false; + } return true; } @@ -247,6 +264,7 @@ bool ClockNetwork::sort_tree_spines(const ClockTreeId& tree_id) { spine_levels_[spine_id] = 0; rec_update_spine_level(spine_id); } + return true; } bool ClockNetwork::rec_update_spine_level(const ClockSpineId& spine_id) { @@ -254,6 +272,16 @@ bool ClockNetwork::rec_update_spine_level(const ClockSpineId& spine_id) { spine_levels_[child_spine_id] = spine_levels_[spine_id] + 1; rec_update_spine_level(child_spine_id); } + return true; +} + +bool ClockNetwork::update_tree_depth(const ClockTreeId& tree_id) { + size_t depth = 0; + for (ClockSpineId spine_id : tree_spines_[tree_id]) { + depth = std::max(depth, spine_levels_[spine_id]); + } + tree_depths_[tree_id] = depth; + return true; } /************************************************************************ diff --git a/libs/libclkarchopenfpga/src/base/clock_network.h b/libs/libclkarchopenfpga/src/base/clock_network.h index 7a7e33616..316815694 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.h +++ b/libs/libclkarchopenfpga/src/base/clock_network.h @@ -53,6 +53,7 @@ class ClockNetwork { public: /* Public Accessors: Basic data query */ std::string tree_name(const ClockTreeId& tree_id) const; size_t tree_width(const ClockTreeId& tree_id) const; + size_t tree_depth(const ClockTreeId& tree_id) const; std::string spine_name(const ClockSpineId& spine_id) const; vtr::Point spine_start_point(const ClockSpineId& spine_id) const; vtr::Point spine_end_point(const ClockSpineId& spine_id) const; @@ -64,6 +65,7 @@ class ClockNetwork { ClockSpineId find_spine(const std::string& name) const; /* Check if there are clock tree */ bool empty() const; + bool is_valid() const; public: /* Public Mutators */ /* Reserve a number of spines to be memory efficent */ @@ -98,12 +100,15 @@ class ClockNetwork { /* Require link_tree_top_spines() to called before! */ bool sort_tree_spines(const ClockTreeId& tree_id); bool rec_update_spine_level(const ClockSpineId& spine_id); + /* Require sort_tree_spines() to called before! */ + bool update_tree_depth(const ClockTreeId& tree_id); private: /* Internal data */ /* Basic information of each tree */ vtr::vector tree_ids_; vtr::vector tree_names_; vtr::vector tree_widths_; + vtr::vector tree_depths_; vtr::vector> tree_top_spines_; /* Basic information of each spine */ diff --git a/libs/libclkarchopenfpga/test/xml_io_clock_network.cpp b/libs/libclkarchopenfpga/test/xml_io_clock_network.cpp index 60655bdd0..81da04ea3 100644 --- a/libs/libclkarchopenfpga/test/xml_io_clock_network.cpp +++ b/libs/libclkarchopenfpga/test/xml_io_clock_network.cpp @@ -21,11 +21,14 @@ int main(int argc, const char** argv) { clk_ntwk.trees().size()); /* Validate before write out */ - clk_ntwk.validate(); - if (!clk_ntwk.is_valid()) { + if (!clk_ntwk.link()) { VTR_LOG_ERROR("Invalid clock network.\n"); exit(1); } + VTR_ASSERT(clk_ntwk.is_valid()); + for (auto tree_id : clk_ntwk.trees()) { + VTR_LOG("Max. depth of the clock tree '%lu' is %d", size_t(tree_id), clk_ntwk.tree_depth(tree_id)); + } /* Output the bus group to an XML file * This is optional only used when there is a second argument From aafd1e6fb304304a5125e8913a1e7caf36f5f5ba Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 22 Feb 2023 21:02:35 -0800 Subject: [PATCH 012/166] [lib] syntax --- libs/libclkarchopenfpga/CMakeLists.txt | 2 +- libs/libclkarchopenfpga/src/base/clock_network.cpp | 12 ++++++------ libs/libclkarchopenfpga/src/base/clock_network.h | 2 +- .../src/io/read_xml_clock_network.cpp | 4 ++-- .../src/io/write_xml_clock_network.cpp | 6 +++--- .../libclkarchopenfpga/test/xml_io_clock_network.cpp | 2 +- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/libs/libclkarchopenfpga/CMakeLists.txt b/libs/libclkarchopenfpga/CMakeLists.txt index 6db47eff5..5ff1f7607 100644 --- a/libs/libclkarchopenfpga/CMakeLists.txt +++ b/libs/libclkarchopenfpga/CMakeLists.txt @@ -20,8 +20,8 @@ set_target_properties(libclkarchopenfpga PROPERTIES PREFIX "") #Avoid extra 'lib #Specify link-time dependancies target_link_libraries(libclkarchopenfpga libopenfpgautil + libarchopenfpga libvtrutil - libarchfpga libpugiutil) #Create the test executable diff --git a/libs/libclkarchopenfpga/src/base/clock_network.cpp b/libs/libclkarchopenfpga/src/base/clock_network.cpp index 3c2915f78..4b80d123f 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.cpp +++ b/libs/libclkarchopenfpga/src/base/clock_network.cpp @@ -93,7 +93,7 @@ vtr::Point ClockNetwork::spine_switch_point(const ClockSpineId& spine_id, c return spine_switch_coords_[spine_id][size_t(switch_point_id)]; } -bool ClockNetwork::find_spine(const std::string& name) const { +ClockSpineId ClockNetwork::find_spine(const std::string& name) const { auto result = spine_name2id_map_.find(name); if (result == spine_name2id_map_.end()) { return ClockSpineId::INVALID(); @@ -128,7 +128,7 @@ void ClockNetwork::reserve_trees(const size_t& num_trees) { tree_top_spines_.reserve(num_trees); } -ClockTreeId ClockNetwork::create_tree(const std::string& name, const size_t& width = 1) { +ClockTreeId ClockNetwork::create_tree(const std::string& name, size_t width) { /* Create a new id */ ClockTreeId tree_id = ClockTreeId(tree_ids_.size()); @@ -208,7 +208,7 @@ void ClockNetwork::set_spine_end_point(const ClockSpineId& spine_id, const vtr:: void ClockNetwork::add_spine_switch_point(const ClockSpineId& spine_id, const ClockSpineId& drive_spine_id, const vtr::Point& coord) { VTR_ASSERT(valid_spine_id(spine_id)); VTR_ASSERT(valid_spine_id(drive_spine_id)); - spine_switch_points_[spine_id].push_back(drive_spine); + spine_switch_points_[spine_id].push_back(drive_spine_id); spine_switch_coords_[spine_id].push_back(coord); /* Do not allow any spine has different parents */ if (spine_parents_[drive_spine_id]) { @@ -225,7 +225,7 @@ void ClockNetwork::add_spine_switch_point(const ClockSpineId& spine_id, const Cl bool ClockNetwork::link() { is_dirty_ = true; - for (ClockTreeId& tree_id : trees()) { + for (ClockTreeId tree_id : trees()) { if (!link_tree(tree_id)) { return false; } @@ -277,7 +277,7 @@ bool ClockNetwork::rec_update_spine_level(const ClockSpineId& spine_id) { bool ClockNetwork::update_tree_depth(const ClockTreeId& tree_id) { size_t depth = 0; - for (ClockSpineId spine_id : tree_spines_[tree_id]) { + for (ClockSpineId spine_id : spines(tree_id)) { depth = std::max(depth, spine_levels_[spine_id]); } tree_depths_[tree_id] = depth; @@ -295,7 +295,7 @@ bool ClockNetwork::valid_spine_id(const ClockSpineId& spine_id) const { return (size_t(spine_id) < spine_ids_.size()) && (spine_id == spine_ids_[spine_id]); } -bool valid_spine_switch_point_id(const ClockSpineId& spine_id, const ClockSwitchPointId& switch_point_id) const { +bool ClockNetwork::valid_spine_switch_point_id(const ClockSpineId& spine_id, const ClockSwitchPointId& switch_point_id) const { if (!valid_spine_id(spine_id)) { return false; } diff --git a/libs/libclkarchopenfpga/src/base/clock_network.h b/libs/libclkarchopenfpga/src/base/clock_network.h index 316815694..4b9b379f5 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.h +++ b/libs/libclkarchopenfpga/src/base/clock_network.h @@ -73,7 +73,7 @@ class ClockNetwork { /* Reserve a number of trees to be memory efficent */ void reserve_trees(const size_t& num_trees); /* Create a new tree, by default the tree can accomodate only 1 clock signal; use width to adjust the size */ - ClockTreeId create_tree(const std::string& name, const size_t& width = 1); + ClockTreeId create_tree(const std::string& name, size_t width = 1); /* Create a new spine, if the spine is already created, return an invalid id */ ClockSpineId create_spine(const std::string& name); /* Try to create a new spine, if the spine is already existing, return the id. If not, create a new spine and return its id */ diff --git a/libs/libclkarchopenfpga/src/io/read_xml_clock_network.cpp b/libs/libclkarchopenfpga/src/io/read_xml_clock_network.cpp index 5f349f39e..bceff737a 100644 --- a/libs/libclkarchopenfpga/src/io/read_xml_clock_network.cpp +++ b/libs/libclkarchopenfpga/src/io/read_xml_clock_network.cpp @@ -167,8 +167,8 @@ ClockNetwork read_xml_clock_network(const char* fname) { for (pugi::xml_node xml_tree : xml_root.children()) { /* Error out if the XML child has an invalid name! */ - if (xml_tree.name() != std::string(XML_CLOCK_NETWORK_NODE_NAME)) { - bad_tag(xml_tree, loc_data, xml_root, {XML_CLOCK_NETWORK_NODE_NAME}); + if (xml_tree.name() != std::string(XML_CLOCK_TREE_NODE_NAME)) { + bad_tag(xml_tree, loc_data, xml_root, {XML_CLOCK_TREE_NODE_NAME}); } read_xml_clock_tree(xml_tree, loc_data, clk_ntwk); } diff --git a/libs/libclkarchopenfpga/src/io/write_xml_clock_network.cpp b/libs/libclkarchopenfpga/src/io/write_xml_clock_network.cpp index cdd58686e..0a8f2191e 100644 --- a/libs/libclkarchopenfpga/src/io/write_xml_clock_network.cpp +++ b/libs/libclkarchopenfpga/src/io/write_xml_clock_network.cpp @@ -28,8 +28,8 @@ static int write_xml_clock_spine_switch_point(std::fstream& fp, const ClockNetwo fp << "<" << XML_CLOCK_SPINE_SWITCH_POINT_NODE_NAME << ""; write_xml_attribute(fp, XML_CLOCK_SPINE_SWITCH_POINT_ATTRIBUTE_TAP, - clk_ntwk.spine_switch_point_tap(spine_id, switch_point_id)); - vtr::Point coord = clk_ntwk.spine_switch_point(spine_id); + clk_ntwk.spine_name(clk_ntwk.spine_switch_point_tap(spine_id, switch_point_id)).c_str()); + vtr::Point coord = clk_ntwk.spine_switch_point(spine_id, switch_point_id); write_xml_attribute(fp, XML_CLOCK_SPINE_SWITCH_POINT_ATTRIBUTE_X, coord.x()); write_xml_attribute(fp, XML_CLOCK_SPINE_SWITCH_POINT_ATTRIBUTE_Y, @@ -47,7 +47,7 @@ static int write_xml_clock_spine(std::fstream& fp, const ClockNetwork& clk_ntwk, fp << "<" << XML_CLOCK_SPINE_NODE_NAME << ""; write_xml_attribute(fp, XML_CLOCK_SPINE_ATTRIBUTE_NAME, - clk_ntwk.spine_name(spine_id)); + clk_ntwk.spine_name(spine_id).c_str()); vtr::Point start_coord = clk_ntwk.spine_start_point(spine_id); write_xml_attribute(fp, XML_CLOCK_SPINE_ATTRIBUTE_START_X, start_coord.x()); diff --git a/libs/libclkarchopenfpga/test/xml_io_clock_network.cpp b/libs/libclkarchopenfpga/test/xml_io_clock_network.cpp index 81da04ea3..9fa98a682 100644 --- a/libs/libclkarchopenfpga/test/xml_io_clock_network.cpp +++ b/libs/libclkarchopenfpga/test/xml_io_clock_network.cpp @@ -16,7 +16,7 @@ int main(int argc, const char** argv) { VTR_ASSERT((2 == argc) || (3 == argc)); /* Parse the circuit library from an XML file */ - const openfpga::ClockNetwork& clk_ntwk = openfpga::read_xml_clock_network(argv[1]); + openfpga::ClockNetwork clk_ntwk = openfpga::read_xml_clock_network(argv[1]); VTR_LOG("Parsed %lu clock tree(s) from XML into clock network.\n", clk_ntwk.trees().size()); From d1133000baa7e7f5f03440e2092a4e1a983b64be Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 22 Feb 2023 21:03:04 -0800 Subject: [PATCH 013/166] [lib] code format --- .../src/base/clock_network.cpp | 69 ++++++++++++------- .../src/base/clock_network.h | 51 +++++++++----- .../src/io/read_xml_clock_network.cpp | 64 ++++++++++------- .../src/io/write_xml_clock_network.cpp | 44 ++++++------ .../test/xml_io_clock_network.cpp | 3 +- 5 files changed, 143 insertions(+), 88 deletions(-) diff --git a/libs/libclkarchopenfpga/src/base/clock_network.cpp b/libs/libclkarchopenfpga/src/base/clock_network.cpp index 4b80d123f..8bf75fbc9 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.cpp +++ b/libs/libclkarchopenfpga/src/base/clock_network.cpp @@ -14,9 +14,7 @@ namespace openfpga { // Begin namespace openfpga /************************************************************************ * Constructors ***********************************************************************/ -ClockNetwork::ClockNetwork() { - is_dirty_ = true; -} +ClockNetwork::ClockNetwork() { is_dirty_ = true; } /************************************************************************ * Public Accessors : aggregates @@ -47,8 +45,9 @@ size_t ClockNetwork::tree_depth(const ClockTreeId& tree_id) const { return tree_depths_[tree_id]; } -std::vector ClockNetwork::spines(const ClockTreeId& tree_id) const { - std::vector ret; +std::vector ClockNetwork::spines( + const ClockTreeId& tree_id) const { + std::vector ret; for (ClockSpineId spine_id : spine_ids_) { if (spine_parent_trees_[spine_id] == tree_id) { ret.push_back(spine_id); @@ -62,17 +61,20 @@ std::string ClockNetwork::spine_name(const ClockSpineId& spine_id) const { return spine_names_[spine_id]; } -vtr::Point ClockNetwork::spine_start_point(const ClockSpineId& spine_id) const { +vtr::Point ClockNetwork::spine_start_point( + const ClockSpineId& spine_id) const { VTR_ASSERT(valid_spine_id(spine_id)); return spine_start_points_[spine_id]; } -vtr::Point ClockNetwork::spine_end_point(const ClockSpineId& spine_id) const { +vtr::Point ClockNetwork::spine_end_point( + const ClockSpineId& spine_id) const { VTR_ASSERT(valid_spine_id(spine_id)); return spine_end_points_[spine_id]; } -std::vector ClockNetwork::spine_switch_points(const ClockSpineId& spine_id) const { +std::vector ClockNetwork::spine_switch_points( + const ClockSpineId& spine_id) const { VTR_ASSERT(valid_spine_id(spine_id)); std::vector ret; ret.reserve(spine_switch_points_[spine_id].size()); @@ -83,12 +85,16 @@ std::vector ClockNetwork::spine_switch_points(const ClockSpi return ret; } -ClockSpineId ClockNetwork::spine_switch_point_tap(const ClockSpineId& spine_id, const ClockSwitchPointId& switch_point_id) const { +ClockSpineId ClockNetwork::spine_switch_point_tap( + const ClockSpineId& spine_id, + const ClockSwitchPointId& switch_point_id) const { VTR_ASSERT(valid_spine_switch_point_id(spine_id, switch_point_id)); return spine_switch_points_[spine_id][size_t(switch_point_id)]; } -vtr::Point ClockNetwork::spine_switch_point(const ClockSpineId& spine_id, const ClockSwitchPointId& switch_point_id) const { +vtr::Point ClockNetwork::spine_switch_point( + const ClockSpineId& spine_id, + const ClockSwitchPointId& switch_point_id) const { VTR_ASSERT(valid_spine_switch_point_id(spine_id, switch_point_id)); return spine_switch_coords_[spine_id][size_t(switch_point_id)]; } @@ -155,8 +161,10 @@ ClockSpineId ClockNetwork::create_spine(const std::string& name) { /* Check if the name is already used or not */ auto result = spine_name2id_map_.find(name); if (result != spine_name2id_map_.end()) { - VTR_LOG_WARN("Unable to create a spine with duplicated name '%s' in clock network\nPlease use the existing spine or rename\n", - name.c_str()); + VTR_LOG_WARN( + "Unable to create a spine with duplicated name '%s' in clock " + "network\nPlease use the existing spine or rename\n", + name.c_str()); return ClockSpineId::INVALID(); } @@ -189,34 +197,40 @@ ClockSpineId ClockNetwork::try_create_spine(const std::string& name) { return spine_id; } -void ClockNetwork::set_spine_parent_tree(const ClockSpineId& spine_id, const ClockTreeId& tree_id) { +void ClockNetwork::set_spine_parent_tree(const ClockSpineId& spine_id, + const ClockTreeId& tree_id) { VTR_ASSERT(valid_spine_id(spine_id)); VTR_ASSERT(valid_tree_id(tree_id)); spine_parent_trees_[spine_id] = tree_id; } -void ClockNetwork::set_spine_start_point(const ClockSpineId& spine_id, const vtr::Point& coord) { +void ClockNetwork::set_spine_start_point(const ClockSpineId& spine_id, + const vtr::Point& coord) { VTR_ASSERT(valid_spine_id(spine_id)); spine_start_points_[spine_id] = coord; } -void ClockNetwork::set_spine_end_point(const ClockSpineId& spine_id, const vtr::Point& coord) { +void ClockNetwork::set_spine_end_point(const ClockSpineId& spine_id, + const vtr::Point& coord) { VTR_ASSERT(valid_spine_id(spine_id)); spine_end_points_[spine_id] = coord; } -void ClockNetwork::add_spine_switch_point(const ClockSpineId& spine_id, const ClockSpineId& drive_spine_id, const vtr::Point& coord) { +void ClockNetwork::add_spine_switch_point(const ClockSpineId& spine_id, + const ClockSpineId& drive_spine_id, + const vtr::Point& coord) { VTR_ASSERT(valid_spine_id(spine_id)); VTR_ASSERT(valid_spine_id(drive_spine_id)); spine_switch_points_[spine_id].push_back(drive_spine_id); spine_switch_coords_[spine_id].push_back(coord); /* Do not allow any spine has different parents */ if (spine_parents_[drive_spine_id]) { - VTR_LOG_ERROR("Detect a spine %s' has two parents '%s' and '%s'. Not allowed in a clock tree!\n", - spine_name(drive_spine_id).c_str(), - spine_name(spine_parents_[drive_spine_id]).c_str(), - spine_name(spine_id).c_str() - ); + VTR_LOG_ERROR( + "Detect a spine %s' has two parents '%s' and '%s'. Not allowed in a " + "clock tree!\n", + spine_name(drive_spine_id).c_str(), + spine_name(spine_parents_[drive_spine_id]).c_str(), + spine_name(spine_id).c_str()); exit(1); } spine_parents_[drive_spine_id] = spine_id; @@ -249,7 +263,8 @@ bool ClockNetwork::link_tree(const ClockTreeId& tree_id) { bool ClockNetwork::link_tree_top_spines(const ClockTreeId& tree_id) { tree_top_spines_[tree_id].clear(); - /* Sort the spines under a tree; assign levels and identify top-level spines */ + /* Sort the spines under a tree; assign levels and identify top-level spines + */ for (ClockSpineId spine_id : spines(tree_id)) { /* Spines that have no parent are the top-level spines*/ if (!spine_parents_[spine_id]) { @@ -288,14 +303,18 @@ bool ClockNetwork::update_tree_depth(const ClockTreeId& tree_id) { * Internal invalidators/validators ***********************************************************************/ bool ClockNetwork::valid_tree_id(const ClockTreeId& tree_id) const { - return (size_t(tree_id) < tree_ids_.size()) && (tree_id == tree_ids_[tree_id]); + return (size_t(tree_id) < tree_ids_.size()) && + (tree_id == tree_ids_[tree_id]); } bool ClockNetwork::valid_spine_id(const ClockSpineId& spine_id) const { - return (size_t(spine_id) < spine_ids_.size()) && (spine_id == spine_ids_[spine_id]); + return (size_t(spine_id) < spine_ids_.size()) && + (spine_id == spine_ids_[spine_id]); } -bool ClockNetwork::valid_spine_switch_point_id(const ClockSpineId& spine_id, const ClockSwitchPointId& switch_point_id) const { +bool ClockNetwork::valid_spine_switch_point_id( + const ClockSpineId& spine_id, + const ClockSwitchPointId& switch_point_id) const { if (!valid_spine_id(spine_id)) { return false; } diff --git a/libs/libclkarchopenfpga/src/base/clock_network.h b/libs/libclkarchopenfpga/src/base/clock_network.h index 4b9b379f5..d54362ced 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.h +++ b/libs/libclkarchopenfpga/src/base/clock_network.h @@ -9,8 +9,8 @@ #include /* Headers from vtrutil library */ -#include "vtr_vector.h" #include "vtr_geometry.h" +#include "vtr_vector.h" /* Headers from openfpgautil library */ #include "clock_network_fwd.h" @@ -38,7 +38,7 @@ namespace openfpga { // Begin namespace openfpga class ClockNetwork { public: /* Types */ typedef vtr::vector::const_iterator - clock_tree_iterator; + clock_tree_iterator; /* Create range */ typedef vtr::Range clock_tree_range; @@ -58,10 +58,16 @@ class ClockNetwork { vtr::Point spine_start_point(const ClockSpineId& spine_id) const; vtr::Point spine_end_point(const ClockSpineId& spine_id) const; /* Return the unique id of switch points under a clock spine*/ - std::vector spine_switch_points(const ClockSpineId& spine_id) const; - ClockSpineId spine_switch_point_tap(const ClockSpineId& spine_id, const ClockSwitchPointId& switch_point_id) const; - vtr::Point spine_switch_point(const ClockSpineId& spine_id, const ClockSwitchPointId& switch_point_id) const; - /* Find a spine with a given name, if not found, return an valid id, otherwise return an invalid one */ + std::vector spine_switch_points( + const ClockSpineId& spine_id) const; + ClockSpineId spine_switch_point_tap( + const ClockSpineId& spine_id, + const ClockSwitchPointId& switch_point_id) const; + vtr::Point spine_switch_point( + const ClockSpineId& spine_id, + const ClockSwitchPointId& switch_point_id) const; + /* Find a spine with a given name, if not found, return an valid id, otherwise + * return an invalid one */ ClockSpineId find_spine(const std::string& name) const; /* Check if there are clock tree */ bool empty() const; @@ -72,18 +78,29 @@ class ClockNetwork { void reserve_spines(const size_t& num_spines); /* Reserve a number of trees to be memory efficent */ void reserve_trees(const size_t& num_trees); - /* Create a new tree, by default the tree can accomodate only 1 clock signal; use width to adjust the size */ + /* Create a new tree, by default the tree can accomodate only 1 clock signal; + * use width to adjust the size */ ClockTreeId create_tree(const std::string& name, size_t width = 1); - /* Create a new spine, if the spine is already created, return an invalid id */ + /* Create a new spine, if the spine is already created, return an invalid id + */ ClockSpineId create_spine(const std::string& name); - /* Try to create a new spine, if the spine is already existing, return the id. If not, create a new spine and return its id */ + /* Try to create a new spine, if the spine is already existing, return the id. + * If not, create a new spine and return its id */ ClockSpineId try_create_spine(const std::string& name); - /* Set the parent tree for a given spine. It is illegal that a spine which does not belong to any tree */ - void set_spine_parent_tree(const ClockSpineId& spine_id, const ClockTreeId& tree_id); - void set_spine_start_point(const ClockSpineId& spine_id, const vtr::Point& coord); - void set_spine_end_point(const ClockSpineId& spine_id, const vtr::Point& coord); - void add_spine_switch_point(const ClockSpineId& spine_id, const ClockSpineId& drive_spine_id, const vtr::Point& coord); - /* Build internal links between clock tree, spines etc. This is also an validator to verify the correctness of the clock network. Must run before using the data! */ + /* Set the parent tree for a given spine. It is illegal that a spine which + * does not belong to any tree */ + void set_spine_parent_tree(const ClockSpineId& spine_id, + const ClockTreeId& tree_id); + void set_spine_start_point(const ClockSpineId& spine_id, + const vtr::Point& coord); + void set_spine_end_point(const ClockSpineId& spine_id, + const vtr::Point& coord); + void add_spine_switch_point(const ClockSpineId& spine_id, + const ClockSpineId& drive_spine_id, + const vtr::Point& coord); + /* Build internal links between clock tree, spines etc. This is also an + * validator to verify the correctness of the clock network. Must run before + * using the data! */ bool link(); public: /* Public invalidators/validators */ @@ -91,7 +108,9 @@ class ClockNetwork { bool valid_tree_id(const ClockTreeId& tree_id) const; /* Show if the tree id is a valid for data queries */ bool valid_spine_id(const ClockSpineId& spine_id) const; - bool valid_spine_switch_point_id(const ClockSpineId& spine_id, const ClockSwitchPointId& switch_point_id) const; + bool valid_spine_switch_point_id( + const ClockSpineId& spine_id, + const ClockSwitchPointId& switch_point_id) const; private: /* Private mutators */ /* Build internal links between spines under a given tree */ diff --git a/libs/libclkarchopenfpga/src/io/read_xml_clock_network.cpp b/libs/libclkarchopenfpga/src/io/read_xml_clock_network.cpp index bceff737a..de50eec94 100644 --- a/libs/libclkarchopenfpga/src/io/read_xml_clock_network.cpp +++ b/libs/libclkarchopenfpga/src/io/read_xml_clock_network.cpp @@ -27,16 +27,18 @@ namespace openfpga { // Begin namespace openfpga /******************************************************************** * Parse XML codes of a to an object of ClockNetwork *******************************************************************/ -static void read_xml_clock_spine_switch_point(pugi::xml_node& xml_switch_point, - const pugiutil::loc_data& loc_data, - ClockNetwork& clk_ntwk, const ClockSpineId& spine_id) { +static void read_xml_clock_spine_switch_point( + pugi::xml_node& xml_switch_point, const pugiutil::loc_data& loc_data, + ClockNetwork& clk_ntwk, const ClockSpineId& spine_id) { if (!clk_ntwk.valid_spine_id(spine_id)) { archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_switch_point), "Invalid id of a clock spine!\n"); } - std::string tap_spine_name = - get_attribute(xml_switch_point, XML_CLOCK_SPINE_SWITCH_POINT_ATTRIBUTE_TAP, loc_data).as_string(); + std::string tap_spine_name = + get_attribute(xml_switch_point, XML_CLOCK_SPINE_SWITCH_POINT_ATTRIBUTE_TAP, + loc_data) + .as_string(); /* Try to find an existing spine, if not, create one */ ClockSpineId tap_spine_id = clk_ntwk.find_spine(tap_spine_name); @@ -49,12 +51,15 @@ static void read_xml_clock_spine_switch_point(pugi::xml_node& xml_switch_point, "Fail to create a clock spine!\n"); } - int tap_x = - get_attribute(xml_switch_point, XML_CLOCK_SPINE_SWITCH_POINT_ATTRIBUTE_X, loc_data).as_int(); - int tap_y = - get_attribute(xml_switch_point, XML_CLOCK_SPINE_SWITCH_POINT_ATTRIBUTE_Y, loc_data).as_int(); + int tap_x = get_attribute(xml_switch_point, + XML_CLOCK_SPINE_SWITCH_POINT_ATTRIBUTE_X, loc_data) + .as_int(); + int tap_y = get_attribute(xml_switch_point, + XML_CLOCK_SPINE_SWITCH_POINT_ATTRIBUTE_Y, loc_data) + .as_int(); - clk_ntwk.add_spine_switch_point(spine_id, tap_spine_id, vtr::Point(tap_x, tap_y)); + clk_ntwk.add_spine_switch_point(spine_id, tap_spine_id, + vtr::Point(tap_x, tap_y)); } /******************************************************************** @@ -62,14 +67,16 @@ static void read_xml_clock_spine_switch_point(pugi::xml_node& xml_switch_point, *******************************************************************/ static void read_xml_clock_spine(pugi::xml_node& xml_spine, const pugiutil::loc_data& loc_data, - ClockNetwork& clk_ntwk, const ClockTreeId& tree_id) { + ClockNetwork& clk_ntwk, + const ClockTreeId& tree_id) { if (!clk_ntwk.valid_tree_id(tree_id)) { archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_spine), "Invalid id of a clock tree!\n"); } - std::string clk_spine_name = - get_attribute(xml_spine, XML_CLOCK_SPINE_ATTRIBUTE_NAME, loc_data).as_string(); + std::string clk_spine_name = + get_attribute(xml_spine, XML_CLOCK_SPINE_ATTRIBUTE_NAME, loc_data) + .as_string(); /* Try to find an existing spine, if not, create one */ ClockSpineId spine_id = clk_ntwk.find_spine(clk_spine_name); @@ -85,23 +92,30 @@ static void read_xml_clock_spine(pugi::xml_node& xml_spine, clk_ntwk.set_spine_parent_tree(spine_id, tree_id); int start_x = - get_attribute(xml_spine, XML_CLOCK_SPINE_ATTRIBUTE_START_X, loc_data).as_int(); + get_attribute(xml_spine, XML_CLOCK_SPINE_ATTRIBUTE_START_X, loc_data) + .as_int(); int start_y = - get_attribute(xml_spine, XML_CLOCK_SPINE_ATTRIBUTE_START_Y, loc_data).as_int(); + get_attribute(xml_spine, XML_CLOCK_SPINE_ATTRIBUTE_START_Y, loc_data) + .as_int(); clk_ntwk.set_spine_start_point(spine_id, vtr::Point(start_x, start_y)); int end_x = - get_attribute(xml_spine, XML_CLOCK_SPINE_ATTRIBUTE_END_X, loc_data).as_int(); + get_attribute(xml_spine, XML_CLOCK_SPINE_ATTRIBUTE_END_X, loc_data) + .as_int(); int end_y = - get_attribute(xml_spine, XML_CLOCK_SPINE_ATTRIBUTE_END_Y, loc_data).as_int(); + get_attribute(xml_spine, XML_CLOCK_SPINE_ATTRIBUTE_END_Y, loc_data) + .as_int(); clk_ntwk.set_spine_end_point(spine_id, vtr::Point(end_x, end_y)); for (pugi::xml_node xml_switch_point : xml_spine.children()) { /* Error out if the XML child has an invalid name! */ - if (xml_switch_point.name() != std::string(XML_CLOCK_SPINE_SWITCH_POINT_NODE_NAME)) { - bad_tag(xml_switch_point, loc_data, xml_spine, {XML_CLOCK_SPINE_SWITCH_POINT_NODE_NAME}); + if (xml_switch_point.name() != + std::string(XML_CLOCK_SPINE_SWITCH_POINT_NODE_NAME)) { + bad_tag(xml_switch_point, loc_data, xml_spine, + {XML_CLOCK_SPINE_SWITCH_POINT_NODE_NAME}); } - read_xml_clock_spine_switch_point(xml_switch_point, loc_data, clk_ntwk, spine_id); + read_xml_clock_spine_switch_point(xml_switch_point, loc_data, clk_ntwk, + spine_id); } } @@ -111,10 +125,12 @@ static void read_xml_clock_spine(pugi::xml_node& xml_spine, static void read_xml_clock_tree(pugi::xml_node& xml_clk_tree, const pugiutil::loc_data& loc_data, ClockNetwork& clk_ntwk) { - std::string clk_tree_name = - get_attribute(xml_clk_tree, XML_CLOCK_TREE_ATTRIBUTE_NAME, loc_data).as_string(); - int clk_tree_width = - get_attribute(xml_clk_tree, XML_CLOCK_TREE_ATTRIBUTE_WIDTH, loc_data).as_int(); + std::string clk_tree_name = + get_attribute(xml_clk_tree, XML_CLOCK_TREE_ATTRIBUTE_NAME, loc_data) + .as_string(); + int clk_tree_width = + get_attribute(xml_clk_tree, XML_CLOCK_TREE_ATTRIBUTE_WIDTH, loc_data) + .as_int(); /* Create a new tree in the storage */ ClockTreeId tree_id = clk_ntwk.create_tree(clk_tree_name, clk_tree_width); diff --git a/libs/libclkarchopenfpga/src/io/write_xml_clock_network.cpp b/libs/libclkarchopenfpga/src/io/write_xml_clock_network.cpp index 0a8f2191e..bf733ab0c 100644 --- a/libs/libclkarchopenfpga/src/io/write_xml_clock_network.cpp +++ b/libs/libclkarchopenfpga/src/io/write_xml_clock_network.cpp @@ -1,5 +1,6 @@ /******************************************************************** - * This file includes functions that outputs a clock network object to XML format + * This file includes functions that outputs a clock network object to XML + *format *******************************************************************/ /* Headers from system goes first */ #include @@ -22,18 +23,21 @@ namespace openfpga { // Begin namespace openfpga -static int write_xml_clock_spine_switch_point(std::fstream& fp, const ClockNetwork& clk_ntwk, - const ClockSpineId& spine_id, const ClockSwitchPointId& switch_point_id) { +static int write_xml_clock_spine_switch_point( + std::fstream& fp, const ClockNetwork& clk_ntwk, const ClockSpineId& spine_id, + const ClockSwitchPointId& switch_point_id) { openfpga::write_tab_to_file(fp, 3); fp << "<" << XML_CLOCK_SPINE_SWITCH_POINT_NODE_NAME << ""; - write_xml_attribute(fp, XML_CLOCK_SPINE_SWITCH_POINT_ATTRIBUTE_TAP, - clk_ntwk.spine_name(clk_ntwk.spine_switch_point_tap(spine_id, switch_point_id)).c_str()); - vtr::Point coord = clk_ntwk.spine_switch_point(spine_id, switch_point_id); - write_xml_attribute(fp, XML_CLOCK_SPINE_SWITCH_POINT_ATTRIBUTE_X, - coord.x()); - write_xml_attribute(fp, XML_CLOCK_SPINE_SWITCH_POINT_ATTRIBUTE_Y, - coord.y()); + write_xml_attribute( + fp, XML_CLOCK_SPINE_SWITCH_POINT_ATTRIBUTE_TAP, + clk_ntwk + .spine_name(clk_ntwk.spine_switch_point_tap(spine_id, switch_point_id)) + .c_str()); + vtr::Point coord = + clk_ntwk.spine_switch_point(spine_id, switch_point_id); + write_xml_attribute(fp, XML_CLOCK_SPINE_SWITCH_POINT_ATTRIBUTE_X, coord.x()); + write_xml_attribute(fp, XML_CLOCK_SPINE_SWITCH_POINT_ATTRIBUTE_Y, coord.y()); fp << "/>" << "\n"; @@ -49,20 +53,17 @@ static int write_xml_clock_spine(std::fstream& fp, const ClockNetwork& clk_ntwk, write_xml_attribute(fp, XML_CLOCK_SPINE_ATTRIBUTE_NAME, clk_ntwk.spine_name(spine_id).c_str()); vtr::Point start_coord = clk_ntwk.spine_start_point(spine_id); - write_xml_attribute(fp, XML_CLOCK_SPINE_ATTRIBUTE_START_X, - start_coord.x()); - write_xml_attribute(fp, XML_CLOCK_SPINE_ATTRIBUTE_START_Y, - start_coord.y()); + write_xml_attribute(fp, XML_CLOCK_SPINE_ATTRIBUTE_START_X, start_coord.x()); + write_xml_attribute(fp, XML_CLOCK_SPINE_ATTRIBUTE_START_Y, start_coord.y()); vtr::Point end_coord = clk_ntwk.spine_end_point(spine_id); - write_xml_attribute(fp, XML_CLOCK_SPINE_ATTRIBUTE_END_X, - end_coord.x()); - write_xml_attribute(fp, XML_CLOCK_SPINE_ATTRIBUTE_END_Y, - end_coord.y()); + write_xml_attribute(fp, XML_CLOCK_SPINE_ATTRIBUTE_END_X, end_coord.x()); + write_xml_attribute(fp, XML_CLOCK_SPINE_ATTRIBUTE_END_Y, end_coord.y()); fp << ">" << "\n"; - for (const ClockSwitchPointId& switch_point_id : clk_ntwk.spine_switch_points(spine_id)) { + for (const ClockSwitchPointId& switch_point_id : + clk_ntwk.spine_switch_points(spine_id)) { write_xml_clock_spine_switch_point(fp, clk_ntwk, spine_id, switch_point_id); } @@ -95,9 +96,8 @@ static int write_xml_clock_tree(std::fstream& fp, const ClockNetwork& clk_ntwk, return 1; } - write_xml_attribute( - fp, XML_CLOCK_TREE_ATTRIBUTE_NAME, - clk_ntwk.tree_name(tree_id).c_str()); + write_xml_attribute(fp, XML_CLOCK_TREE_ATTRIBUTE_NAME, + clk_ntwk.tree_name(tree_id).c_str()); write_xml_attribute(fp, XML_CLOCK_TREE_ATTRIBUTE_WIDTH, clk_ntwk.tree_width(tree_id)); fp << ">" diff --git a/libs/libclkarchopenfpga/test/xml_io_clock_network.cpp b/libs/libclkarchopenfpga/test/xml_io_clock_network.cpp index 9fa98a682..928fe4043 100644 --- a/libs/libclkarchopenfpga/test/xml_io_clock_network.cpp +++ b/libs/libclkarchopenfpga/test/xml_io_clock_network.cpp @@ -27,7 +27,8 @@ int main(int argc, const char** argv) { } VTR_ASSERT(clk_ntwk.is_valid()); for (auto tree_id : clk_ntwk.trees()) { - VTR_LOG("Max. depth of the clock tree '%lu' is %d", size_t(tree_id), clk_ntwk.tree_depth(tree_id)); + VTR_LOG("Max. depth of the clock tree '%lu' is %d", size_t(tree_id), + clk_ntwk.tree_depth(tree_id)); } /* Output the bus group to an XML file From a9d5e4dfbdba5a46a5faa475570535e335cdf5b1 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 22 Feb 2023 21:18:00 -0800 Subject: [PATCH 014/166] [lib] update example clock arch xml --- libs/libclkarchopenfpga/arch/example.xml | 26 ++++++++++++------------ 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/libs/libclkarchopenfpga/arch/example.xml b/libs/libclkarchopenfpga/arch/example.xml index 452e6942b..5ff2c975c 100644 --- a/libs/libclkarchopenfpga/arch/example.xml +++ b/libs/libclkarchopenfpga/arch/example.xml @@ -1,19 +1,19 @@ - - - + + + - - - + + + - - - + + + - - - - + + + + From 40f6b5a3fefadca424c0546c1ba741f6bec0482e Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 22 Feb 2023 21:23:08 -0800 Subject: [PATCH 015/166] [lib] fixed a few bugs --- libs/libclkarchopenfpga/arch/example.xml | 2 +- libs/libclkarchopenfpga/src/base/clock_network.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/libclkarchopenfpga/arch/example.xml b/libs/libclkarchopenfpga/arch/example.xml index 5ff2c975c..f3edac222 100644 --- a/libs/libclkarchopenfpga/arch/example.xml +++ b/libs/libclkarchopenfpga/arch/example.xml @@ -9,7 +9,7 @@ - + diff --git a/libs/libclkarchopenfpga/src/base/clock_network.cpp b/libs/libclkarchopenfpga/src/base/clock_network.cpp index 8bf75fbc9..39bd5b52b 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.cpp +++ b/libs/libclkarchopenfpga/src/base/clock_network.cpp @@ -170,7 +170,6 @@ ClockSpineId ClockNetwork::create_spine(const std::string& name) { /* Create a new id */ ClockSpineId spine_id = ClockSpineId(spine_ids_.size()); - VTR_ASSERT(valid_spine_id(spine_id)); spine_ids_.push_back(spine_id); spine_names_.push_back(name); @@ -184,6 +183,7 @@ ClockSpineId ClockNetwork::create_spine(const std::string& name) { spine_parent_trees_.emplace_back(); /* Register to the lookup */ + VTR_ASSERT(valid_spine_id(spine_id)); spine_name2id_map_[name] = spine_id; return spine_id; From 65b27a33775c4d0bc6cbc1fb6fba41eeb0d123a2 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 22 Feb 2023 21:29:18 -0800 Subject: [PATCH 016/166] [lib] fixed a few bugs --- libs/libclkarchopenfpga/arch/example.xml | 3 ++- libs/libclkarchopenfpga/src/base/clock_network.cpp | 2 +- libs/libclkarchopenfpga/test/xml_io_clock_network.cpp | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/libs/libclkarchopenfpga/arch/example.xml b/libs/libclkarchopenfpga/arch/example.xml index f3edac222..e5ed17f98 100644 --- a/libs/libclkarchopenfpga/arch/example.xml +++ b/libs/libclkarchopenfpga/arch/example.xml @@ -1,7 +1,8 @@ - + + diff --git a/libs/libclkarchopenfpga/src/base/clock_network.cpp b/libs/libclkarchopenfpga/src/base/clock_network.cpp index 39bd5b52b..bffc2a2a0 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.cpp +++ b/libs/libclkarchopenfpga/src/base/clock_network.cpp @@ -42,7 +42,7 @@ size_t ClockNetwork::tree_depth(const ClockTreeId& tree_id) const { VTR_LOG_ERROR("Unable to identify tree depth when data is still dirty!\n"); exit(1); } - return tree_depths_[tree_id]; + return tree_depths_[tree_id] + 1; } std::vector ClockNetwork::spines( diff --git a/libs/libclkarchopenfpga/test/xml_io_clock_network.cpp b/libs/libclkarchopenfpga/test/xml_io_clock_network.cpp index 928fe4043..7a3708c67 100644 --- a/libs/libclkarchopenfpga/test/xml_io_clock_network.cpp +++ b/libs/libclkarchopenfpga/test/xml_io_clock_network.cpp @@ -27,7 +27,7 @@ int main(int argc, const char** argv) { } VTR_ASSERT(clk_ntwk.is_valid()); for (auto tree_id : clk_ntwk.trees()) { - VTR_LOG("Max. depth of the clock tree '%lu' is %d", size_t(tree_id), + VTR_LOG("Max. depth of the clock tree '%lu' is %d\n", size_t(tree_id), clk_ntwk.tree_depth(tree_id)); } From e175472a076153d761c97a2be136cbebe625fc3c Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 22 Feb 2023 21:58:25 -0800 Subject: [PATCH 017/166] [core] adding new commands --- openfpga/CMakeLists.txt | 1 + openfpga/src/base/openfpga_context.h | 8 ++ .../src/base/openfpga_read_arch_template.h | 59 ++++++++++++++ .../base/openfpga_setup_command_template.h | 80 +++++++++++++++++++ 4 files changed, 148 insertions(+) diff --git a/openfpga/CMakeLists.txt b/openfpga/CMakeLists.txt index 5ee3d079d..31a4e37b9 100644 --- a/openfpga/CMakeLists.txt +++ b/openfpga/CMakeLists.txt @@ -31,6 +31,7 @@ set_target_properties(libopenfpga PROPERTIES PREFIX "") #Avoid extra 'lib' prefi #Specify link-time dependancies target_link_libraries(libopenfpga + libclkarchopenfpga libarchopenfpga libopenfpgashell libopenfpgautil diff --git a/openfpga/src/base/openfpga_context.h b/openfpga/src/base/openfpga_context.h index bf247d950..25214254f 100644 --- a/openfpga/src/base/openfpga_context.h +++ b/openfpga/src/base/openfpga_context.h @@ -25,6 +25,7 @@ #include "vpr_netlist_annotation.h" #include "vpr_placement_annotation.h" #include "vpr_routing_annotation.h" +#include "clock_network.h" /******************************************************************** * This file includes the declaration of the date structure @@ -61,6 +62,9 @@ class OpenfpgaContext : public Context { const openfpga::BitstreamSetting& bitstream_setting() const { return bitstream_setting_; } + const openfpga::ClockNetwork& clock_arch() const { + return clock_arch_; + } const openfpga::VprDeviceAnnotation& vpr_device_annotation() const { return vpr_device_annotation_; } @@ -116,6 +120,9 @@ class OpenfpgaContext : public Context { openfpga::BitstreamSetting& mutable_bitstream_setting() { return bitstream_setting_; } + openfpga::ClockNetwork& mutable_clock_arch() { + return clock_arch_; + } openfpga::VprDeviceAnnotation& mutable_vpr_device_annotation() { return vpr_device_annotation_; } @@ -165,6 +172,7 @@ class OpenfpgaContext : public Context { openfpga::Arch arch_; openfpga::SimulationSetting sim_setting_; openfpga::BitstreamSetting bitstream_setting_; + openfpga::ClockNetwork clock_arch_; /* Annotation to pb_type of VPR */ openfpga::VprDeviceAnnotation vpr_device_annotation_; diff --git a/openfpga/src/base/openfpga_read_arch_template.h b/openfpga/src/base/openfpga_read_arch_template.h index d80ac6f84..9d03efda6 100644 --- a/openfpga/src/base/openfpga_read_arch_template.h +++ b/openfpga/src/base/openfpga_read_arch_template.h @@ -14,6 +14,8 @@ #include "read_xml_openfpga_arch.h" #include "vtr_log.h" #include "write_xml_openfpga_arch.h" +#include "read_xml_clock_network.h" +#include "write_xml_clock_network.h" /* begin namespace openfpga */ namespace openfpga { @@ -209,6 +211,63 @@ int write_bitstream_setting_template(const T& openfpga_context, return CMD_EXEC_SUCCESS; } +/******************************************************************** + * Top-level function to read an OpenFPGA bitstream setting file + * we use the APIs from the libarchopenfpga library + * + * The command will accept an option '--file' which is the bitstream setting + * file provided by users + *******************************************************************/ +template +int read_openfpga_clock_arch_template(T& openfpga_context, const Command& cmd, + const CommandContext& cmd_context) { + /* Check the option '--file' is enabled or not + * Actually, it must be enabled as the shell interface will check + * before reaching this fuction + */ + CommandOptionId opt_file = cmd.option("file"); + VTR_ASSERT(true == cmd_context.option_enable(cmd, opt_file)); + VTR_ASSERT(false == cmd_context.option_value(cmd, opt_file).empty()); + + std::string arch_file_name = cmd_context.option_value(cmd, opt_file); + + VTR_LOG("Reading XML clock architecture '%s'...\n", arch_file_name.c_str()); + openfpga_context.mutable_clock_arch() = + read_xml_clock_network(arch_file_name.c_str()); + + /* TODO: should identify the error code from internal function execution */ + return CMD_EXEC_SUCCESS; +} + +/******************************************************************** + * A function to write an OpenFPGA bitstream setting file + * we use the APIs from the libarchopenfpga library + * + * The command will accept an option '--file' which is the simulation setting + * file provided by users + *******************************************************************/ +template +int write_openfpga_clock_arch_template(const T& openfpga_context, + const Command& cmd, + const CommandContext& cmd_context) { + /* Check the option '--file' is enabled or not + * Actually, it must be enabled as the shell interface will check + * before reaching this fuction + */ + CommandOptionId opt_file = cmd.option("file"); + VTR_ASSERT(true == cmd_context.option_enable(cmd, opt_file)); + VTR_ASSERT(false == cmd_context.option_value(cmd, opt_file).empty()); + + std::string arch_file_name = cmd_context.option_value(cmd, opt_file); + + VTR_LOG("Writing XML clock architecture to '%s'...\n", arch_file_name.c_str()); + write_xml_clock_network(arch_file_name.c_str(), + openfpga_context.clock_arch()); + + /* TODO: should identify the error code from internal function execution */ + return CMD_EXEC_SUCCESS; +} + } /* end namespace openfpga */ #endif diff --git a/openfpga/src/base/openfpga_setup_command_template.h b/openfpga/src/base/openfpga_setup_command_template.h index d7ad1a654..3dbc3cde3 100644 --- a/openfpga/src/base/openfpga_setup_command_template.h +++ b/openfpga/src/base/openfpga_setup_command_template.h @@ -570,6 +570,65 @@ ShellCommandId add_pcf2place_command_template( return shell_cmd_id; } +/******************************************************************** + * - Add a command to Shell environment: read_openfpga_clock_arch + * - Add associated options + * - Add command dependency + *******************************************************************/ +template +ShellCommandId add_read_openfpga_clock_arch_command_template( + openfpga::Shell& shell, const ShellCommandClassId& cmd_class_id, + const std::vector& dependent_cmds, const bool& hidden) { + Command shell_cmd("read_openfpga_clock_arch"); + + /* Add an option '--file' in short '-f'*/ + CommandOptionId opt_file = shell_cmd.add_option( + "file", true, "file path to the clock architecture XML"); + shell_cmd.set_option_short_name(opt_file, "f"); + shell_cmd.set_option_require_value(opt_file, openfpga::OPT_STRING); + + /* Add command 'read_openfpga_clock_arch' to the Shell */ + ShellCommandId shell_cmd_id = shell.add_command( + shell_cmd, "read OpenFPGA clock architecture file", hidden); + shell.set_command_class(shell_cmd_id, cmd_class_id); + shell.set_command_execute_function(shell_cmd_id, + read_openfpga_clock_arch_template); + /* Add command dependency to the Shell */ + shell.set_command_dependency(shell_cmd_id, dependent_cmds); + + return shell_cmd_id; +} + +/******************************************************************** + * - Add a command to Shell environment: write_openfpga_clock_arch + * - Add associated options + * - Add command dependency + *******************************************************************/ +template +ShellCommandId add_write_openfpga_clock_arch_command_template( + openfpga::Shell& shell, const ShellCommandClassId& cmd_class_id, + const std::vector& dependent_cmds, const bool& hidden) { + Command shell_cmd("write_openfpga_clock_arch"); + /* Add an option '--file' in short '-f'*/ + CommandOptionId opt_file = shell_cmd.add_option( + "file", true, "file path to the clock architecture XML"); + shell_cmd.set_option_short_name(opt_file, "f"); + shell_cmd.set_option_require_value(opt_file, openfpga::OPT_STRING); + + /* Add command 'write_openfpga_clock_arch' to the Shell */ + ShellCommandId shell_cmd_id = shell.add_command( + shell_cmd, "write OpenFPGA clock architecture file", hidden); + shell.set_command_class(shell_cmd_id, cmd_class_id); + shell.set_command_const_execute_function(shell_cmd_id, + write_openfpga_clock_arch_template); + + /* Add command dependency to the Shell */ + shell.set_command_dependency(shell_cmd_id, dependent_cmds); + + return shell_cmd_id; +} + + template void add_setup_command_templates(openfpga::Shell& shell, const bool& hidden = false) { @@ -636,6 +695,27 @@ void add_setup_command_templates(openfpga::Shell& shell, shell, openfpga_setup_cmd_class, write_bitstream_setting_dependent_cmds, hidden); + /******************************** + * Command 'read_openfpga_clock_arch' + */ + std::vector read_openfpga_clock_arch_dependent_cmds; + read_openfpga_clock_arch_dependent_cmds.push_back(vpr_cmd_id); + read_openfpga_clock_arch_dependent_cmds.push_back(read_arch_cmd_id); + ShellCommandId read_openfpga_clock_arch_cmd_id = + add_read_openfpga_clock_arch_command_template( + shell, openfpga_setup_cmd_class, read_openfpga_clock_arch_dependent_cmds, hidden); + + /******************************** + * Command 'write_openfpga_clock_arch' + */ + /* The 'write_openfpga_clock_arch' command should NOT be executed + * before 'read_openfpga_clock_arch' */ + std::vector write_openfpga_clock_arch_dependent_cmds( + 1, read_openfpga_clock_arch_cmd_id); + add_write_openfpga_clock_arch_command_template( + shell, openfpga_setup_cmd_class, write_openfpga_clock_arch_dependent_cmds, + hidden); + /******************************** * Command 'link_openfpga_arch' */ From e1dab3d2279103988fb225bb13c5811966b199ea Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 22 Feb 2023 22:01:24 -0800 Subject: [PATCH 018/166] [code] format --- openfpga/src/base/openfpga_context.h | 10 +++------- openfpga/src/base/openfpga_read_arch_template.h | 7 ++++--- openfpga/src/base/openfpga_setup_command_template.h | 8 ++++---- 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/openfpga/src/base/openfpga_context.h b/openfpga/src/base/openfpga_context.h index 25214254f..5c38cc0b8 100644 --- a/openfpga/src/base/openfpga_context.h +++ b/openfpga/src/base/openfpga_context.h @@ -5,6 +5,7 @@ #include "bitstream_manager.h" #include "bitstream_setting.h" +#include "clock_network.h" #include "decoder_library.h" #include "device_rr_gsb.h" #include "fabric_bitstream.h" @@ -25,7 +26,6 @@ #include "vpr_netlist_annotation.h" #include "vpr_placement_annotation.h" #include "vpr_routing_annotation.h" -#include "clock_network.h" /******************************************************************** * This file includes the declaration of the date structure @@ -62,9 +62,7 @@ class OpenfpgaContext : public Context { const openfpga::BitstreamSetting& bitstream_setting() const { return bitstream_setting_; } - const openfpga::ClockNetwork& clock_arch() const { - return clock_arch_; - } + const openfpga::ClockNetwork& clock_arch() const { return clock_arch_; } const openfpga::VprDeviceAnnotation& vpr_device_annotation() const { return vpr_device_annotation_; } @@ -120,9 +118,7 @@ class OpenfpgaContext : public Context { openfpga::BitstreamSetting& mutable_bitstream_setting() { return bitstream_setting_; } - openfpga::ClockNetwork& mutable_clock_arch() { - return clock_arch_; - } + openfpga::ClockNetwork& mutable_clock_arch() { return clock_arch_; } openfpga::VprDeviceAnnotation& mutable_vpr_device_annotation() { return vpr_device_annotation_; } diff --git a/openfpga/src/base/openfpga_read_arch_template.h b/openfpga/src/base/openfpga_read_arch_template.h index 9d03efda6..3129f0a92 100644 --- a/openfpga/src/base/openfpga_read_arch_template.h +++ b/openfpga/src/base/openfpga_read_arch_template.h @@ -11,11 +11,11 @@ #include "command_context.h" #include "command_exit_codes.h" #include "globals.h" +#include "read_xml_clock_network.h" #include "read_xml_openfpga_arch.h" #include "vtr_log.h" -#include "write_xml_openfpga_arch.h" -#include "read_xml_clock_network.h" #include "write_xml_clock_network.h" +#include "write_xml_openfpga_arch.h" /* begin namespace openfpga */ namespace openfpga { @@ -260,7 +260,8 @@ int write_openfpga_clock_arch_template(const T& openfpga_context, std::string arch_file_name = cmd_context.option_value(cmd, opt_file); - VTR_LOG("Writing XML clock architecture to '%s'...\n", arch_file_name.c_str()); + VTR_LOG("Writing XML clock architecture to '%s'...\n", + arch_file_name.c_str()); write_xml_clock_network(arch_file_name.c_str(), openfpga_context.clock_arch()); diff --git a/openfpga/src/base/openfpga_setup_command_template.h b/openfpga/src/base/openfpga_setup_command_template.h index 3dbc3cde3..0d6d675fc 100644 --- a/openfpga/src/base/openfpga_setup_command_template.h +++ b/openfpga/src/base/openfpga_setup_command_template.h @@ -619,8 +619,8 @@ ShellCommandId add_write_openfpga_clock_arch_command_template( ShellCommandId shell_cmd_id = shell.add_command( shell_cmd, "write OpenFPGA clock architecture file", hidden); shell.set_command_class(shell_cmd_id, cmd_class_id); - shell.set_command_const_execute_function(shell_cmd_id, - write_openfpga_clock_arch_template); + shell.set_command_const_execute_function( + shell_cmd_id, write_openfpga_clock_arch_template); /* Add command dependency to the Shell */ shell.set_command_dependency(shell_cmd_id, dependent_cmds); @@ -628,7 +628,6 @@ ShellCommandId add_write_openfpga_clock_arch_command_template( return shell_cmd_id; } - template void add_setup_command_templates(openfpga::Shell& shell, const bool& hidden = false) { @@ -703,7 +702,8 @@ void add_setup_command_templates(openfpga::Shell& shell, read_openfpga_clock_arch_dependent_cmds.push_back(read_arch_cmd_id); ShellCommandId read_openfpga_clock_arch_cmd_id = add_read_openfpga_clock_arch_command_template( - shell, openfpga_setup_cmd_class, read_openfpga_clock_arch_dependent_cmds, hidden); + shell, openfpga_setup_cmd_class, read_openfpga_clock_arch_dependent_cmds, + hidden); /******************************** * Command 'write_openfpga_clock_arch' From b78ca69fe588273abaebf7a0485bc36de3d2fbfd Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 22 Feb 2023 22:29:16 -0800 Subject: [PATCH 019/166] [core] enable clock arch link --- openfpga/src/base/openfpga_read_arch_template.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openfpga/src/base/openfpga_read_arch_template.h b/openfpga/src/base/openfpga_read_arch_template.h index 3129f0a92..9003642ba 100644 --- a/openfpga/src/base/openfpga_read_arch_template.h +++ b/openfpga/src/base/openfpga_read_arch_template.h @@ -234,6 +234,8 @@ int read_openfpga_clock_arch_template(T& openfpga_context, const Command& cmd, VTR_LOG("Reading XML clock architecture '%s'...\n", arch_file_name.c_str()); openfpga_context.mutable_clock_arch() = read_xml_clock_network(arch_file_name.c_str()); + /* Build internal links */ + openfpga_context.mutable_clock_arch().link(); /* TODO: should identify the error code from internal function execution */ return CMD_EXEC_SUCCESS; From 786b458a27da2e315e9a7dd412a89bdac3a0a8f9 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 23 Feb 2023 13:30:18 -0800 Subject: [PATCH 020/166] [core] adding new command 'append_clock_rr_graph' --- .../src/base/openfpga_link_arch_template.h | 20 ++++++++++ .../base/openfpga_setup_command_template.h | 38 +++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/openfpga/src/base/openfpga_link_arch_template.h b/openfpga/src/base/openfpga_link_arch_template.h index 58a751338..aa557b72e 100644 --- a/openfpga/src/base/openfpga_link_arch_template.h +++ b/openfpga/src/base/openfpga_link_arch_template.h @@ -182,6 +182,26 @@ int link_arch_template(T& openfpga_ctx, const Command& cmd, return CMD_EXEC_SUCCESS; } +/******************************************************************** + * Top-level function to append a clock network to VPR's routing resource graph, including: + * - Routing tracks dedicated to clock network + * - Programmable switches to enable reconfigurability of clock network + * - + *******************************************************************/ +template +int append_clock_rr_graph_template(T& openfpga_ctx, const Command& cmd, + const CommandContext& cmd_context) { + vtr::ScopedStartFinishTimer timer( + "Append clock network to routing resource graph"); + + CommandOptionId opt_verbose = cmd.option("verbose"); + + /* TODO */ + + return CMD_EXEC_SUCCESS; +} + + } /* end namespace openfpga */ #endif diff --git a/openfpga/src/base/openfpga_setup_command_template.h b/openfpga/src/base/openfpga_setup_command_template.h index 0d6d675fc..9a5ca2c63 100644 --- a/openfpga/src/base/openfpga_setup_command_template.h +++ b/openfpga/src/base/openfpga_setup_command_template.h @@ -628,6 +628,34 @@ ShellCommandId add_write_openfpga_clock_arch_command_template( return shell_cmd_id; } +/******************************************************************** + * - Add a command to Shell environment: append_clock_rr_graph + * - Add associated options + * - Add command dependency + *******************************************************************/ +template +ShellCommandId add_append_clock_rr_graph_command_template( + openfpga::Shell& shell, const ShellCommandClassId& cmd_class_id, + const std::vector& dependent_cmds, const bool& hidden) { + Command shell_cmd("append_clock_rr_graph"); + + /* Add an option '--verbose' */ + shell_cmd.add_option("verbose", false, "Show verbose outputs"); + + /* Add command 'pb_pin_fixup' to the Shell */ + ShellCommandId shell_cmd_id = shell.add_command( + shell_cmd, + "Append clock network to the routing resource graph built by VPR.", + hidden); + shell.set_command_class(shell_cmd_id, cmd_class_id); + shell.set_command_execute_function(shell_cmd_id, append_clock_rr_graph_template); + + /* Add command dependency to the Shell */ + shell.set_command_dependency(shell_cmd_id, dependent_cmds); + + return shell_cmd_id; +} + template void add_setup_command_templates(openfpga::Shell& shell, const bool& hidden = false) { @@ -729,6 +757,16 @@ void add_setup_command_templates(openfpga::Shell& shell, ShellCommandId link_arch_cmd_id = add_link_arch_command_template( shell, openfpga_setup_cmd_class, link_arch_dependent_cmds, hidden); + /******************************** + * Command 'append_clock_rr_graph' + */ + /* The 'append_clock_rr_graph' command should NOT be executed before + * 'read_openfpga_clock_arch' */ + std::vector append_clock_rr_graph_dependent_cmds; + append_clock_rr_graph_dependent_cmds.push_back(read_openfpga_clock_arch_cmd_id); + add_append_clock_rr_graph_command_template(shell, openfpga_setup_cmd_class, + append_clock_rr_graph_dependent_cmds, hidden); + /******************************** * Command 'write_gsb' */ From aa55c692d7d6d4d160c566737dd11884706f0f3d Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 23 Feb 2023 18:04:07 -0800 Subject: [PATCH 021/166] [core] starting developing core function for clock rr_graph build-up --- .../src/annotation/append_clock_rr_graph.cpp | 21 ++++++++++++++++++ .../src/annotation/append_clock_rr_graph.h | 22 +++++++++++++++++++ .../src/base/openfpga_link_arch_template.h | 7 +++--- 3 files changed, 46 insertions(+), 4 deletions(-) create mode 100644 openfpga/src/annotation/append_clock_rr_graph.cpp create mode 100644 openfpga/src/annotation/append_clock_rr_graph.h diff --git a/openfpga/src/annotation/append_clock_rr_graph.cpp b/openfpga/src/annotation/append_clock_rr_graph.cpp new file mode 100644 index 000000000..5b5b5f561 --- /dev/null +++ b/openfpga/src/annotation/append_clock_rr_graph.cpp @@ -0,0 +1,21 @@ +#include "annotate_clock_rr_graph.h" +#include "vtr_assert.h" +#include "vtr_geometry.h" +#include "vtr_log.h" + +/* begin namespace openfpga */ +namespace openfpga { + +/******************************************************************** + * Assign mapped blocks to grid locations + * This is used by bitstream generator mainly as a fast look-up to + * get mapped blocks with a given coordinate + *******************************************************************/ +int append_clock_rr_graph(DeviceContext& device_ctx, + const ClockNetwork& clk_ntwk) { + VTR_LOG("Adding clock nodes to routing resource graph..."); + + VTR_LOG("Done\n"); +} + +} /* end namespace openfpga */ diff --git a/openfpga/src/annotation/append_clock_rr_graph.h b/openfpga/src/annotation/append_clock_rr_graph.h new file mode 100644 index 000000000..d3658c9e1 --- /dev/null +++ b/openfpga/src/annotation/append_clock_rr_graph.h @@ -0,0 +1,22 @@ +#ifndef APPEND_CLOCK_RR_GRAPH_H +#define APPEND_CLOCK_RR_GRAPH_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +#include "vpr_context.h" +#include "clock_network.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ + +/* begin namespace openfpga */ +namespace openfpga { + +int append_clock_rr_graph(DeviceContext& device_ctx, + const ClockNetwork& clk_ntwk); + +} /* end namespace openfpga */ + +#endif diff --git a/openfpga/src/base/openfpga_link_arch_template.h b/openfpga/src/base/openfpga_link_arch_template.h index aa557b72e..ae601ae0b 100644 --- a/openfpga/src/base/openfpga_link_arch_template.h +++ b/openfpga/src/base/openfpga_link_arch_template.h @@ -26,6 +26,7 @@ #include "vtr_assert.h" #include "vtr_log.h" #include "vtr_time.h" +#include "append_clock_rr_graph.h" /* begin namespace openfpga */ namespace openfpga { @@ -186,7 +187,7 @@ int link_arch_template(T& openfpga_ctx, const Command& cmd, * Top-level function to append a clock network to VPR's routing resource graph, including: * - Routing tracks dedicated to clock network * - Programmable switches to enable reconfigurability of clock network - * - + * - Adding virtual sources for clock signals *******************************************************************/ template int append_clock_rr_graph_template(T& openfpga_ctx, const Command& cmd, @@ -196,9 +197,7 @@ int append_clock_rr_graph_template(T& openfpga_ctx, const Command& cmd, CommandOptionId opt_verbose = cmd.option("verbose"); - /* TODO */ - - return CMD_EXEC_SUCCESS; + return append_clock_rr_graph(g_vpr_ctx.mutable_device(), openfpga_ctx.clock_arch()); } From ee0459d72965b6a80b5b2939ed5ea8c594e58d16 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 24 Feb 2023 17:58:37 -0800 Subject: [PATCH 022/166] [core] developing append_clock_rr_graph function --- .../src/annotation/append_clock_rr_graph.cpp | 48 +++++++++++++++++-- .../src/annotation/append_clock_rr_graph.h | 5 +- .../src/base/openfpga_link_arch_template.h | 2 +- 3 files changed, 48 insertions(+), 7 deletions(-) diff --git a/openfpga/src/annotation/append_clock_rr_graph.cpp b/openfpga/src/annotation/append_clock_rr_graph.cpp index 5b5b5f561..10f9fd227 100644 --- a/openfpga/src/annotation/append_clock_rr_graph.cpp +++ b/openfpga/src/annotation/append_clock_rr_graph.cpp @@ -2,6 +2,7 @@ #include "vtr_assert.h" #include "vtr_geometry.h" #include "vtr_log.h" +#include "command_exit_codes.h" /* begin namespace openfpga */ namespace openfpga { @@ -11,11 +12,50 @@ namespace openfpga { * This is used by bitstream generator mainly as a fast look-up to * get mapped blocks with a given coordinate *******************************************************************/ -int append_clock_rr_graph(DeviceContext& device_ctx, - const ClockNetwork& clk_ntwk) { - VTR_LOG("Adding clock nodes to routing resource graph..."); +int append_clock_rr_graph(DeviceContext& vpr_device_ctx, + const ClockNetwork& clk_ntwk, + const bool& verbose) { + vtr::ScopedStartFinishTimer timer("Adding clock nodes to routing resource graph"); - VTR_LOG("Done\n"); + /* Skip if there is no clock tree */ + if (clk_ntwk.num_trees()) { + VTR_LOG("Skip due to 0 clock trees.\nDouble check your clock architecture definition if this is unexpected\n"); + return CMD_EXEC_SUCCESS; + } + + /* Walk through the GSB array and add clock nodes to each GSB. + * Note that the GSB array is smaller than the grids by 1 column and 1 row!!! + */ + vtr::Point gsb_range(vpr_device_ctx.grid.width() - 1, + vpr_device_ctx.grid.height() - 1); + + size_t gsb_cnt = 0; + /* For each switch block, determine the size of array */ + for (size_t ix = 0; ix < gsb_range.x(); ++ix) { + for (size_t iy = 0; iy < gsb_range.y(); ++iy) { + /* Here we give the builder the fringe coordinates so that it can handle + * the GSBs at the borderside correctly sort drive_rr_nodes should be + * called if required by users + */ + const RRGSB& rr_gsb = + build_rr_gsb(vpr_device_ctx, + vtr::Point(vpr_device_ctx.grid.width() - 2, + vpr_device_ctx.grid.height() - 2), + vtr::Point(ix, iy)); + + /* Add clock nodes to device_rr_gsb */ + vtr::Point gsb_coordinate = rr_gsb.get_sb_coordinate(); + gsb_cnt++; /* Update counter */ + /* Print info */ + VTR_LOGV(verbose, "[%lu%] Added clock nodes to GSB[%lu][%lu]\r", + 100 * gsb_cnt / (gsb_range.x() * gsb_range.y()), ix, iy); + } + } + /* Report number of added clock nodes and edges */ + VTR_LOGV(verbose, "Appended clock nodes to %d General Switch Blocks (GSBs).\n", + gsb_range.x() * gsb_range.y()); + + return CMD_EXEC_SUCCESS; } } /* end namespace openfpga */ diff --git a/openfpga/src/annotation/append_clock_rr_graph.h b/openfpga/src/annotation/append_clock_rr_graph.h index d3658c9e1..9c20c51a6 100644 --- a/openfpga/src/annotation/append_clock_rr_graph.h +++ b/openfpga/src/annotation/append_clock_rr_graph.h @@ -14,8 +14,9 @@ /* begin namespace openfpga */ namespace openfpga { -int append_clock_rr_graph(DeviceContext& device_ctx, - const ClockNetwork& clk_ntwk); +int append_clock_rr_graph(DeviceContext& vpr_device_ctx, + const ClockNetwork& clk_ntwk, + const bool& verbose); } /* end namespace openfpga */ diff --git a/openfpga/src/base/openfpga_link_arch_template.h b/openfpga/src/base/openfpga_link_arch_template.h index ae601ae0b..99651b5a7 100644 --- a/openfpga/src/base/openfpga_link_arch_template.h +++ b/openfpga/src/base/openfpga_link_arch_template.h @@ -197,7 +197,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.clock_arch()); + return append_clock_rr_graph(g_vpr_ctx.mutable_device(), openfpga_ctx.clock_arch(), cmd_context.option_enable(cmd, opt_verbose)); } From 7f07a9d0311f1be7b3cfc28daf5fa88dc3eea5c6 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 24 Feb 2023 19:15:39 -0800 Subject: [PATCH 023/166] [lib] add default seg/switch to clock arch. Fixed syntax --- libs/libclkarchopenfpga/CMakeLists.txt | 1 + libs/libclkarchopenfpga/arch/example.xml | 2 +- .../src/base/clock_network.cpp | 18 +++++++ .../src/base/clock_network.h | 15 +++++- .../src/io/clock_network_xml_constants.h | 4 ++ .../src/io/read_xml_clock_network.cpp | 12 +++++ .../src/io/write_xml_clock_network.cpp | 7 ++- .../src/annotation/append_clock_rr_graph.cpp | 51 ++++++------------- .../src/annotation/append_clock_rr_graph.h | 5 +- .../src/base/openfpga_link_arch_template.h | 12 +++-- .../base/openfpga_setup_command_template.h | 14 ++--- 11 files changed, 89 insertions(+), 52 deletions(-) diff --git a/libs/libclkarchopenfpga/CMakeLists.txt b/libs/libclkarchopenfpga/CMakeLists.txt index 5ff1f7607..07283a792 100644 --- a/libs/libclkarchopenfpga/CMakeLists.txt +++ b/libs/libclkarchopenfpga/CMakeLists.txt @@ -21,6 +21,7 @@ set_target_properties(libclkarchopenfpga PROPERTIES PREFIX "") #Avoid extra 'lib target_link_libraries(libclkarchopenfpga libopenfpgautil libarchopenfpga + librrgraph libvtrutil libpugiutil) diff --git a/libs/libclkarchopenfpga/arch/example.xml b/libs/libclkarchopenfpga/arch/example.xml index e5ed17f98..3d7acab70 100644 --- a/libs/libclkarchopenfpga/arch/example.xml +++ b/libs/libclkarchopenfpga/arch/example.xml @@ -1,4 +1,4 @@ - + diff --git a/libs/libclkarchopenfpga/src/base/clock_network.cpp b/libs/libclkarchopenfpga/src/base/clock_network.cpp index bffc2a2a0..87cd94da1 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.cpp +++ b/libs/libclkarchopenfpga/src/base/clock_network.cpp @@ -19,6 +19,8 @@ ClockNetwork::ClockNetwork() { is_dirty_ = true; } /************************************************************************ * Public Accessors : aggregates ***********************************************************************/ +size_t ClockNetwork::num_trees() const { return trees().size(); } + ClockNetwork::clock_tree_range ClockNetwork::trees() const { return vtr::make_range(tree_ids_.begin(), tree_ids_.end()); } @@ -26,6 +28,14 @@ ClockNetwork::clock_tree_range ClockNetwork::trees() const { /************************************************************************ * Public Accessors : Basic data query ***********************************************************************/ +std::string ClockNetwork::default_segment_name() const { + return default_segment_name_; +} + +std::string ClockNetwork::default_switch_name() const { + return default_switch_name_; +} + std::string ClockNetwork::tree_name(const ClockTreeId& tree_id) const { VTR_ASSERT(valid_tree_id(tree_id)); return tree_names_[tree_id]; @@ -134,6 +144,14 @@ void ClockNetwork::reserve_trees(const size_t& num_trees) { tree_top_spines_.reserve(num_trees); } +void ClockNetwork::set_default_segment_name(const std::string& name) { + default_segment_name_ = name; +} + +void ClockNetwork::set_default_switch_name(const std::string& name) { + default_switch_name_ = name; +} + ClockTreeId ClockNetwork::create_tree(const std::string& name, size_t width) { /* Create a new id */ ClockTreeId tree_id = ClockTreeId(tree_ids_.size()); diff --git a/libs/libclkarchopenfpga/src/base/clock_network.h b/libs/libclkarchopenfpga/src/base/clock_network.h index d54362ced..8dbda835a 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.h +++ b/libs/libclkarchopenfpga/src/base/clock_network.h @@ -14,7 +14,7 @@ /* Headers from openfpgautil library */ #include "clock_network_fwd.h" -#include "openfpga_port.h" +#include "rr_graph_fwd.h" namespace openfpga { // Begin namespace openfpga @@ -46,11 +46,14 @@ class ClockNetwork { ClockNetwork(); public: /* Accessors: aggregates */ + size_t num_trees() const; clock_tree_range trees() const; /* Return a list of spine id under a clock tree */ std::vector spines(const ClockTreeId& tree_id) const; public: /* Public Accessors: Basic data query */ + std::string default_segment_name() const; + std::string default_switch_name() const; std::string tree_name(const ClockTreeId& tree_id) const; size_t tree_width(const ClockTreeId& tree_id) const; size_t tree_depth(const ClockTreeId& tree_id) const; @@ -78,6 +81,8 @@ class ClockNetwork { void reserve_spines(const size_t& num_spines); /* Reserve a number of trees to be memory efficent */ void reserve_trees(const size_t& num_trees); + void set_default_segment_name(const std::string& name); + void set_default_switch_name(const std::string& name); /* Create a new tree, by default the tree can accomodate only 1 clock signal; * use width to adjust the size */ ClockTreeId create_tree(const std::string& name, size_t width = 1); @@ -142,6 +147,14 @@ class ClockNetwork { vtr::vector> spine_children_; vtr::vector spine_parent_trees_; + /* Default routing resource */ + std::string default_segment_name_; /* The routing segment representing the + clock wires */ + RRSegmentId default_segment_id_; + std::string + default_switch_name_; /* The routing switch interconnecting clock wire */ + RRSwitchId default_switch_id_; + /* Fast lookup */ std::map tree_name2id_map_; std::map spine_name2id_map_; diff --git a/libs/libclkarchopenfpga/src/io/clock_network_xml_constants.h b/libs/libclkarchopenfpga/src/io/clock_network_xml_constants.h index 8d96330b4..417e3d9db 100644 --- a/libs/libclkarchopenfpga/src/io/clock_network_xml_constants.h +++ b/libs/libclkarchopenfpga/src/io/clock_network_xml_constants.h @@ -4,6 +4,10 @@ /* Constants required by XML parser */ constexpr const char* XML_CLOCK_NETWORK_ROOT_NAME = "clock_networks"; +constexpr const char* XML_CLOCK_NETWORK_ATTRIBUTE_DEFAULT_SEGMENT = + "default_segment"; +constexpr const char* XML_CLOCK_NETWORK_ATTRIBUTE_DEFAULT_SWITCH = + "default_switch"; constexpr const char* XML_CLOCK_TREE_NODE_NAME = "clock_network"; constexpr const char* XML_CLOCK_TREE_ATTRIBUTE_NAME = "name"; constexpr const char* XML_CLOCK_TREE_ATTRIBUTE_WIDTH = "width"; diff --git a/libs/libclkarchopenfpga/src/io/read_xml_clock_network.cpp b/libs/libclkarchopenfpga/src/io/read_xml_clock_network.cpp index de50eec94..c8bd9835e 100644 --- a/libs/libclkarchopenfpga/src/io/read_xml_clock_network.cpp +++ b/libs/libclkarchopenfpga/src/io/read_xml_clock_network.cpp @@ -167,6 +167,18 @@ ClockNetwork read_xml_clock_network(const char* fname) { pugi::xml_node xml_root = get_single_child(doc, XML_CLOCK_NETWORK_ROOT_NAME, loc_data); + std::string default_segment_name = + get_attribute(xml_root, XML_CLOCK_NETWORK_ATTRIBUTE_DEFAULT_SEGMENT, + loc_data) + .as_string(); + clk_ntwk.set_default_segment_name(default_segment_name); + + std::string default_switch_name = + get_attribute(xml_root, XML_CLOCK_NETWORK_ATTRIBUTE_DEFAULT_SWITCH, + loc_data) + .as_string(); + clk_ntwk.set_default_switch_name(default_switch_name); + size_t num_trees = std::distance(xml_root.children().begin(), xml_root.children().end()); diff --git a/libs/libclkarchopenfpga/src/io/write_xml_clock_network.cpp b/libs/libclkarchopenfpga/src/io/write_xml_clock_network.cpp index bf733ab0c..e2524a0ae 100644 --- a/libs/libclkarchopenfpga/src/io/write_xml_clock_network.cpp +++ b/libs/libclkarchopenfpga/src/io/write_xml_clock_network.cpp @@ -135,7 +135,12 @@ int write_xml_clock_network(const char* fname, const ClockNetwork& clk_ntwk) { openfpga::check_file_stream(fname, fp); /* Write the root node */ - fp << "<" << XML_CLOCK_NETWORK_ROOT_NAME << ">" + fp << "<" << XML_CLOCK_NETWORK_ROOT_NAME; + write_xml_attribute(fp, XML_CLOCK_NETWORK_ATTRIBUTE_DEFAULT_SEGMENT, + clk_ntwk.default_segment_name().c_str()); + write_xml_attribute(fp, XML_CLOCK_NETWORK_ATTRIBUTE_DEFAULT_SWITCH, + clk_ntwk.default_switch_name().c_str()); + fp << ">" << "\n"; int err_code = 0; diff --git a/openfpga/src/annotation/append_clock_rr_graph.cpp b/openfpga/src/annotation/append_clock_rr_graph.cpp index 10f9fd227..ffc60f835 100644 --- a/openfpga/src/annotation/append_clock_rr_graph.cpp +++ b/openfpga/src/annotation/append_clock_rr_graph.cpp @@ -1,8 +1,10 @@ -#include "annotate_clock_rr_graph.h" +#include "append_clock_rr_graph.h" + +#include "command_exit_codes.h" #include "vtr_assert.h" #include "vtr_geometry.h" #include "vtr_log.h" -#include "command_exit_codes.h" +#include "vtr_time.h" /* begin namespace openfpga */ namespace openfpga { @@ -13,47 +15,26 @@ namespace openfpga { * get mapped blocks with a given coordinate *******************************************************************/ int append_clock_rr_graph(DeviceContext& vpr_device_ctx, - const ClockNetwork& clk_ntwk, - const bool& verbose) { - vtr::ScopedStartFinishTimer timer("Adding clock nodes to routing resource graph"); + const ClockNetwork& clk_ntwk, const bool& verbose) { + vtr::ScopedStartFinishTimer timer( + "Appending programmable clock network to routing resource graph"); /* Skip if there is no clock tree */ if (clk_ntwk.num_trees()) { - VTR_LOG("Skip due to 0 clock trees.\nDouble check your clock architecture definition if this is unexpected\n"); + VTR_LOG( + "Skip due to 0 clock trees.\nDouble check your clock architecture " + "definition if this is unexpected\n"); return CMD_EXEC_SUCCESS; } - /* Walk through the GSB array and add clock nodes to each GSB. - * Note that the GSB array is smaller than the grids by 1 column and 1 row!!! - */ - vtr::Point gsb_range(vpr_device_ctx.grid.width() - 1, - vpr_device_ctx.grid.height() - 1); + size_t num_clock_nodes = 0; + size_t num_clock_edges = 0; - size_t gsb_cnt = 0; - /* For each switch block, determine the size of array */ - for (size_t ix = 0; ix < gsb_range.x(); ++ix) { - for (size_t iy = 0; iy < gsb_range.y(); ++iy) { - /* Here we give the builder the fringe coordinates so that it can handle - * the GSBs at the borderside correctly sort drive_rr_nodes should be - * called if required by users - */ - const RRGSB& rr_gsb = - build_rr_gsb(vpr_device_ctx, - vtr::Point(vpr_device_ctx.grid.width() - 2, - vpr_device_ctx.grid.height() - 2), - vtr::Point(ix, iy)); - - /* Add clock nodes to device_rr_gsb */ - vtr::Point gsb_coordinate = rr_gsb.get_sb_coordinate(); - gsb_cnt++; /* Update counter */ - /* Print info */ - VTR_LOGV(verbose, "[%lu%] Added clock nodes to GSB[%lu][%lu]\r", - 100 * gsb_cnt / (gsb_range.x() * gsb_range.y()), ix, iy); - } - } /* Report number of added clock nodes and edges */ - VTR_LOGV(verbose, "Appended clock nodes to %d General Switch Blocks (GSBs).\n", - gsb_range.x() * gsb_range.y()); + VTR_LOGV( + verbose, + "Appended %lu clock nodes and %lu clock edges to routing resource graph.\n", + num_clock_nodes, num_clock_edges); return CMD_EXEC_SUCCESS; } diff --git a/openfpga/src/annotation/append_clock_rr_graph.h b/openfpga/src/annotation/append_clock_rr_graph.h index 9c20c51a6..703c5f0c7 100644 --- a/openfpga/src/annotation/append_clock_rr_graph.h +++ b/openfpga/src/annotation/append_clock_rr_graph.h @@ -4,8 +4,8 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include "vpr_context.h" #include "clock_network.h" +#include "vpr_context.h" /******************************************************************** * Function declaration @@ -15,8 +15,7 @@ namespace openfpga { int append_clock_rr_graph(DeviceContext& vpr_device_ctx, - const ClockNetwork& clk_ntwk, - const bool& verbose); + const ClockNetwork& clk_ntwk, const bool& verbose); } /* end namespace openfpga */ diff --git a/openfpga/src/base/openfpga_link_arch_template.h b/openfpga/src/base/openfpga_link_arch_template.h index 99651b5a7..7b9197018 100644 --- a/openfpga/src/base/openfpga_link_arch_template.h +++ b/openfpga/src/base/openfpga_link_arch_template.h @@ -12,6 +12,7 @@ #include "annotate_placement.h" #include "annotate_rr_graph.h" #include "annotate_simulation_setting.h" +#include "append_clock_rr_graph.h" #include "build_tile_direct.h" #include "command.h" #include "command_context.h" @@ -26,7 +27,6 @@ #include "vtr_assert.h" #include "vtr_log.h" #include "vtr_time.h" -#include "append_clock_rr_graph.h" /* begin namespace openfpga */ namespace openfpga { @@ -184,10 +184,11 @@ int link_arch_template(T& openfpga_ctx, const Command& cmd, } /******************************************************************** - * Top-level function to append a clock network to VPR's routing resource graph, including: + * Top-level function to append a clock network to VPR's routing resource graph, + *including: * - Routing tracks dedicated to clock network * - Programmable switches to enable reconfigurability of clock network - * - Adding virtual sources for clock signals + * - Adding virtual sources for clock signals *******************************************************************/ template int append_clock_rr_graph_template(T& openfpga_ctx, const Command& cmd, @@ -197,10 +198,11 @@ 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.clock_arch(), cmd_context.option_enable(cmd, opt_verbose)); + return append_clock_rr_graph(g_vpr_ctx.mutable_device(), + openfpga_ctx.clock_arch(), + cmd_context.option_enable(cmd, opt_verbose)); } - } /* end namespace openfpga */ #endif diff --git a/openfpga/src/base/openfpga_setup_command_template.h b/openfpga/src/base/openfpga_setup_command_template.h index 9a5ca2c63..c22f114e4 100644 --- a/openfpga/src/base/openfpga_setup_command_template.h +++ b/openfpga/src/base/openfpga_setup_command_template.h @@ -645,10 +645,10 @@ ShellCommandId add_append_clock_rr_graph_command_template( /* Add command 'pb_pin_fixup' to the Shell */ ShellCommandId shell_cmd_id = shell.add_command( shell_cmd, - "Append clock network to the routing resource graph built by VPR.", - hidden); + "Append clock network to the routing resource graph built by VPR.", hidden); shell.set_command_class(shell_cmd_id, cmd_class_id); - shell.set_command_execute_function(shell_cmd_id, append_clock_rr_graph_template); + shell.set_command_execute_function(shell_cmd_id, + append_clock_rr_graph_template); /* Add command dependency to the Shell */ shell.set_command_dependency(shell_cmd_id, dependent_cmds); @@ -763,9 +763,11 @@ void add_setup_command_templates(openfpga::Shell& shell, /* The 'append_clock_rr_graph' command should NOT be executed before * 'read_openfpga_clock_arch' */ std::vector append_clock_rr_graph_dependent_cmds; - append_clock_rr_graph_dependent_cmds.push_back(read_openfpga_clock_arch_cmd_id); - add_append_clock_rr_graph_command_template(shell, openfpga_setup_cmd_class, - append_clock_rr_graph_dependent_cmds, hidden); + append_clock_rr_graph_dependent_cmds.push_back( + read_openfpga_clock_arch_cmd_id); + add_append_clock_rr_graph_command_template( + shell, openfpga_setup_cmd_class, append_clock_rr_graph_dependent_cmds, + hidden); /******************************** * Command 'write_gsb' From cf84e1df536ddcf1d4eec894a5a56df3691e578b Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 24 Feb 2023 22:50:27 -0800 Subject: [PATCH 024/166] [core] dev --- .../src/annotation/append_clock_rr_graph.cpp | 42 +++++++++++++++++-- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/openfpga/src/annotation/append_clock_rr_graph.cpp b/openfpga/src/annotation/append_clock_rr_graph.cpp index ffc60f835..2fbecc0aa 100644 --- a/openfpga/src/annotation/append_clock_rr_graph.cpp +++ b/openfpga/src/annotation/append_clock_rr_graph.cpp @@ -1,5 +1,5 @@ #include "append_clock_rr_graph.h" - +#include "rr_graph_builder_utils.h" #include "command_exit_codes.h" #include "vtr_assert.h" #include "vtr_geometry.h" @@ -9,6 +9,36 @@ /* begin namespace openfpga */ namespace openfpga { +static +size_t estimate_clock_rr_graph_num_nodes(const DeviceGrid& grids, + const bool& through_channel) { + size_t num_nodes = 0; + /* Check the number of CHANX nodes required */ + for (size_t iy = 0; iy < grids.height() - 1; ++iy) { + for (size_t ix = 1; ix < grids.width() - 1; ++ix) { + vtr::Point chanx_coord(ix, iy); + /* Bypass if the routing channel does not exist when through channels are not allowed */ + if ((false == through_channel) + && (false == is_chanx_exist(grids, chanx_coord))) { + continue; + } + } + } + + for (size_t ix = 0; ix < grids.width() - 1; ++ix) { + for (size_t iy = 1; iy < grids.height() - 1; ++iy) { + vtr::Point chany_coord(ix, iy); + /* Bypass if the routing channel does not exist when through channel are not allowed */ + if ((false == through_channel) + && (false == is_chany_exist(grids, chany_coord))) { + continue; + } + } + } + + return num_nodes; +} + /******************************************************************** * Assign mapped blocks to grid locations * This is used by bitstream generator mainly as a fast look-up to @@ -27,14 +57,18 @@ int append_clock_rr_graph(DeviceContext& vpr_device_ctx, return CMD_EXEC_SUCCESS; } - size_t num_clock_nodes = 0; + /* Estimate the number of nodes and pre-allocated */ + size_t orig_num_nodes = vpr_device_ctx.rr_graph.num_nodes(); + size_t num_clock_nodes = estimate_clock_rr_graph_num_nodes(vpr_device_ctx.grid, vpr_device_ctx.arch->through_channel); + vpr_device_ctx.rr_graph_builder.reserve_nodes(num_clock_nodes + orig_num_nodes); + size_t num_clock_edges = 0; /* Report number of added clock nodes and edges */ VTR_LOGV( verbose, - "Appended %lu clock nodes and %lu clock edges to routing resource graph.\n", - num_clock_nodes, num_clock_edges); + "Appended %lu clock nodes (+%.2f\%) and %lu clock edges to routing resource graph.\n", + num_clock_nodes, (float)(num_clock_nodes / orig_num_nodes), num_clock_edges); return CMD_EXEC_SUCCESS; } From 8be6e7d0a02fadc8ac259e234126e9bedd9e84aa Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 25 Feb 2023 11:04:48 -0800 Subject: [PATCH 025/166] [core] dev --- .../src/annotation/append_clock_rr_graph.cpp | 54 ++++++++++++++++--- 1 file changed, 48 insertions(+), 6 deletions(-) diff --git a/openfpga/src/annotation/append_clock_rr_graph.cpp b/openfpga/src/annotation/append_clock_rr_graph.cpp index 2fbecc0aa..fdf650f65 100644 --- a/openfpga/src/annotation/append_clock_rr_graph.cpp +++ b/openfpga/src/annotation/append_clock_rr_graph.cpp @@ -9,9 +9,37 @@ /* begin namespace openfpga */ namespace openfpga { +/******************************************************************** + * Estimate the number of clock nodes to be added for a given tile and clock structure + * For each layer/level of a clock network, we need + * - the clock nodes are paired in INC and DEC directions + * - the number of clock nodes depend on the width of clock tree (number of clock signals) + * - Note that some layer only need CHANX or CHANY clock nodes since clock nodes cannot make turns in the same layer. + * For instance + * - Layer 0: CHANX + * - Layer 1: CHANY + * - Layer 2: CHANX + *******************************************************************/ +static +size_t estimate_clock_rr_graph_num_nodes(const ClockNetwork& clk_ntwk, + const t_rr_type& chan_type) { + size_t num_nodes = 0; + + + + return num_nodes; +} + +/******************************************************************** + * Estimate the number of clock nodes to be added. + * Clock nodes are required by X-direction and Y-direction connection blocks + * which are in the type of CHANX and CHANY + * Note that switch blocks do not require any new nodes but new edges + *******************************************************************/ static size_t estimate_clock_rr_graph_num_nodes(const DeviceGrid& grids, - const bool& through_channel) { + const bool& through_channel, + const ClockNetwork& clk_ntwk) { size_t num_nodes = 0; /* Check the number of CHANX nodes required */ for (size_t iy = 0; iy < grids.height() - 1; ++iy) { @@ -22,6 +50,8 @@ size_t estimate_clock_rr_graph_num_nodes(const DeviceGrid& grids, && (false == is_chanx_exist(grids, chanx_coord))) { continue; } + /* Estimate the routing tracks required by clock routing only */ + num_nodes += estimate_clock_rr_graph_num_chan_nodes(clk_ntwk, CHANX); } } @@ -33,6 +63,8 @@ size_t estimate_clock_rr_graph_num_nodes(const DeviceGrid& grids, && (false == is_chany_exist(grids, chany_coord))) { continue; } + /* Estimate the routing tracks required by clock routing only */ + num_nodes += estimate_clock_rr_graph_num_chan_nodes(clk_ntwk, CHANY); } } @@ -40,9 +72,12 @@ size_t estimate_clock_rr_graph_num_nodes(const DeviceGrid& grids, } /******************************************************************** - * Assign mapped blocks to grid locations - * This is used by bitstream generator mainly as a fast look-up to - * get mapped blocks with a given coordinate + * Append a programmable clock network to an existing routing resource graph + * This function will do the following jobs: + * - Estimate the number of clock nodes and pre-allocate memory + * - Add clock nodes + * - Build edges between clock nodes + * - Sanity checks *******************************************************************/ int append_clock_rr_graph(DeviceContext& vpr_device_ctx, const ClockNetwork& clk_ntwk, const bool& verbose) { @@ -57,13 +92,20 @@ int append_clock_rr_graph(DeviceContext& vpr_device_ctx, return CMD_EXEC_SUCCESS; } - /* Estimate the number of nodes and pre-allocated */ + /* TODO: report any clock structure we do not support yet! */ + + /* Estimate the number of nodes and pre-allocate */ size_t orig_num_nodes = vpr_device_ctx.rr_graph.num_nodes(); - size_t num_clock_nodes = estimate_clock_rr_graph_num_nodes(vpr_device_ctx.grid, vpr_device_ctx.arch->through_channel); + size_t num_clock_nodes = estimate_clock_rr_graph_num_nodes(vpr_device_ctx.grid, vpr_device_ctx.arch->through_channel, clk_ntwk); vpr_device_ctx.rr_graph_builder.reserve_nodes(num_clock_nodes + orig_num_nodes); + /* TODO: Add clock nodes */ + + /* TODO: Add edges between clock nodes*/ size_t num_clock_edges = 0; + /* TODO: Sanity checks */ + /* Report number of added clock nodes and edges */ VTR_LOGV( verbose, From 0b336507618c4abac1ba91ee29b6d7cc959ed5f6 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 25 Feb 2023 22:41:33 -0800 Subject: [PATCH 026/166] [core] dev --- .../src/base/clock_network.cpp | 52 +++++++++++++++++++ .../src/base/clock_network.h | 21 ++++++++ .../src/base/clock_network_fwd.h | 2 + .../src/annotation/append_clock_rr_graph.cpp | 10 ++-- 4 files changed, 82 insertions(+), 3 deletions(-) diff --git a/libs/libclkarchopenfpga/src/base/clock_network.cpp b/libs/libclkarchopenfpga/src/base/clock_network.cpp index 87cd94da1..389e6678b 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.cpp +++ b/libs/libclkarchopenfpga/src/base/clock_network.cpp @@ -25,9 +25,53 @@ ClockNetwork::clock_tree_range ClockNetwork::trees() const { return vtr::make_range(tree_ids_.begin(), tree_ids_.end()); } +std::vector ClockNetwork::levels(const ClockTreeId& tree_id) const { + std::vector ret; + for (size_t ilvl = 0; ilvl < tree_depth(tree_id); ++ilvl) { + ret.push_back(ClockLevelId(ilvl)); + } + return ret; +} + /************************************************************************ * Public Accessors : Basic data query ***********************************************************************/ +t_rr_type ClockNetwork::spine_track_type(const ClockSpineId& spine_id) const { + VTR_ASSERT(valid_spine_start_end_points(spine_id)); + if (spine_start_point(spine_id).y() == spine_end_point(spine_id).y()) { + return CHANX; + } + return CHANY; +} + +Direction ClockNetwork::spine_direction(const ClockSpineId& spine_id) const { + VTR_ASSERT(valid_spine_start_end_points(spine_id)); + if (spine_track_type(spine_id) == CHANX) { + if (spine_start_point(spine_id).x() < spine_end_point(spine_id).x()) { + return Direction::INC; + } + } else { + VTR_ASSERT(spine_track_type(spine_id) == CHANY); + if (spine_start_point(spine_id).y() < spine_end_point(spine_id).y()) { + return Direction::INC; + } + } + return Direction::DEC; +} + +size_t ClockNetwork::num_tracks(const ClockTreeId& tree_id, const ClockLevelId& level, const t_rr_type& direction) const { + size_t num_tracks = 0; + for (ClockSpineId curr_spine : spines(tree_id)) { + if (spine_levels_[curr_spine] != size_t(level)) { + continue; + } + if (spine_track_type(curr_spine) == direction) { + num_tracks++; + } + } + return num_tracks; +} + std::string ClockNetwork::default_segment_name() const { return default_segment_name_; } @@ -339,4 +383,12 @@ bool ClockNetwork::valid_spine_switch_point_id( return size_t(switch_point_id) < spine_switch_points_[spine_id].size(); } +bool ClockNetwork::valid_spine_start_end_points(const ClockSpineId& spine_id) const { + VTR_ASSERT(valid_spine_id(spine_id)); + if ((spine_start_point(spine_id).x() != spine_end_point(spine_id).x()) && (spine_start_point(spine_id).y() != spine_end_point(spine_id).y())) { + return false; + } + return true; +} + } // End of namespace openfpga diff --git a/libs/libclkarchopenfpga/src/base/clock_network.h b/libs/libclkarchopenfpga/src/base/clock_network.h index 8dbda835a..e4bc20f7d 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.h +++ b/libs/libclkarchopenfpga/src/base/clock_network.h @@ -15,6 +15,7 @@ /* Headers from openfpgautil library */ #include "clock_network_fwd.h" #include "rr_graph_fwd.h" +#include "rr_node_types.h" namespace openfpga { // Begin namespace openfpga @@ -48,10 +49,14 @@ class ClockNetwork { public: /* Accessors: aggregates */ size_t num_trees() const; clock_tree_range trees() const; + /* Return the range of clock levels */ + std::vector levels(const ClockTreeId& tree_id) const; /* Return a list of spine id under a clock tree */ std::vector spines(const ClockTreeId& tree_id) const; public: /* Public Accessors: Basic data query */ + /* Return the number of routing tracks required by a selected clock tree at a given level and direction */ + size_t num_tracks(const ClockTreeId& tree_id, const ClockLevelId& level, const t_rr_type& direction) const; std::string default_segment_name() const; std::string default_switch_name() const; std::string tree_name(const ClockTreeId& tree_id) const; @@ -60,6 +65,20 @@ class ClockNetwork { std::string spine_name(const ClockSpineId& spine_id) const; vtr::Point spine_start_point(const ClockSpineId& spine_id) const; vtr::Point spine_end_point(const ClockSpineId& spine_id) const; + /* Identify the direction of a spine, depending on its starting and ending points + * - CHANX represents a horizental routing track + * - CHANY represents a vertical routing track + */ + t_rr_type spine_track_type(const ClockSpineId& spine_id) const; + /* Identify the direction of a spine, depending on its starting and ending points + * INC represents + * - a CHANX track goes from left to right, or + * - a CHANY track goes from bottom to top + * DEC represents + * - a CHANX track goes from right to left, or + * - a CHANY track goes from top to bottom + */ + Direction spine_direction(const ClockSpineId& spine_id) const; /* Return the unique id of switch points under a clock spine*/ std::vector spine_switch_points( const ClockSpineId& spine_id) const; @@ -116,6 +135,8 @@ class ClockNetwork { bool valid_spine_switch_point_id( const ClockSpineId& spine_id, const ClockSwitchPointId& switch_point_id) const; + /* Valid starting and ending point should indicate either this is a X-direction spine or a Y-direction spine. Diagonal spine is not supported! */ + bool valid_spine_start_end_points(const ClockSpineId& spine_id) const; private: /* Private mutators */ /* Build internal links between spines under a given tree */ diff --git a/libs/libclkarchopenfpga/src/base/clock_network_fwd.h b/libs/libclkarchopenfpga/src/base/clock_network_fwd.h index cc4af5f70..a18dc4394 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network_fwd.h +++ b/libs/libclkarchopenfpga/src/base/clock_network_fwd.h @@ -14,10 +14,12 @@ namespace openfpga { // Begin namespace openfpga +struct clock_level_id_tag; struct clock_tree_id_tag; struct clock_spine_id_tag; struct clock_switch_point_id_tag; +typedef vtr::StrongId ClockLevelId; typedef vtr::StrongId ClockTreeId; typedef vtr::StrongId ClockSpineId; typedef vtr::StrongId ClockSwitchPointId; diff --git a/openfpga/src/annotation/append_clock_rr_graph.cpp b/openfpga/src/annotation/append_clock_rr_graph.cpp index fdf650f65..1e6f85921 100644 --- a/openfpga/src/annotation/append_clock_rr_graph.cpp +++ b/openfpga/src/annotation/append_clock_rr_graph.cpp @@ -21,11 +21,15 @@ namespace openfpga { * - Layer 2: CHANX *******************************************************************/ static -size_t estimate_clock_rr_graph_num_nodes(const ClockNetwork& clk_ntwk, +size_t estimate_clock_rr_graph_num_chan_nodes(const ClockNetwork& clk_ntwk, const t_rr_type& chan_type) { size_t num_nodes = 0; - + for (auto itree : clk_ntwk.trees()) { + for (auto ilvl : clk_ntwk.levels(itree)) { + num_nodes += clk_ntwk.num_tracks(itree, ilvl, chan_type); + } + } return num_nodes; } @@ -109,7 +113,7 @@ int append_clock_rr_graph(DeviceContext& vpr_device_ctx, /* Report number of added clock nodes and edges */ VTR_LOGV( verbose, - "Appended %lu clock nodes (+%.2f\%) and %lu clock edges to routing resource graph.\n", + "Appended %lu clock nodes (+%.2f%) and %lu clock edges to routing resource graph.\n", num_clock_nodes, (float)(num_clock_nodes / orig_num_nodes), num_clock_edges); return CMD_EXEC_SUCCESS; From 8f0d94ba73c8f630ffca5864b942a4bdc130637d Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 25 Feb 2023 22:43:21 -0800 Subject: [PATCH 027/166] [code] format --- .../src/base/clock_network.cpp | 15 +++-- .../src/base/clock_network.h | 17 ++++-- .../src/annotation/append_clock_rr_graph.cpp | 61 ++++++++++--------- 3 files changed, 54 insertions(+), 39 deletions(-) diff --git a/libs/libclkarchopenfpga/src/base/clock_network.cpp b/libs/libclkarchopenfpga/src/base/clock_network.cpp index 389e6678b..1625578bb 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.cpp +++ b/libs/libclkarchopenfpga/src/base/clock_network.cpp @@ -25,7 +25,8 @@ ClockNetwork::clock_tree_range ClockNetwork::trees() const { return vtr::make_range(tree_ids_.begin(), tree_ids_.end()); } -std::vector ClockNetwork::levels(const ClockTreeId& tree_id) const { +std::vector ClockNetwork::levels( + const ClockTreeId& tree_id) const { std::vector ret; for (size_t ilvl = 0; ilvl < tree_depth(tree_id); ++ilvl) { ret.push_back(ClockLevelId(ilvl)); @@ -55,11 +56,13 @@ Direction ClockNetwork::spine_direction(const ClockSpineId& spine_id) const { if (spine_start_point(spine_id).y() < spine_end_point(spine_id).y()) { return Direction::INC; } - } + } return Direction::DEC; } -size_t ClockNetwork::num_tracks(const ClockTreeId& tree_id, const ClockLevelId& level, const t_rr_type& direction) const { +size_t ClockNetwork::num_tracks(const ClockTreeId& tree_id, + const ClockLevelId& level, + const t_rr_type& direction) const { size_t num_tracks = 0; for (ClockSpineId curr_spine : spines(tree_id)) { if (spine_levels_[curr_spine] != size_t(level)) { @@ -383,9 +386,11 @@ bool ClockNetwork::valid_spine_switch_point_id( return size_t(switch_point_id) < spine_switch_points_[spine_id].size(); } -bool ClockNetwork::valid_spine_start_end_points(const ClockSpineId& spine_id) const { +bool ClockNetwork::valid_spine_start_end_points( + const ClockSpineId& spine_id) const { VTR_ASSERT(valid_spine_id(spine_id)); - if ((spine_start_point(spine_id).x() != spine_end_point(spine_id).x()) && (spine_start_point(spine_id).y() != spine_end_point(spine_id).y())) { + if ((spine_start_point(spine_id).x() != spine_end_point(spine_id).x()) && + (spine_start_point(spine_id).y() != spine_end_point(spine_id).y())) { return false; } return true; diff --git a/libs/libclkarchopenfpga/src/base/clock_network.h b/libs/libclkarchopenfpga/src/base/clock_network.h index e4bc20f7d..acbe238d4 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.h +++ b/libs/libclkarchopenfpga/src/base/clock_network.h @@ -55,8 +55,10 @@ class ClockNetwork { std::vector spines(const ClockTreeId& tree_id) const; public: /* Public Accessors: Basic data query */ - /* Return the number of routing tracks required by a selected clock tree at a given level and direction */ - size_t num_tracks(const ClockTreeId& tree_id, const ClockLevelId& level, const t_rr_type& direction) const; + /* Return the number of routing tracks required by a selected clock tree at a + * given level and direction */ + size_t num_tracks(const ClockTreeId& tree_id, const ClockLevelId& level, + const t_rr_type& direction) const; std::string default_segment_name() const; std::string default_switch_name() const; std::string tree_name(const ClockTreeId& tree_id) const; @@ -65,13 +67,14 @@ class ClockNetwork { std::string spine_name(const ClockSpineId& spine_id) const; vtr::Point spine_start_point(const ClockSpineId& spine_id) const; vtr::Point spine_end_point(const ClockSpineId& spine_id) const; - /* Identify the direction of a spine, depending on its starting and ending points + /* Identify the direction of a spine, depending on its starting and ending + * points * - CHANX represents a horizental routing track * - CHANY represents a vertical routing track */ t_rr_type spine_track_type(const ClockSpineId& spine_id) const; - /* Identify the direction of a spine, depending on its starting and ending points - * INC represents + /* Identify the direction of a spine, depending on its starting and ending + * points INC represents * - a CHANX track goes from left to right, or * - a CHANY track goes from bottom to top * DEC represents @@ -135,7 +138,9 @@ class ClockNetwork { bool valid_spine_switch_point_id( const ClockSpineId& spine_id, const ClockSwitchPointId& switch_point_id) const; - /* Valid starting and ending point should indicate either this is a X-direction spine or a Y-direction spine. Diagonal spine is not supported! */ + /* Valid starting and ending point should indicate either this is a + * X-direction spine or a Y-direction spine. Diagonal spine is not supported! + */ bool valid_spine_start_end_points(const ClockSpineId& spine_id) const; private: /* Private mutators */ diff --git a/openfpga/src/annotation/append_clock_rr_graph.cpp b/openfpga/src/annotation/append_clock_rr_graph.cpp index 1e6f85921..2e29c4ad3 100644 --- a/openfpga/src/annotation/append_clock_rr_graph.cpp +++ b/openfpga/src/annotation/append_clock_rr_graph.cpp @@ -1,6 +1,7 @@ #include "append_clock_rr_graph.h" -#include "rr_graph_builder_utils.h" + #include "command_exit_codes.h" +#include "rr_graph_builder_utils.h" #include "vtr_assert.h" #include "vtr_geometry.h" #include "vtr_log.h" @@ -10,26 +11,26 @@ namespace openfpga { /******************************************************************** - * Estimate the number of clock nodes to be added for a given tile and clock structure - * For each layer/level of a clock network, we need + * Estimate the number of clock nodes to be added for a given tile and clock + *structure For each layer/level of a clock network, we need * - the clock nodes are paired in INC and DEC directions - * - the number of clock nodes depend on the width of clock tree (number of clock signals) - * - Note that some layer only need CHANX or CHANY clock nodes since clock nodes cannot make turns in the same layer. - * For instance + * - the number of clock nodes depend on the width of clock tree (number of + *clock signals) + * - Note that some layer only need CHANX or CHANY clock nodes since clock nodes + *cannot make turns in the same layer. For instance * - Layer 0: CHANX * - Layer 1: CHANY * - Layer 2: CHANX *******************************************************************/ -static -size_t estimate_clock_rr_graph_num_chan_nodes(const ClockNetwork& clk_ntwk, - const t_rr_type& chan_type) { +static size_t estimate_clock_rr_graph_num_chan_nodes( + const ClockNetwork& clk_ntwk, const t_rr_type& chan_type) { size_t num_nodes = 0; for (auto itree : clk_ntwk.trees()) { for (auto ilvl : clk_ntwk.levels(itree)) { - num_nodes += clk_ntwk.num_tracks(itree, ilvl, chan_type); + num_nodes += clk_ntwk.num_tracks(itree, ilvl, chan_type); } - } + } return num_nodes; } @@ -37,21 +38,21 @@ size_t estimate_clock_rr_graph_num_chan_nodes(const ClockNetwork& clk_ntwk, /******************************************************************** * Estimate the number of clock nodes to be added. * Clock nodes are required by X-direction and Y-direction connection blocks - * which are in the type of CHANX and CHANY + * which are in the type of CHANX and CHANY * Note that switch blocks do not require any new nodes but new edges *******************************************************************/ -static -size_t estimate_clock_rr_graph_num_nodes(const DeviceGrid& grids, - const bool& through_channel, - const ClockNetwork& clk_ntwk) { +static size_t estimate_clock_rr_graph_num_nodes(const DeviceGrid& grids, + const bool& through_channel, + const ClockNetwork& clk_ntwk) { size_t num_nodes = 0; /* Check the number of CHANX nodes required */ for (size_t iy = 0; iy < grids.height() - 1; ++iy) { for (size_t ix = 1; ix < grids.width() - 1; ++ix) { vtr::Point chanx_coord(ix, iy); - /* Bypass if the routing channel does not exist when through channels are not allowed */ - if ((false == through_channel) - && (false == is_chanx_exist(grids, chanx_coord))) { + /* Bypass if the routing channel does not exist when through channels are + * not allowed */ + if ((false == through_channel) && + (false == is_chanx_exist(grids, chanx_coord))) { continue; } /* Estimate the routing tracks required by clock routing only */ @@ -62,9 +63,10 @@ size_t estimate_clock_rr_graph_num_nodes(const DeviceGrid& grids, for (size_t ix = 0; ix < grids.width() - 1; ++ix) { for (size_t iy = 1; iy < grids.height() - 1; ++iy) { vtr::Point chany_coord(ix, iy); - /* Bypass if the routing channel does not exist when through channel are not allowed */ - if ((false == through_channel) - && (false == is_chany_exist(grids, chany_coord))) { + /* Bypass if the routing channel does not exist when through channel are + * not allowed */ + if ((false == through_channel) && + (false == is_chany_exist(grids, chany_coord))) { continue; } /* Estimate the routing tracks required by clock routing only */ @@ -100,8 +102,10 @@ int append_clock_rr_graph(DeviceContext& vpr_device_ctx, /* Estimate the number of nodes and pre-allocate */ size_t orig_num_nodes = vpr_device_ctx.rr_graph.num_nodes(); - size_t num_clock_nodes = estimate_clock_rr_graph_num_nodes(vpr_device_ctx.grid, vpr_device_ctx.arch->through_channel, clk_ntwk); - vpr_device_ctx.rr_graph_builder.reserve_nodes(num_clock_nodes + orig_num_nodes); + size_t num_clock_nodes = estimate_clock_rr_graph_num_nodes( + vpr_device_ctx.grid, vpr_device_ctx.arch->through_channel, clk_ntwk); + vpr_device_ctx.rr_graph_builder.reserve_nodes(num_clock_nodes + + orig_num_nodes); /* TODO: Add clock nodes */ @@ -111,10 +115,11 @@ int append_clock_rr_graph(DeviceContext& vpr_device_ctx, /* TODO: Sanity checks */ /* Report number of added clock nodes and edges */ - VTR_LOGV( - verbose, - "Appended %lu clock nodes (+%.2f%) and %lu clock edges to routing resource graph.\n", - num_clock_nodes, (float)(num_clock_nodes / orig_num_nodes), num_clock_edges); + VTR_LOGV(verbose, + "Appended %lu clock nodes (+%.2f%) and %lu clock edges to routing " + "resource graph.\n", + num_clock_nodes, (float)(num_clock_nodes / orig_num_nodes), + num_clock_edges); return CMD_EXEC_SUCCESS; } From 06f77d043502b39c407e3b6f99b3da596e499d7f Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 25 Feb 2023 22:59:07 -0800 Subject: [PATCH 028/166] [core] dev --- .../src/annotation/append_clock_rr_graph.cpp | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/openfpga/src/annotation/append_clock_rr_graph.cpp b/openfpga/src/annotation/append_clock_rr_graph.cpp index 2e29c4ad3..389f3b8e4 100644 --- a/openfpga/src/annotation/append_clock_rr_graph.cpp +++ b/openfpga/src/annotation/append_clock_rr_graph.cpp @@ -77,6 +77,42 @@ static size_t estimate_clock_rr_graph_num_nodes(const DeviceGrid& grids, return num_nodes; } +/******************************************************************** + * 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) + *******************************************************************/ +static void add_rr_graph_clock_nodes(const DeviceGrid& grids, + const bool& through_channel, + const ClockNetwork& clk_ntwk) { + /* Add X-direction clock nodes */ + for (size_t iy = 0; iy < grids.height() - 1; ++iy) { + for (size_t ix = 1; ix < grids.width() - 1; ++ix) { + vtr::Point chanx_coord(ix, iy); + /* Bypass if the routing channel does not exist when through channels are + * not allowed */ + if ((false == through_channel) && + (false == is_chanx_exist(grids, chanx_coord))) { + continue; + } + } + } + + /* Add Y-direction clock nodes */ + for (size_t ix = 0; ix < grids.width() - 1; ++ix) { + for (size_t iy = 1; iy < grids.height() - 1; ++iy) { + vtr::Point chany_coord(ix, iy); + /* Bypass if the routing channel does not exist when through channel are + * not allowed */ + if ((false == through_channel) && + (false == is_chany_exist(grids, chany_coord))) { + continue; + } + } + } +} + /******************************************************************** * Append a programmable clock network to an existing routing resource graph * This function will do the following jobs: @@ -108,6 +144,10 @@ int append_clock_rr_graph(DeviceContext& vpr_device_ctx, orig_num_nodes); /* TODO: Add clock nodes */ + add_rr_graph_clock_nodes(vpr_device_ctx.grid, + vpr_device_ctx.arch->through_channel, clk_ntwk); + VTR_ASSERT(num_clock_nodes + orig_num_nodes == + vpr_device_ctx.rr_graph.num_nodes()); /* TODO: Add edges between clock nodes*/ size_t num_clock_edges = 0; From 3db5acfb37aa9df935e4b645d5d21c86592b54c4 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 26 Feb 2023 12:40:13 -0800 Subject: [PATCH 029/166] [core] dev --- .../src/base/clock_network.cpp | 41 +++++++++++++++++-- .../src/base/clock_network.h | 4 +- .../src/annotation/append_clock_rr_graph.cpp | 38 ++++++++++++++++- 3 files changed, 77 insertions(+), 6 deletions(-) diff --git a/libs/libclkarchopenfpga/src/base/clock_network.cpp b/libs/libclkarchopenfpga/src/base/clock_network.cpp index 1625578bb..4cc8e7257 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.cpp +++ b/libs/libclkarchopenfpga/src/base/clock_network.cpp @@ -62,19 +62,54 @@ Direction ClockNetwork::spine_direction(const ClockSpineId& spine_id) const { size_t ClockNetwork::num_tracks(const ClockTreeId& tree_id, const ClockLevelId& level, - const t_rr_type& direction) const { + const t_rr_type& track_type) const { size_t num_tracks = 0; + /* 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 + */ + std::map dir_flags; + dir_flags[Direction::INC] = false; + dir_flags[Direction::DEC] = false; for (ClockSpineId curr_spine : spines(tree_id)) { if (spine_levels_[curr_spine] != size_t(level)) { continue; } - if (spine_track_type(curr_spine) == direction) { - num_tracks++; + if (spine_track_type(curr_spine) == track_type) { + if (!dir_flags[spine_direction(curr_spine)]) { + num_tracks += tree_width(spine_parent_trees_[curr_spine]); + dir_flags[spine_direction(curr_spine)] = true; + } } } return num_tracks; } +size_t ClockNetwork::num_tracks(const ClockTreeId& tree_id, + const ClockLevelId& level, + const t_rr_type& track_type, + const Direction& direction) const { + size_t num_tracks = 0; + /* 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) { + num_tracks += tree_width(spine_parent_trees_[curr_spine]); + dir_flags = true; + } + } + } + return num_tracks; +} + + std::string ClockNetwork::default_segment_name() const { return default_segment_name_; } diff --git a/libs/libclkarchopenfpga/src/base/clock_network.h b/libs/libclkarchopenfpga/src/base/clock_network.h index acbe238d4..6d973f6a4 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.h +++ b/libs/libclkarchopenfpga/src/base/clock_network.h @@ -58,7 +58,9 @@ class ClockNetwork { /* Return the number of routing tracks required by a selected clock tree at a * given level and direction */ size_t num_tracks(const ClockTreeId& tree_id, const ClockLevelId& level, - const t_rr_type& direction) const; + const t_rr_type& track_type) const; + size_t num_tracks(const ClockTreeId& tree_id, const ClockLevelId& level, + const t_rr_type& track_type, const Direction& direction) const; std::string default_segment_name() const; std::string default_switch_name() const; std::string tree_name(const ClockTreeId& tree_id) const; diff --git a/openfpga/src/annotation/append_clock_rr_graph.cpp b/openfpga/src/annotation/append_clock_rr_graph.cpp index 389f3b8e4..f8abc64b6 100644 --- a/openfpga/src/annotation/append_clock_rr_graph.cpp +++ b/openfpga/src/annotation/append_clock_rr_graph.cpp @@ -77,13 +77,45 @@ static size_t estimate_clock_rr_graph_num_nodes(const DeviceGrid& grids, return num_nodes; } +/******************************************************************** + * Add clock nodes to a routing resource graph + * For each tree and level of the tree, add a number of clock nodes + * with direction, ptc and coordinates etc. + *******************************************************************/ +static size_t add_rr_graph_clock_nodes(RRGraphBuilder& rr_graph_builder, + const RRGraphView& rr_graph_view, + const ClockNetwork& clk_ntwk, + const vtr::Point chan_coord, + const t_rr_type& chan_type) { + size_t orig_chan_width = rr_graph_view.node_lookup().find_channel_nodes(chan_coord.x(), chan_coord.y(), chan_type).size(); + size_t curr_node_ptc = orig_chan_width; + + 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) { + 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); + rr_graph_builder.set_node_capacity(clk_node, 1); + /* 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 */ + /* Update ptc count and go to next */ + curr_node_ptc++; + } + } + } + } +} + /******************************************************************** * 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) *******************************************************************/ -static void add_rr_graph_clock_nodes(const DeviceGrid& grids, +static void add_rr_graph_clock_nodes(RRGraphBuilder& rr_graph_builder, + const RRGraphView& rr_graph_view, + const DeviceGrid& grids, const bool& through_channel, const ClockNetwork& clk_ntwk) { /* Add X-direction clock nodes */ @@ -96,6 +128,7 @@ static void add_rr_graph_clock_nodes(const DeviceGrid& grids, (false == is_chanx_exist(grids, chanx_coord))) { continue; } + add_rr_graph_clock_nodes(rr_graph_builder, rr_graph_view, clk_ntwk, chanx_coord, CHANX); } } @@ -109,6 +142,7 @@ static void add_rr_graph_clock_nodes(const DeviceGrid& grids, (false == is_chany_exist(grids, chany_coord))) { continue; } + add_rr_graph_clock_nodes(rr_graph_builder, rr_graph_view, clk_ntwk, chany_coord, CHANY); } } } @@ -144,7 +178,7 @@ int append_clock_rr_graph(DeviceContext& vpr_device_ctx, orig_num_nodes); /* TODO: Add clock nodes */ - add_rr_graph_clock_nodes(vpr_device_ctx.grid, + add_rr_graph_clock_nodes(vpr_device_ctx.rr_graph_builder, 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 == vpr_device_ctx.rr_graph.num_nodes()); From 75773ddd4e319d40cfd1e6db3b5e5cfd3eaa5a11 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 26 Feb 2023 12:46:29 -0800 Subject: [PATCH 030/166] [code] format --- .../src/base/clock_network.cpp | 11 +++--- .../src/base/clock_network.h | 3 +- .../src/annotation/append_clock_rr_graph.cpp | 39 ++++++++++++------- 3 files changed, 33 insertions(+), 20 deletions(-) diff --git a/libs/libclkarchopenfpga/src/base/clock_network.cpp b/libs/libclkarchopenfpga/src/base/clock_network.cpp index 4cc8e7257..a4ed7801c 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.cpp +++ b/libs/libclkarchopenfpga/src/base/clock_network.cpp @@ -65,8 +65,9 @@ size_t ClockNetwork::num_tracks(const ClockTreeId& tree_id, const t_rr_type& track_type) const { size_t num_tracks = 0; /* 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 + * 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 */ std::map dir_flags; dir_flags[Direction::INC] = false; @@ -91,8 +92,9 @@ size_t ClockNetwork::num_tracks(const ClockTreeId& tree_id, const Direction& direction) const { size_t num_tracks = 0; /* 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 + * 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)) { @@ -109,7 +111,6 @@ size_t ClockNetwork::num_tracks(const ClockTreeId& tree_id, return num_tracks; } - std::string ClockNetwork::default_segment_name() const { return default_segment_name_; } diff --git a/libs/libclkarchopenfpga/src/base/clock_network.h b/libs/libclkarchopenfpga/src/base/clock_network.h index 6d973f6a4..8be76ad1e 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.h +++ b/libs/libclkarchopenfpga/src/base/clock_network.h @@ -60,7 +60,8 @@ class ClockNetwork { size_t num_tracks(const ClockTreeId& tree_id, const ClockLevelId& level, const t_rr_type& track_type) const; size_t num_tracks(const ClockTreeId& tree_id, const ClockLevelId& level, - const t_rr_type& track_type, const Direction& direction) const; + const t_rr_type& track_type, + const Direction& direction) const; std::string default_segment_name() const; std::string default_switch_name() const; std::string tree_name(const ClockTreeId& tree_id) const; diff --git a/openfpga/src/annotation/append_clock_rr_graph.cpp b/openfpga/src/annotation/append_clock_rr_graph.cpp index f8abc64b6..f89272ecd 100644 --- a/openfpga/src/annotation/append_clock_rr_graph.cpp +++ b/openfpga/src/annotation/append_clock_rr_graph.cpp @@ -78,27 +78,35 @@ static size_t estimate_clock_rr_graph_num_nodes(const DeviceGrid& grids, } /******************************************************************** - * Add clock nodes to a routing resource graph + * Add clock nodes to a routing resource graph * For each tree and level of the tree, add a number of clock nodes * with direction, ptc and coordinates etc. *******************************************************************/ -static size_t add_rr_graph_clock_nodes(RRGraphBuilder& rr_graph_builder, - const RRGraphView& rr_graph_view, - const ClockNetwork& clk_ntwk, - const vtr::Point chan_coord, - const t_rr_type& chan_type) { - size_t orig_chan_width = rr_graph_view.node_lookup().find_channel_nodes(chan_coord.x(), chan_coord.y(), chan_type).size(); +static void add_rr_graph_clock_nodes(RRGraphBuilder& rr_graph_builder, + const RRGraphView& rr_graph_view, + const ClockNetwork& clk_ntwk, + const vtr::Point chan_coord, + const t_rr_type& chan_type) { + size_t orig_chan_width = + rr_graph_view.node_lookup() + .find_channel_nodes(chan_coord.x(), chan_coord.y(), chan_type) + .size(); size_t curr_node_ptc = orig_chan_width; 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) { - RRNodeId clk_node = rr_graph_builder.create_node(chan_coord.x(), chan_coord.y(), chan_type, curr_node_ptc); + for (size_t itrack = 0; + itrack < clk_ntwk.num_tracks(itree, ilvl, chan_type, node_dir); + ++itrack) { + 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); rr_graph_builder.set_node_capacity(clk_node, 1); - /* 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 */ + /* 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 + */ /* Update ptc count and go to next */ curr_node_ptc++; } @@ -128,7 +136,8 @@ static void add_rr_graph_clock_nodes(RRGraphBuilder& rr_graph_builder, (false == is_chanx_exist(grids, chanx_coord))) { continue; } - add_rr_graph_clock_nodes(rr_graph_builder, rr_graph_view, clk_ntwk, chanx_coord, CHANX); + add_rr_graph_clock_nodes(rr_graph_builder, rr_graph_view, clk_ntwk, + chanx_coord, CHANX); } } @@ -142,7 +151,8 @@ static void add_rr_graph_clock_nodes(RRGraphBuilder& rr_graph_builder, (false == is_chany_exist(grids, chany_coord))) { continue; } - add_rr_graph_clock_nodes(rr_graph_builder, rr_graph_view, clk_ntwk, chany_coord, CHANY); + add_rr_graph_clock_nodes(rr_graph_builder, rr_graph_view, clk_ntwk, + chany_coord, CHANY); } } } @@ -178,7 +188,8 @@ int append_clock_rr_graph(DeviceContext& vpr_device_ctx, orig_num_nodes); /* TODO: Add clock nodes */ - add_rr_graph_clock_nodes(vpr_device_ctx.rr_graph_builder, vpr_device_ctx.rr_graph, vpr_device_ctx.grid, + add_rr_graph_clock_nodes(vpr_device_ctx.rr_graph_builder, + 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 == vpr_device_ctx.rr_graph.num_nodes()); From 4bd952027f81e26dede409478de4bf506c63bf07 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 26 Feb 2023 15:31:07 -0800 Subject: [PATCH 031/166] [core] dev --- .../src/annotation/append_clock_rr_graph.cpp | 99 ++++++++++++++++++- 1 file changed, 94 insertions(+), 5 deletions(-) diff --git a/openfpga/src/annotation/append_clock_rr_graph.cpp b/openfpga/src/annotation/append_clock_rr_graph.cpp index f89272ecd..ae56a41ed 100644 --- a/openfpga/src/annotation/append_clock_rr_graph.cpp +++ b/openfpga/src/annotation/append_clock_rr_graph.cpp @@ -82,7 +82,7 @@ static size_t estimate_clock_rr_graph_num_nodes(const DeviceGrid& grids, * For each tree and level of the tree, add a number of clock nodes * with direction, ptc and coordinates etc. *******************************************************************/ -static void add_rr_graph_clock_nodes(RRGraphBuilder& rr_graph_builder, +static void add_rr_graph_block_clock_nodes(RRGraphBuilder& rr_graph_builder, const RRGraphView& rr_graph_view, const ClockNetwork& clk_ntwk, const vtr::Point chan_coord, @@ -103,6 +103,7 @@ static void add_rr_graph_clock_nodes(RRGraphBuilder& rr_graph_builder, chan_coord.x(), chan_coord.y(), chan_type, curr_node_ptc); rr_graph_builder.set_node_direction(clk_node, node_dir); rr_graph_builder.set_node_capacity(clk_node, 1); + /* TODO: need to set cost_index using segment id */ /* 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 @@ -115,6 +116,7 @@ static void add_rr_graph_clock_nodes(RRGraphBuilder& rr_graph_builder, } } + /******************************************************************** * Add clock nodes one by one to the routing resource graph. * Assign node-level attributes properly @@ -136,7 +138,7 @@ static void add_rr_graph_clock_nodes(RRGraphBuilder& rr_graph_builder, (false == is_chanx_exist(grids, chanx_coord))) { continue; } - add_rr_graph_clock_nodes(rr_graph_builder, rr_graph_view, clk_ntwk, + add_rr_graph_block_clock_nodes(rr_graph_builder, rr_graph_view, clk_ntwk, chanx_coord, CHANX); } } @@ -151,12 +153,91 @@ static void add_rr_graph_clock_nodes(RRGraphBuilder& rr_graph_builder, (false == is_chany_exist(grids, chany_coord))) { continue; } - add_rr_graph_clock_nodes(rr_graph_builder, rr_graph_view, clk_ntwk, + add_rr_graph_block_clock_nodes(rr_graph_builder, rr_graph_view, clk_ntwk, chany_coord, CHANY); } } } +/******************************************************************** + * Add edges for the clock nodes in a given connection block + *******************************************************************/ +void add_rr_graph_block_clock_edges(RRGraphBuilder& rr_graph_builder, + const RRGraphView& rr_graph_view, + const ClockNetwork& clk_ntwk, + const vtr::Point chan_coord, + const t_rr_type& chan_type) { + 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 */ + /* TODO: find the fan-out clock node through lookup */ + /* TODO: Create edges */ + } + } + } + } +} + + +/******************************************************************** + * Add edges to interconnect clock nodes + * Walk through the routing tracks in each connection block (driver nodes) + * and add edge to their fan-out clock nodes + * Note that + * - clock nodes at the same level of a clock tree can only go straight + * - clock nodes can only drive clock nodes belong to the same clock index (a clock tree may contain multiple clocks) + * - clock nodes can only drive clock nodes (by making a turn, straight connection is not allowed) which are 1 level lower in the same clock tree with the same clock index + * For example + * + * clk0_lvl1_chany[1][2] + * ^ + * | + * clk0_lvl0_chanx[1][1] -->---------+--->---> clk0_lvl0_chanx[2][1] + * | + * v + * clk0_lvl1_chany[1][1] + *******************************************************************/ +void add_rr_graph_clock_edges(RRGraphBuilder& rr_graph_builder, + const RRGraphView& rr_graph_view, + const DeviceGrid& grids, + const bool& through_channel, + const ClockNetwork& clk_ntwk) { + /* Add edges which is driven by X-direction clock routing tracks */ + for (size_t iy = 0; iy < grids.height() - 1; ++iy) { + for (size_t ix = 1; ix < grids.width() - 1; ++ix) { + vtr::Point chanx_coord(ix, iy); + /* Bypass if the routing channel does not exist when through channels are + * not allowed */ + if ((false == through_channel) && + (false == is_chanx_exist(grids, chanx_coord))) { + continue; + } + add_rr_graph_block_clock_edges(rr_graph_builder, rr_graph_view, clk_ntwk, + chanx_coord, CHANX); + } + } + + /* Add edges which is driven by Y-direction clock routing tracks */ + for (size_t ix = 0; ix < grids.width() - 1; ++ix) { + for (size_t iy = 1; iy < grids.height() - 1; ++iy) { + vtr::Point chany_coord(ix, iy); + /* Bypass if the routing channel does not exist when through channel are + * not allowed */ + if ((false == through_channel) && + (false == is_chany_exist(grids, chany_coord))) { + continue; + } + add_rr_graph_block_clock_edges(rr_graph_builder, rr_graph_view, clk_ntwk, + chany_coord, CHANY); + } + } + +} + /******************************************************************** * Append a programmable clock network to an existing routing resource graph * This function will do the following jobs: @@ -178,7 +259,12 @@ int append_clock_rr_graph(DeviceContext& vpr_device_ctx, return CMD_EXEC_SUCCESS; } - /* TODO: report any clock structure we do not support yet! */ + /* Report any clock structure we do not support yet! */ + if (clk_ntwk.num_trees() > 1) { + VTR_LOG( + "Currently only support 1 clock tree in programmable clock architecture\nPlease update your clock architecture definition\n"); + return CMD_EXEC_FATAL_ERROR; + } /* Estimate the number of nodes and pre-allocate */ size_t orig_num_nodes = vpr_device_ctx.rr_graph.num_nodes(); @@ -187,7 +273,7 @@ int append_clock_rr_graph(DeviceContext& vpr_device_ctx, vpr_device_ctx.rr_graph_builder.reserve_nodes(num_clock_nodes + orig_num_nodes); - /* TODO: Add clock nodes */ + /* Add clock nodes */ add_rr_graph_clock_nodes(vpr_device_ctx.rr_graph_builder, vpr_device_ctx.rr_graph, vpr_device_ctx.grid, vpr_device_ctx.arch->through_channel, clk_ntwk); @@ -196,6 +282,9 @@ 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, + vpr_device_ctx.rr_graph, vpr_device_ctx.grid, + vpr_device_ctx.arch->through_channel, clk_ntwk); /* TODO: Sanity checks */ From 780fc0f26d2d514265e8f9985ce6b6f5177ba27d Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 26 Feb 2023 18:03:55 -0800 Subject: [PATCH 032/166] [core] developing validators and annotate rr_segment for clock arch --- libs/libclkarchopenfpga/CMakeLists.txt | 1 + .../src/base/clock_network.cpp | 51 +++++++++++++++++-- .../src/base/clock_network.h | 14 ++++- .../src/utils/clock_network_utils.cpp | 29 +++++++++++ .../src/utils/clock_network_utils.h | 21 ++++++++ .../src/annotation/append_clock_rr_graph.cpp | 36 ++++++------- .../src/base/openfpga_read_arch_template.h | 9 ++++ 7 files changed, 139 insertions(+), 22 deletions(-) create mode 100644 libs/libclkarchopenfpga/src/utils/clock_network_utils.cpp create mode 100644 libs/libclkarchopenfpga/src/utils/clock_network_utils.h diff --git a/libs/libclkarchopenfpga/CMakeLists.txt b/libs/libclkarchopenfpga/CMakeLists.txt index 07283a792..b465429cd 100644 --- a/libs/libclkarchopenfpga/CMakeLists.txt +++ b/libs/libclkarchopenfpga/CMakeLists.txt @@ -20,6 +20,7 @@ set_target_properties(libclkarchopenfpga PROPERTIES PREFIX "") #Avoid extra 'lib #Specify link-time dependancies target_link_libraries(libclkarchopenfpga libopenfpgautil + libopenfpgashell libarchopenfpga librrgraph libvtrutil diff --git a/libs/libclkarchopenfpga/src/base/clock_network.cpp b/libs/libclkarchopenfpga/src/base/clock_network.cpp index a4ed7801c..9de997e6c 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.cpp +++ b/libs/libclkarchopenfpga/src/base/clock_network.cpp @@ -14,7 +14,11 @@ namespace openfpga { // Begin namespace openfpga /************************************************************************ * Constructors ***********************************************************************/ -ClockNetwork::ClockNetwork() { is_dirty_ = true; } +ClockNetwork::ClockNetwork() { + default_segment_id_ = RRSegmentId::INVALID(); + default_switch_id_ = RRSwitchId::INVALID(); + is_dirty_ = true; +} /************************************************************************ * Public Accessors : aggregates @@ -115,6 +119,10 @@ std::string ClockNetwork::default_segment_name() const { return default_segment_name_; } +RRSegmentId ClockNetwork::default_segment() const { + return default_segment_id_; +} + std::string ClockNetwork::default_switch_name() const { return default_switch_name_; } @@ -227,6 +235,10 @@ void ClockNetwork::reserve_trees(const size_t& num_trees) { tree_top_spines_.reserve(num_trees); } +void ClockNetwork::set_default_segment(const RRSegmentId& seg_id) { + default_segment_id_ = seg_id; +} + void ClockNetwork::set_default_segment_name(const std::string& name) { default_segment_name_ = name; } @@ -339,13 +351,46 @@ void ClockNetwork::add_spine_switch_point(const ClockSpineId& spine_id, } bool ClockNetwork::link() { - is_dirty_ = true; for (ClockTreeId tree_id : trees()) { if (!link_tree(tree_id)) { return false; } } - is_dirty_ = false; + return true; +} + +bool ClockNetwork::validate_tree() const { + for (ClockTreeId tree_id : trees()) { + for (ClockSpineId spine_id : spines(tree_id)) { + for (ClockSwitchPointId switch_point_id : spine_switch_points(spine_id)) { + if (!valid_spine_switch_point_id(spine_id, switch_point_id)) { + VTR_LOG_ERROR( + "Spine '%s' contains invalid switching point (%lu, %lu)\n", + spine_name(spine_id).c_str(), + spine_switch_point(spine_id, switch_point_id).x(), + spine_switch_point(spine_id, switch_point_id).y()); + return false; + } + } + if (!valid_spine_start_end_points(spine_id)) { + VTR_LOG_ERROR( + "Spine '%s' contains invalid starting point (%lu, %lu) or ending " + "point (%lu, %lu)\n", + spine_name(spine_id).c_str(), spine_start_point(spine_id).x(), + spine_start_point(spine_id).y(), spine_end_point(spine_id).x(), + spine_end_point(spine_id).y()); + return false; + } + } + } + return true; +} + +bool ClockNetwork::validate() const { + is_dirty_ = true; + if (default_segment_id_ && default_switch_id_ && validate_tree()) { + is_dirty_ = false; + } return true; } diff --git a/libs/libclkarchopenfpga/src/base/clock_network.h b/libs/libclkarchopenfpga/src/base/clock_network.h index 8be76ad1e..6f00dd3ca 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.h +++ b/libs/libclkarchopenfpga/src/base/clock_network.h @@ -62,6 +62,9 @@ class ClockNetwork { size_t num_tracks(const ClockTreeId& tree_id, const ClockLevelId& level, const t_rr_type& track_type, const Direction& direction) const; + /* Return the id of default routing segment, use this to find detailed segment + * information from RRGraph */ + RRSegmentId default_segment() const; std::string default_segment_name() const; std::string default_switch_name() const; std::string tree_name(const ClockTreeId& tree_id) const; @@ -106,6 +109,7 @@ class ClockNetwork { void reserve_spines(const size_t& num_spines); /* Reserve a number of trees to be memory efficent */ void reserve_trees(const size_t& num_trees); + void set_default_segment(const RRSegmentId& seg_id); void set_default_segment_name(const std::string& name); void set_default_switch_name(const std::string& name); /* Create a new tree, by default the tree can accomodate only 1 clock signal; @@ -145,6 +149,14 @@ class ClockNetwork { * X-direction spine or a Y-direction spine. Diagonal spine is not supported! */ bool valid_spine_start_end_points(const ClockSpineId& spine_id) const; + /* Validate the internal data. Required to ensure clean data before usage. If + * validation is successful, is_valid() will return true */ + bool validate() const; + + private: /* Public invalidators/validators */ + /* Ensure tree data is clean. All the spines are valid, and switch points are + * valid */ + bool validate_tree() const; private: /* Private mutators */ /* Build internal links between spines under a given tree */ @@ -189,7 +201,7 @@ class ClockNetwork { std::map spine_name2id_map_; /* Flags */ - bool is_dirty_; + mutable bool is_dirty_; }; } // End of namespace openfpga diff --git a/libs/libclkarchopenfpga/src/utils/clock_network_utils.cpp b/libs/libclkarchopenfpga/src/utils/clock_network_utils.cpp new file mode 100644 index 000000000..b58daf418 --- /dev/null +++ b/libs/libclkarchopenfpga/src/utils/clock_network_utils.cpp @@ -0,0 +1,29 @@ +#include "clock_network_utils.h" + +#include "command_exit_codes.h" +#include "vtr_assert.h" +#include "vtr_time.h" + +namespace openfpga { // Begin namespace openfpga + +/******************************************************************** + * Link all the segments that are defined in a routing resource graph to a given + *clock network + *******************************************************************/ +int link_clock_network_rr_segments(ClockNetwork& clk_ntwk, + const RRGraphView& rr_graph) { + /* default segment id */ + std::string default_segment_name = clk_ntwk.default_segment_name(); + for (size_t rr_seg_id = 0; rr_seg_id < rr_graph.num_rr_segments(); + ++rr_seg_id) { + if (rr_graph.rr_segments(RRSegmentId(rr_seg_id)).name == + default_segment_name) { + clk_ntwk.set_default_segment(RRSegmentId(rr_seg_id)); + return CMD_EXEC_SUCCESS; + } + } + + return CMD_EXEC_FATAL_ERROR; +} + +} // End of namespace openfpga diff --git a/libs/libclkarchopenfpga/src/utils/clock_network_utils.h b/libs/libclkarchopenfpga/src/utils/clock_network_utils.h new file mode 100644 index 000000000..faa348989 --- /dev/null +++ b/libs/libclkarchopenfpga/src/utils/clock_network_utils.h @@ -0,0 +1,21 @@ +#ifndef CLOCK_NETWORK_UTILS_H +#define CLOCK_NETWORK_UTILS_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +#include "clock_network.h" +#include "rr_graph_view.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ + +namespace openfpga { // Begin namespace openfpga + +int link_clock_network_rr_segments(ClockNetwork& clk_ntwk, + const RRGraphView& rr_graph); + +} // End of namespace openfpga + +#endif diff --git a/openfpga/src/annotation/append_clock_rr_graph.cpp b/openfpga/src/annotation/append_clock_rr_graph.cpp index ae56a41ed..ee2fdf5f6 100644 --- a/openfpga/src/annotation/append_clock_rr_graph.cpp +++ b/openfpga/src/annotation/append_clock_rr_graph.cpp @@ -83,10 +83,10 @@ 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, - const RRGraphView& rr_graph_view, - const ClockNetwork& clk_ntwk, - const vtr::Point chan_coord, - const t_rr_type& chan_type) { + const RRGraphView& rr_graph_view, + const ClockNetwork& clk_ntwk, + const vtr::Point chan_coord, + const t_rr_type& chan_type) { size_t orig_chan_width = rr_graph_view.node_lookup() .find_channel_nodes(chan_coord.x(), chan_coord.y(), chan_type) @@ -116,7 +116,6 @@ 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 @@ -139,7 +138,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, - chanx_coord, CHANX); + chanx_coord, CHANX); } } @@ -154,7 +153,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); + chany_coord, CHANY); } } } @@ -163,10 +162,10 @@ static void add_rr_graph_clock_nodes(RRGraphBuilder& rr_graph_builder, * Add edges for the clock nodes in a given connection block *******************************************************************/ void add_rr_graph_block_clock_edges(RRGraphBuilder& rr_graph_builder, - const RRGraphView& rr_graph_view, - const ClockNetwork& clk_ntwk, - const vtr::Point chan_coord, - const t_rr_type& chan_type) { + const RRGraphView& rr_graph_view, + const ClockNetwork& clk_ntwk, + const vtr::Point chan_coord, + const t_rr_type& chan_type) { for (auto itree : clk_ntwk.trees()) { for (auto ilvl : clk_ntwk.levels(itree)) { for (auto node_dir : {Direction::INC, Direction::DEC}) { @@ -182,16 +181,17 @@ void add_rr_graph_block_clock_edges(RRGraphBuilder& rr_graph_builder, } } - /******************************************************************** * Add edges to interconnect clock nodes * Walk through the routing tracks in each connection block (driver nodes) * and add edge to their fan-out clock nodes - * Note that + * Note that * - clock nodes at the same level of a clock tree can only go straight - * - clock nodes can only drive clock nodes belong to the same clock index (a clock tree may contain multiple clocks) - * - clock nodes can only drive clock nodes (by making a turn, straight connection is not allowed) which are 1 level lower in the same clock tree with the same clock index - * For example + * - clock nodes can only drive clock nodes belong to the same clock index (a + *clock tree may contain multiple clocks) + * - clock nodes can only drive clock nodes (by making a turn, straight + *connection is not allowed) which are 1 level lower in the same clock tree with + *the same clock index For example * * clk0_lvl1_chany[1][2] * ^ @@ -235,7 +235,6 @@ void add_rr_graph_clock_edges(RRGraphBuilder& rr_graph_builder, chany_coord, CHANY); } } - } /******************************************************************** @@ -262,7 +261,8 @@ int append_clock_rr_graph(DeviceContext& vpr_device_ctx, /* Report any clock structure we do not support yet! */ if (clk_ntwk.num_trees() > 1) { VTR_LOG( - "Currently only support 1 clock tree in programmable clock architecture\nPlease update your clock architecture definition\n"); + "Currently only support 1 clock tree in programmable clock " + "architecture\nPlease update your clock architecture definition\n"); return CMD_EXEC_FATAL_ERROR; } diff --git a/openfpga/src/base/openfpga_read_arch_template.h b/openfpga/src/base/openfpga_read_arch_template.h index 9003642ba..c60b91452 100644 --- a/openfpga/src/base/openfpga_read_arch_template.h +++ b/openfpga/src/base/openfpga_read_arch_template.h @@ -7,6 +7,7 @@ #include "check_circuit_library.h" #include "check_tile_annotation.h" #include "circuit_library_utils.h" +#include "clock_network_utils.h" #include "command.h" #include "command_context.h" #include "command_exit_codes.h" @@ -236,6 +237,14 @@ int read_openfpga_clock_arch_template(T& openfpga_context, const Command& cmd, read_xml_clock_network(arch_file_name.c_str()); /* Build internal links */ openfpga_context.mutable_clock_arch().link(); + link_clock_network_rr_segments(openfpga_context.mutable_clock_arch(), + g_vpr_ctx.device().rr_graph); + /* Ensure clean data */ + openfpga_context.clock_arch().validate(); + if (!openfpga_context.clock_arch().is_valid()) { + VTR_LOG_ERROR("Pre-checking clock architecture failed!"); + return CMD_EXEC_FATAL_ERROR; + } /* TODO: should identify the error code from internal function execution */ return CMD_EXEC_SUCCESS; From b9e5ae7ae9796269e548efbf8aa4a477ca7c50e1 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 26 Feb 2023 18:31:08 -0800 Subject: [PATCH 033/166] [core] developing --- openfpga/src/annotation/append_clock_rr_graph.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/openfpga/src/annotation/append_clock_rr_graph.cpp b/openfpga/src/annotation/append_clock_rr_graph.cpp index ee2fdf5f6..ae4c607a2 100644 --- a/openfpga/src/annotation/append_clock_rr_graph.cpp +++ b/openfpga/src/annotation/append_clock_rr_graph.cpp @@ -2,6 +2,7 @@ #include "command_exit_codes.h" #include "rr_graph_builder_utils.h" +#include "rr_graph_cost.h" #include "vtr_assert.h" #include "vtr_geometry.h" #include "vtr_log.h" @@ -86,7 +87,8 @@ static void add_rr_graph_block_clock_nodes(RRGraphBuilder& rr_graph_builder, const RRGraphView& rr_graph_view, const ClockNetwork& clk_ntwk, const vtr::Point chan_coord, - const t_rr_type& chan_type) { + const t_rr_type& chan_type, + const int& cost_index_offset) { size_t orig_chan_width = rr_graph_view.node_lookup() .find_channel_nodes(chan_coord.x(), chan_coord.y(), chan_type) @@ -103,7 +105,8 @@ static void add_rr_graph_block_clock_nodes(RRGraphBuilder& rr_graph_builder, chan_coord.x(), chan_coord.y(), chan_type, curr_node_ptc); rr_graph_builder.set_node_direction(clk_node, node_dir); rr_graph_builder.set_node_capacity(clk_node, 1); - /* TODO: need to set cost_index using segment id */ + /* set cost_index using segment id */ + rr_graph_builder.set_node_cost_index(clk_node, RRIndexedDataId(cost_index_offset + 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 @@ -138,7 +141,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, - chanx_coord, CHANX); + chanx_coord, CHANX, CHANX_COST_INDEX_START); } } @@ -153,7 +156,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); + chany_coord, CHANY, CHANX_COST_INDEX_START + rr_graph_view.num_rr_segments()); } } } From db36f87dfa838a925d5e0cea0fc55752a4e1f15e Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 26 Feb 2023 18:39:53 -0800 Subject: [PATCH 034/166] [core] enhance clock tree arch validation --- libs/libclkarchopenfpga/src/base/clock_network.cpp | 12 ++++++++++++ openfpga/src/annotation/append_clock_rr_graph.cpp | 12 ++++++++---- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/libs/libclkarchopenfpga/src/base/clock_network.cpp b/libs/libclkarchopenfpga/src/base/clock_network.cpp index 9de997e6c..d89492c58 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.cpp +++ b/libs/libclkarchopenfpga/src/base/clock_network.cpp @@ -381,6 +381,18 @@ bool ClockNetwork::validate_tree() const { spine_end_point(spine_id).y()); return false; } + /* parent spine and child spine should be in different track type */ + ClockSpineId parent_spine = spine_parents_[spine_id]; + if (valid_spine_id(parent_spine)) { + if (spine_track_type(spine_id) == spine_track_type(parent_spine)) { + VTR_LOG_ERROR( + "Spine '%s' and its parent '%s' are in the same track type (both " + "horizental or vertical). Expect they are othorgonal (one " + "horizental and one vertical)!\n", + spine_name(spine_id).c_str(), spine_name(parent_spine).c_str()); + return false; + } + } } } return true; diff --git a/openfpga/src/annotation/append_clock_rr_graph.cpp b/openfpga/src/annotation/append_clock_rr_graph.cpp index ae4c607a2..bad9d2074 100644 --- a/openfpga/src/annotation/append_clock_rr_graph.cpp +++ b/openfpga/src/annotation/append_clock_rr_graph.cpp @@ -106,7 +106,9 @@ static void add_rr_graph_block_clock_nodes(RRGraphBuilder& rr_graph_builder, rr_graph_builder.set_node_direction(clk_node, node_dir); rr_graph_builder.set_node_capacity(clk_node, 1); /* set cost_index using segment id */ - rr_graph_builder.set_node_cost_index(clk_node, RRIndexedDataId(cost_index_offset + size_t(clk_ntwk.default_segment()))); + rr_graph_builder.set_node_cost_index( + clk_node, RRIndexedDataId(cost_index_offset + + 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 @@ -141,7 +143,8 @@ 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, - chanx_coord, CHANX, CHANX_COST_INDEX_START); + chanx_coord, CHANX, + CHANX_COST_INDEX_START); } } @@ -155,8 +158,9 @@ static void add_rr_graph_clock_nodes(RRGraphBuilder& rr_graph_builder, (false == is_chany_exist(grids, chany_coord))) { continue; } - add_rr_graph_block_clock_nodes(rr_graph_builder, rr_graph_view, clk_ntwk, - chany_coord, CHANY, CHANX_COST_INDEX_START + rr_graph_view.num_rr_segments()); + add_rr_graph_block_clock_nodes( + rr_graph_builder, rr_graph_view, clk_ntwk, chany_coord, CHANY, + CHANX_COST_INDEX_START + rr_graph_view.num_rr_segments()); } } } From 87a91460827edfcf95f2286dd2bc2f86980130d7 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 26 Feb 2023 22:23:17 -0800 Subject: [PATCH 035/166] [core] adding rr spatial lookup for clock nodes only --- .../src/base/clock_network.cpp | 30 ++++++ .../src/base/clock_network.h | 4 + .../src/base/clock_network_fwd.h | 2 + .../src/base/rr_clock_spatial_lookup.cpp | 99 +++++++++++++++++ .../src/base/rr_clock_spatial_lookup.h | 102 ++++++++++++++++++ .../src/annotation/append_clock_rr_graph.cpp | 40 ++++--- .../src/annotation/append_clock_rr_graph.h | 5 +- openfpga/src/base/openfpga_context.h | 4 + .../src/base/openfpga_link_arch_template.h | 1 + 9 files changed, 269 insertions(+), 18 deletions(-) create mode 100644 libs/libclkarchopenfpga/src/base/rr_clock_spatial_lookup.cpp create mode 100644 libs/libclkarchopenfpga/src/base/rr_clock_spatial_lookup.h diff --git a/libs/libclkarchopenfpga/src/base/clock_network.cpp b/libs/libclkarchopenfpga/src/base/clock_network.cpp index d89492c58..3c2861282 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.cpp +++ b/libs/libclkarchopenfpga/src/base/clock_network.cpp @@ -38,6 +38,36 @@ std::vector ClockNetwork::levels( return ret; } +std::vector ClockNetwork::pins(const ClockTreeId& tree_id, + const ClockLevelId& level, + const t_rr_type& track_type, + const Direction& direction) const { + std::vector 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 ***********************************************************************/ diff --git a/libs/libclkarchopenfpga/src/base/clock_network.h b/libs/libclkarchopenfpga/src/base/clock_network.h index 6f00dd3ca..793da08d5 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.h +++ b/libs/libclkarchopenfpga/src/base/clock_network.h @@ -53,6 +53,10 @@ class ClockNetwork { std::vector levels(const ClockTreeId& tree_id) const; /* Return a list of spine id under a clock tree */ std::vector 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 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 diff --git a/libs/libclkarchopenfpga/src/base/clock_network_fwd.h b/libs/libclkarchopenfpga/src/base/clock_network_fwd.h index a18dc4394..1285f069c 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network_fwd.h +++ b/libs/libclkarchopenfpga/src/base/clock_network_fwd.h @@ -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 ClockLevelId; typedef vtr::StrongId ClockTreeId; +typedef vtr::StrongId ClockTreePinId; typedef vtr::StrongId ClockSpineId; typedef vtr::StrongId ClockSwitchPointId; diff --git a/libs/libclkarchopenfpga/src/base/rr_clock_spatial_lookup.cpp b/libs/libclkarchopenfpga/src/base/rr_clock_spatial_lookup.cpp new file mode 100644 index 000000000..cc6fe98c4 --- /dev/null +++ b/libs/libclkarchopenfpga/src/base/rr_clock_spatial_lookup.cpp @@ -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 diff --git a/libs/libclkarchopenfpga/src/base/rr_clock_spatial_lookup.h b/libs/libclkarchopenfpga/src/base/rr_clock_spatial_lookup.h new file mode 100644 index 000000000..fe5b9e91f --- /dev/null +++ b/libs/libclkarchopenfpga/src/base/rr_clock_spatial_lookup.h @@ -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>>, 2>, 2> rr_node_indices_; +}; + +} // end namespace openfpga + +#endif diff --git a/openfpga/src/annotation/append_clock_rr_graph.cpp b/openfpga/src/annotation/append_clock_rr_graph.cpp index bad9d2074..4e9489803 100644 --- a/openfpga/src/annotation/append_clock_rr_graph.cpp +++ b/openfpga/src/annotation/append_clock_rr_graph.cpp @@ -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 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 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(clk_rr_lookup), vpr_device_ctx.rr_graph, vpr_device_ctx.grid, vpr_device_ctx.arch->through_channel, clk_ntwk); diff --git a/openfpga/src/annotation/append_clock_rr_graph.h b/openfpga/src/annotation/append_clock_rr_graph.h index 703c5f0c7..8f69f37f0 100644 --- a/openfpga/src/annotation/append_clock_rr_graph.h +++ b/openfpga/src/annotation/append_clock_rr_graph.h @@ -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 */ diff --git a/openfpga/src/base/openfpga_context.h b/openfpga/src/base/openfpga_context.h index 5c38cc0b8..baf6464a6 100644 --- a/openfpga/src/base/openfpga_context.h +++ b/openfpga/src/base/openfpga_context.h @@ -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_; diff --git a/openfpga/src/base/openfpga_link_arch_template.h b/openfpga/src/base/openfpga_link_arch_template.h index 7b9197018..0ba411511 100644 --- a/openfpga/src/base/openfpga_link_arch_template.h +++ b/openfpga/src/base/openfpga_link_arch_template.h @@ -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)); } From 009d711ba584fcfe66915e9074c32b3fcfca470c Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 26 Feb 2023 22:23:41 -0800 Subject: [PATCH 036/166] [core] code format --- .../src/base/clock_network.cpp | 12 +- .../src/base/clock_network.h | 10 +- .../src/base/rr_clock_spatial_lookup.cpp | 156 +++++++++-------- .../src/base/rr_clock_spatial_lookup.h | 159 +++++++++--------- .../src/annotation/append_clock_rr_graph.cpp | 65 ++++--- .../src/annotation/append_clock_rr_graph.h | 3 +- openfpga/src/base/openfpga_context.h | 10 +- .../src/base/openfpga_link_arch_template.h | 7 +- 8 files changed, 215 insertions(+), 207 deletions(-) diff --git a/libs/libclkarchopenfpga/src/base/clock_network.cpp b/libs/libclkarchopenfpga/src/base/clock_network.cpp index 3c2861282..dcd6e828f 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.cpp +++ b/libs/libclkarchopenfpga/src/base/clock_network.cpp @@ -38,10 +38,9 @@ std::vector ClockNetwork::levels( return ret; } -std::vector ClockNetwork::pins(const ClockTreeId& tree_id, - const ClockLevelId& level, - const t_rr_type& track_type, - const Direction& direction) const { +std::vector ClockNetwork::pins( + const ClockTreeId& tree_id, const ClockLevelId& level, + const t_rr_type& track_type, const Direction& direction) const { std::vector 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 @@ -56,7 +55,8 @@ std::vector ClockNetwork::pins(const ClockTreeId& tree_id, 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) { + for (size_t i = 0; i < tree_width(spine_parent_trees_[curr_spine]); + ++i) { ret.push_back(ClockTreePinId(i)); } dir_flags = true; @@ -66,8 +66,6 @@ std::vector ClockNetwork::pins(const ClockTreeId& tree_id, return ret; } - - /************************************************************************ * Public Accessors : Basic data query ***********************************************************************/ diff --git a/libs/libclkarchopenfpga/src/base/clock_network.h b/libs/libclkarchopenfpga/src/base/clock_network.h index 793da08d5..60250af86 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.h +++ b/libs/libclkarchopenfpga/src/base/clock_network.h @@ -53,10 +53,12 @@ class ClockNetwork { std::vector levels(const ClockTreeId& tree_id) const; /* Return a list of spine id under a clock tree */ std::vector 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 pins(const ClockTreeId& tree_id, const ClockLevelId& level, - const t_rr_type& track_type, - const Direction& direction) const; + /* Return a list of clock pins in a bus of clock tree at a given level and + * direction */ + std::vector 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 diff --git a/libs/libclkarchopenfpga/src/base/rr_clock_spatial_lookup.cpp b/libs/libclkarchopenfpga/src/base/rr_clock_spatial_lookup.cpp index cc6fe98c4..adbba8399 100644 --- a/libs/libclkarchopenfpga/src/base/rr_clock_spatial_lookup.cpp +++ b/libs/libclkarchopenfpga/src/base/rr_clock_spatial_lookup.cpp @@ -1,99 +1,97 @@ -#include "vtr_assert.h" -#include "vtr_log.h" #include "rr_clock_spatial_lookup.h" -namespace openfpga { // begin namespace openfpga +#include "vtr_assert.h" +#include "vtr_log.h" -RRClockSpatialLookup::RRClockSpatialLookup() { +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; } -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, +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()); + 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_nodes(x, y, direction); - /* Resize on demand finished; Register the node */ - rr_node_indices_[dir][x][y][tree][lvl][pin] = node; + /* 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, +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); + /* 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)}); - } + 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(); - } + for (auto& data : rr_node_indices_) { + data.clear(); + } } -} // end namespace openfpga +} // end namespace openfpga diff --git a/libs/libclkarchopenfpga/src/base/rr_clock_spatial_lookup.h b/libs/libclkarchopenfpga/src/base/rr_clock_spatial_lookup.h index fe5b9e91f..4e1ec0f9b 100644 --- a/libs/libclkarchopenfpga/src/base/rr_clock_spatial_lookup.h +++ b/libs/libclkarchopenfpga/src/base/rr_clock_spatial_lookup.h @@ -1,102 +1,111 @@ #ifndef RR_CLOCK_SPATIAL_LOOKUP_H #define RR_CLOCK_SPATIAL_LOOKUP_H -/** +/** * @file - * @brief This RRClockSpatialLookup class encapsulates + * @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 + * 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 + * 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 "clock_network_fwd.h" +#include "physical_types.h" +#include "rr_graph_fwd.h" +#include "rr_node_types.h" #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 +namespace openfpga { // begin namespace openfpga class RRClockSpatialLookup { - /* -- Constructors -- */ - public: - /* Explicitly define the only way to create an object */ - explicit 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; + /* 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; + /* -- 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) + /* -- 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); + * + * @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(); + /** @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); + 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>>, 2>, 2> rr_node_indices_; + /* -- 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>>, + 2>, + 2> + rr_node_indices_; }; -} // end namespace openfpga +} // end namespace openfpga #endif diff --git a/openfpga/src/annotation/append_clock_rr_graph.cpp b/openfpga/src/annotation/append_clock_rr_graph.cpp index 4e9489803..fe2605c5f 100644 --- a/openfpga/src/annotation/append_clock_rr_graph.cpp +++ b/openfpga/src/annotation/append_clock_rr_graph.cpp @@ -111,7 +111,8 @@ static void add_rr_graph_block_clock_nodes(RRGraphBuilder& rr_graph_builder, /* FIXME: need to set rc_index and cost_index when building the graph * in VTR */ /* 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); + 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++; } @@ -140,9 +141,9 @@ 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, clk_rr_lookup, rr_graph_view, clk_ntwk, - chanx_coord, CHANX, - CHANX_COST_INDEX_START); + add_rr_graph_block_clock_nodes(rr_graph_builder, clk_rr_lookup, + rr_graph_view, clk_ntwk, chanx_coord, + CHANX, CHANX_COST_INDEX_START); } } @@ -157,8 +158,8 @@ static void add_rr_graph_clock_nodes(RRGraphBuilder& rr_graph_builder, continue; } add_rr_graph_block_clock_nodes( - rr_graph_builder, clk_rr_lookup, rr_graph_view, clk_ntwk, chany_coord, CHANY, - CHANX_COST_INDEX_START + rr_graph_view.num_rr_segments()); + rr_graph_builder, clk_rr_lookup, rr_graph_view, clk_ntwk, chany_coord, + CHANY, CHANX_COST_INDEX_START + rr_graph_view.num_rr_segments()); } } } @@ -166,19 +167,17 @@ 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 chan_coord, - const t_rr_type& chan_type) { +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 chan_coord, const t_rr_type& chan_type) { for (auto itree : clk_ntwk.trees()) { for (auto ilvl : clk_ntwk.levels(itree)) { for (auto node_dir : {Direction::INC, Direction::DEC}) { 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); + 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,13 +207,12 @@ 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, - const ClockNetwork& clk_ntwk) { +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, + const ClockNetwork& clk_ntwk) { /* Add edges which is driven by X-direction clock routing tracks */ for (size_t iy = 0; iy < grids.height() - 1; ++iy) { for (size_t ix = 1; ix < grids.width() - 1; ++ix) { @@ -225,8 +223,9 @@ 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, clk_rr_lookup, rr_graph_view, clk_ntwk, - chanx_coord, CHANX); + add_rr_graph_block_clock_edges(rr_graph_builder, clk_rr_lookup, + rr_graph_view, clk_ntwk, chanx_coord, + CHANX); } } @@ -240,8 +239,9 @@ 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, clk_rr_lookup, rr_graph_view, clk_ntwk, - chany_coord, CHANY); + add_rr_graph_block_clock_edges(rr_graph_builder, clk_rr_lookup, + rr_graph_view, clk_ntwk, chany_coord, + CHANY); } } } @@ -256,8 +256,7 @@ void add_rr_graph_clock_edges(RRGraphBuilder& rr_graph_builder, *******************************************************************/ int append_clock_rr_graph(DeviceContext& vpr_device_ctx, RRClockSpatialLookup& clk_rr_lookup, - const ClockNetwork& clk_ntwk, - const bool& verbose) { + const ClockNetwork& clk_ntwk, const bool& verbose) { vtr::ScopedStartFinishTimer timer( "Appending programmable clock network to routing resource graph"); @@ -285,8 +284,7 @@ int append_clock_rr_graph(DeviceContext& vpr_device_ctx, orig_num_nodes); /* Add clock nodes */ - add_rr_graph_clock_nodes(vpr_device_ctx.rr_graph_builder, - clk_rr_lookup, + 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 == @@ -294,10 +292,11 @@ 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(clk_rr_lookup), - vpr_device_ctx.rr_graph, vpr_device_ctx.grid, - vpr_device_ctx.arch->through_channel, clk_ntwk); + add_rr_graph_clock_edges( + vpr_device_ctx.rr_graph_builder, + static_cast(clk_rr_lookup), + vpr_device_ctx.rr_graph, vpr_device_ctx.grid, + vpr_device_ctx.arch->through_channel, clk_ntwk); /* TODO: Sanity checks */ diff --git a/openfpga/src/annotation/append_clock_rr_graph.h b/openfpga/src/annotation/append_clock_rr_graph.h index 8f69f37f0..635a54a79 100644 --- a/openfpga/src/annotation/append_clock_rr_graph.h +++ b/openfpga/src/annotation/append_clock_rr_graph.h @@ -17,8 +17,7 @@ namespace openfpga { int append_clock_rr_graph(DeviceContext& vpr_device_ctx, RRClockSpatialLookup& clk_rr_lookup, - const ClockNetwork& clk_ntwk, - const bool& verbose); + const ClockNetwork& clk_ntwk, const bool& verbose); } /* end namespace openfpga */ diff --git a/openfpga/src/base/openfpga_context.h b/openfpga/src/base/openfpga_context.h index baf6464a6..9455ed916 100644 --- a/openfpga/src/base/openfpga_context.h +++ b/openfpga/src/base/openfpga_context.h @@ -6,7 +6,6 @@ #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" @@ -18,6 +17,7 @@ #include "netlist_manager.h" #include "openfpga_arch.h" #include "openfpga_flow_manager.h" +#include "rr_clock_spatial_lookup.h" #include "simulation_setting.h" #include "tile_direct.h" #include "vpr_bitstream_annotation.h" @@ -64,7 +64,9 @@ 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::RRClockSpatialLookup& clock_rr_lookup() const { + return clock_rr_lookup_; + } const openfpga::VprDeviceAnnotation& vpr_device_annotation() const { return vpr_device_annotation_; } @@ -121,7 +123,9 @@ 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::RRClockSpatialLookup& mutable_clock_rr_lookup() { + return clock_rr_lookup_; + } openfpga::VprDeviceAnnotation& mutable_vpr_device_annotation() { return vpr_device_annotation_; } diff --git a/openfpga/src/base/openfpga_link_arch_template.h b/openfpga/src/base/openfpga_link_arch_template.h index 0ba411511..28612bfe7 100644 --- a/openfpga/src/base/openfpga_link_arch_template.h +++ b/openfpga/src/base/openfpga_link_arch_template.h @@ -198,10 +198,9 @@ 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)); + 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)); } } /* end namespace openfpga */ From cae05a14e19f44b501a779eddadc34336bdd4a32 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 26 Feb 2023 23:10:50 -0800 Subject: [PATCH 037/166] [core] dev --- .../src/annotation/append_clock_rr_graph.cpp | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/openfpga/src/annotation/append_clock_rr_graph.cpp b/openfpga/src/annotation/append_clock_rr_graph.cpp index fe2605c5f..6eb06c1c1 100644 --- a/openfpga/src/annotation/append_clock_rr_graph.cpp +++ b/openfpga/src/annotation/append_clock_rr_graph.cpp @@ -168,23 +168,33 @@ 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, + RRGraphBuilder& rr_graph_builder, size_t& num_edges_to_create, const RRClockSpatialLookup& clk_rr_lookup, const RRGraphView& rr_graph_view, const ClockNetwork& clk_ntwk, const vtr::Point chan_coord, const t_rr_type& chan_type) { + size_t edge_count = 0; for (auto itree : clk_ntwk.trees()) { for (auto ilvl : clk_ntwk.levels(itree)) { for (auto node_dir : {Direction::INC, Direction::DEC}) { 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( + RRNodeId src_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 */ + for (RRNodeId des_node : find_clock_track2track_node(chan_coord, itree, ilvl, ipin, node_dir)) { /* TODO: Create edges */ + VTR_ASSERT(des_node); + rr_graph_builder.create_edge(src_node, des_node, clk_ntwk.default_switch()); + edge_count++; + } + /* TODO: If this is the clock node at the last level of the tree, should drive some grid IPINs which are clocks */ } } } } + /* Allocate edges */ + rr_graph_builder.build_edges(true); + num_edges_to_create += edge_count; } /******************************************************************** @@ -208,6 +218,7 @@ static void add_rr_graph_block_clock_edges( * clk0_lvl1_chany[1][1] *******************************************************************/ static void add_rr_graph_clock_edges(RRGraphBuilder& rr_graph_builder, + size_t& num_edges_to_create, const RRClockSpatialLookup& clk_rr_lookup, const RRGraphView& rr_graph_view, const DeviceGrid& grids, @@ -223,7 +234,7 @@ static 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, clk_rr_lookup, + add_rr_graph_block_clock_edges(rr_graph_builder, num_edges_to_create, clk_rr_lookup, rr_graph_view, clk_ntwk, chanx_coord, CHANX); } @@ -239,7 +250,7 @@ static 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, clk_rr_lookup, + add_rr_graph_block_clock_edges(rr_graph_builder, num_edges_to_create, clk_rr_lookup, rr_graph_view, clk_ntwk, chany_coord, CHANY); } @@ -294,6 +305,7 @@ int append_clock_rr_graph(DeviceContext& vpr_device_ctx, size_t num_clock_edges = 0; add_rr_graph_clock_edges( vpr_device_ctx.rr_graph_builder, + num_clock_edges, static_cast(clk_rr_lookup), vpr_device_ctx.rr_graph, vpr_device_ctx.grid, vpr_device_ctx.arch->through_channel, clk_ntwk); From b6eace8facb3878b36f0329d73b27b64c574cc61 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 27 Feb 2023 13:10:54 -0800 Subject: [PATCH 038/166] [core] now switch id is linked in clock network --- .../src/base/clock_network.cpp | 9 +++++ .../src/base/clock_network.h | 2 + .../src/utils/clock_network_utils.cpp | 39 +++++++++++++++++++ .../src/utils/clock_network_utils.h | 4 +- .../src/annotation/append_clock_rr_graph.cpp | 30 ++++++++++++-- .../src/base/openfpga_read_arch_template.h | 2 +- 6 files changed, 80 insertions(+), 6 deletions(-) diff --git a/libs/libclkarchopenfpga/src/base/clock_network.cpp b/libs/libclkarchopenfpga/src/base/clock_network.cpp index dcd6e828f..40397a7c9 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.cpp +++ b/libs/libclkarchopenfpga/src/base/clock_network.cpp @@ -155,6 +155,10 @@ std::string ClockNetwork::default_switch_name() const { return default_switch_name_; } +RRSwitchId ClockNetwork::default_switch() const { + return default_switch_id_; +} + std::string ClockNetwork::tree_name(const ClockTreeId& tree_id) const { VTR_ASSERT(valid_tree_id(tree_id)); return tree_names_[tree_id]; @@ -267,6 +271,11 @@ void ClockNetwork::set_default_segment(const RRSegmentId& seg_id) { default_segment_id_ = seg_id; } +void ClockNetwork::set_default_switch(const RRSwitchId& switch_id) { + default_switch_id_ = switch_id; +} + + void ClockNetwork::set_default_segment_name(const std::string& name) { default_segment_name_ = name; } diff --git a/libs/libclkarchopenfpga/src/base/clock_network.h b/libs/libclkarchopenfpga/src/base/clock_network.h index 60250af86..1a093cdf0 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.h +++ b/libs/libclkarchopenfpga/src/base/clock_network.h @@ -72,6 +72,7 @@ class ClockNetwork { * information from RRGraph */ RRSegmentId default_segment() const; std::string default_segment_name() const; + RRSwitchId default_switch() const; std::string default_switch_name() const; std::string tree_name(const ClockTreeId& tree_id) const; size_t tree_width(const ClockTreeId& tree_id) const; @@ -116,6 +117,7 @@ class ClockNetwork { /* Reserve a number of trees to be memory efficent */ void reserve_trees(const size_t& num_trees); void set_default_segment(const RRSegmentId& seg_id); + void set_default_switch(const RRSwitchId& switch_id); void set_default_segment_name(const std::string& name); void set_default_switch_name(const std::string& name); /* Create a new tree, by default the tree can accomodate only 1 clock signal; diff --git a/libs/libclkarchopenfpga/src/utils/clock_network_utils.cpp b/libs/libclkarchopenfpga/src/utils/clock_network_utils.cpp index b58daf418..ffda09026 100644 --- a/libs/libclkarchopenfpga/src/utils/clock_network_utils.cpp +++ b/libs/libclkarchopenfpga/src/utils/clock_network_utils.cpp @@ -10,6 +10,7 @@ namespace openfpga { // Begin namespace openfpga * Link all the segments that are defined in a routing resource graph to a given *clock network *******************************************************************/ +static int link_clock_network_rr_segments(ClockNetwork& clk_ntwk, const RRGraphView& rr_graph) { /* default segment id */ @@ -26,4 +27,42 @@ int link_clock_network_rr_segments(ClockNetwork& clk_ntwk, return CMD_EXEC_FATAL_ERROR; } +/******************************************************************** + * Link all the switches that are defined in a routing resource graph to a given + *clock network + *******************************************************************/ +static +int link_clock_network_rr_switches(ClockNetwork& clk_ntwk, + const RRGraphView& rr_graph) { + /* default switch id */ + std::string default_switch_name = clk_ntwk.default_switch_name(); + for (size_t rr_switch_id = 0; rr_switch_id < rr_graph.num_rr_switches(); + ++rr_switch_id) { + if (std::string(rr_graph.rr_switch_inf(RRSwitchId(rr_switch_id)).name) == + default_switch_name) { + clk_ntwk.set_default_switch(RRSwitchId(rr_switch_id)); + return CMD_EXEC_SUCCESS; + } + } + + return CMD_EXEC_FATAL_ERROR; +} + +int link_clock_network_rr_graph(ClockNetwork& clk_ntwk, + const RRGraphView& rr_graph) { + int status = CMD_EXEC_SUCCESS; + + status = link_clock_network_rr_segments(clk_ntwk, rr_graph); + if (CMD_EXEC_FATAL_ERROR == status) { + return status; + } + status = link_clock_network_rr_switches(clk_ntwk, rr_graph); + if (CMD_EXEC_FATAL_ERROR == status) { + return status; + } + + return status; +} + + } // End of namespace openfpga diff --git a/libs/libclkarchopenfpga/src/utils/clock_network_utils.h b/libs/libclkarchopenfpga/src/utils/clock_network_utils.h index faa348989..0a266c188 100644 --- a/libs/libclkarchopenfpga/src/utils/clock_network_utils.h +++ b/libs/libclkarchopenfpga/src/utils/clock_network_utils.h @@ -13,8 +13,8 @@ namespace openfpga { // Begin namespace openfpga -int link_clock_network_rr_segments(ClockNetwork& clk_ntwk, - const RRGraphView& rr_graph); +int link_clock_network_rr_graph(ClockNetwork& clk_ntwk, + const RRGraphView& rr_graph); } // End of namespace openfpga diff --git a/openfpga/src/annotation/append_clock_rr_graph.cpp b/openfpga/src/annotation/append_clock_rr_graph.cpp index 6eb06c1c1..476ed6a3f 100644 --- a/openfpga/src/annotation/append_clock_rr_graph.cpp +++ b/openfpga/src/annotation/append_clock_rr_graph.cpp @@ -164,6 +164,29 @@ static void add_rr_graph_clock_nodes(RRGraphBuilder& rr_graph_builder, } } +/******************************************************************** + * Add edges for the clock nodes in a given connection block + * For example + * + * clk0_lvl1_chany[1][2] + * ^ + * | + * clk0_lvl0_chanx[1][1] -->---------+--->---> clk0_lvl0_chanx[2][1] + * | + * v + * clk0_lvl1_chany[1][1] + *******************************************************************/ +static +std::vector find_clock_track2track_node(const vtr::Point& chan_coord, + const ClockTreeId& clk_tree, + const ClockLevelId& clk_lvl, + const ClockTreePinId& clk_pin, + const Direction& direction) { + std::vector des_nodes; + + return des_nodes +} + /******************************************************************** * Add edges for the clock nodes in a given connection block *******************************************************************/ @@ -179,10 +202,10 @@ static void add_rr_graph_block_clock_edges( /* find the driver clock node through lookup */ RRNodeId src_node = clk_rr_lookup.find_node( chan_coord.x(), chan_coord.y(), itree, ilvl, ipin, node_dir); - VTR_ASSERT(driver_node); + VTR_ASSERT(src_node); /* TODO: find the fan-out clock node through lookup */ for (RRNodeId des_node : find_clock_track2track_node(chan_coord, itree, ilvl, ipin, node_dir)) { - /* TODO: Create edges */ + /* Create edges */ VTR_ASSERT(des_node); rr_graph_builder.create_edge(src_node, des_node, clk_ntwk.default_switch()); edge_count++; @@ -207,7 +230,8 @@ static void add_rr_graph_block_clock_edges( *clock tree may contain multiple clocks) * - clock nodes can only drive clock nodes (by making a turn, straight *connection is not allowed) which are 1 level lower in the same clock tree with - *the same clock index For example + *the same clock index + * For example * * clk0_lvl1_chany[1][2] * ^ diff --git a/openfpga/src/base/openfpga_read_arch_template.h b/openfpga/src/base/openfpga_read_arch_template.h index c60b91452..65daa4f27 100644 --- a/openfpga/src/base/openfpga_read_arch_template.h +++ b/openfpga/src/base/openfpga_read_arch_template.h @@ -237,7 +237,7 @@ int read_openfpga_clock_arch_template(T& openfpga_context, const Command& cmd, read_xml_clock_network(arch_file_name.c_str()); /* Build internal links */ openfpga_context.mutable_clock_arch().link(); - link_clock_network_rr_segments(openfpga_context.mutable_clock_arch(), + link_clock_network_rr_graph(openfpga_context.mutable_clock_arch(), g_vpr_ctx.device().rr_graph); /* Ensure clean data */ openfpga_context.clock_arch().validate(); From 9ec4d690db7819a8b9a634db0f4e957e0594a243 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 27 Feb 2023 15:10:36 -0800 Subject: [PATCH 039/166] [core] clock edges interconnecting clock tracks across levels --- .../src/base/clock_network.cpp | 10 + .../src/base/clock_network.h | 7 + .../src/annotation/append_clock_rr_graph.cpp | 173 +++++++++++++++++- 3 files changed, 182 insertions(+), 8 deletions(-) diff --git a/libs/libclkarchopenfpga/src/base/clock_network.cpp b/libs/libclkarchopenfpga/src/base/clock_network.cpp index 40397a7c9..4b8e22200 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.cpp +++ b/libs/libclkarchopenfpga/src/base/clock_network.cpp @@ -244,6 +244,10 @@ bool ClockNetwork::empty() const { return 0 == tree_ids_.size(); } bool ClockNetwork::is_valid() const { return !is_dirty_; } +ClockLevelId ClockNetwork::next_level(const ClockLevelId& lvl) const { + return ClockLevelId(size_t(lvl) + 1); +} + /************************************************************************ * Public Mutators ***********************************************************************/ @@ -502,6 +506,12 @@ bool ClockNetwork::valid_tree_id(const ClockTreeId& tree_id) const { (tree_id == tree_ids_[tree_id]); } +bool ClockNetwork::valid_level_id(const ClockTreeId& tree_id, const ClockLevelId& lvl_id) const { + return valid_tree_id(tree_id) && + (size_t(lvl_id) < tree_depth(tree_id)); +} + + bool ClockNetwork::valid_spine_id(const ClockSpineId& spine_id) const { return (size_t(spine_id) < spine_ids_.size()) && (spine_id == spine_ids_[spine_id]); diff --git a/libs/libclkarchopenfpga/src/base/clock_network.h b/libs/libclkarchopenfpga/src/base/clock_network.h index 1a093cdf0..e19138096 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.h +++ b/libs/libclkarchopenfpga/src/base/clock_network.h @@ -110,6 +110,11 @@ class ClockNetwork { /* Check if there are clock tree */ bool empty() const; bool is_valid() const; + /* Get the level id which is next to the current level + * Note that this follows the same rule in computing levels in update_tree_depth() + * If the rule has been changed, this API should be changed as well + */ + ClockLevelId next_level(const ClockLevelId& lvl) const; public: /* Public Mutators */ /* Reserve a number of spines to be memory efficent */ @@ -148,6 +153,8 @@ class ClockNetwork { public: /* Public invalidators/validators */ /* Show if the tree id is a valid for data queries */ bool valid_tree_id(const ClockTreeId& tree_id) const; + /* Show if the level id is a valid for a given tree */ + bool valid_level_id(const ClockTreeId& tree_id, const ClockLevelId& lvl_id) const; /* Show if the tree id is a valid for data queries */ bool valid_spine_id(const ClockSpineId& spine_id) const; bool valid_spine_switch_point_id( diff --git a/openfpga/src/annotation/append_clock_rr_graph.cpp b/openfpga/src/annotation/append_clock_rr_graph.cpp index 476ed6a3f..15278e7ad 100644 --- a/openfpga/src/annotation/append_clock_rr_graph.cpp +++ b/openfpga/src/annotation/append_clock_rr_graph.cpp @@ -165,26 +165,183 @@ static void add_rr_graph_clock_nodes(RRGraphBuilder& rr_graph_builder, } /******************************************************************** - * Add edges for the clock nodes in a given connection block + * Find the destination nodes for a driver clock node in a given connection block + * There are two types of destination nodes: + * - Straight connection where the driver clock node connects to another clock node + * in the same direction and at the same level as well as clock index * For example * + * clk0_lvl0_chanx[1][1] -->------------->---> clk0_lvl0_chanx[2][1] + * + * - Turning connections where the driver clock node makes turns to connect other clock nodes + * at 1-level up and in the same clock index + * + * * clk0_lvl1_chany[1][2] * ^ * | - * clk0_lvl0_chanx[1][1] -->---------+--->---> clk0_lvl0_chanx[2][1] + * clk0_lvl0_chanx[1][1] -->---------+ * | * v * clk0_lvl1_chany[1][1] + * + * Coordindate system: + * + * +----------+----------+------------+ + * | Grid | CBy | Grid | + * | [x][y+1] | [x][y+1] | [x+1][y+1] | + * +----------+----------+------------+ + * | CBx | SB | CBx | + * | [x][y] | [x][y] | [x+1][y] | + * +----------+----------+------------+ + * | Grid | CBy | Grid | + * | [x][y] | [x][y] | [x+1][y] | + * +----------+----------+------------+ + * *******************************************************************/ static -std::vector find_clock_track2track_node(const vtr::Point& chan_coord, +std::vector find_clock_track2track_node(const RRGraphView& rr_graph_view, + const ClockNetwork& clk_ntwk, + const RRClockSpatialLookup& clk_rr_lookup, + const t_rr_type& chan_type, + const vtr::Point& chan_coord, const ClockTreeId& clk_tree, const ClockLevelId& clk_lvl, const ClockTreePinId& clk_pin, const Direction& direction) { std::vector des_nodes; - return des_nodes + /* Straight connection */ + vtr::Point straight_des_coord = chan_coord; + if (chan_type == CHANX) { + if (direction == Direction::INC) { + straight_des_coord.set_x(straight_des_coord.x() + 1); + } else { + VTR_ASSERT(direction == Direction::DEC); + straight_des_coord.set_x(straight_des_coord.x() - 1); + } + } else { + VTR_ASSERT(chan_type == CHANY); + if (direction == Direction::INC) { + straight_des_coord.set_y(straight_des_coord.y() + 1); + } else { + VTR_ASSERT(direction == Direction::DEC); + straight_des_coord.set_y(straight_des_coord.y() - 1); + } + } + RRNodeId straight_des_node = clk_rr_lookup.find_node(straight_des_coord.x(), straight_des_coord.y(), clk_tree, clk_lvl, clk_pin, direction); + if (rr_graph_view.valid_node(straight_des_node)) { + VTR_ASSERT(chan_type == rr_graph_view.node_type(straight_des_node)); + des_nodes.push_back(straight_des_node); + } + + /* Check the next level if this is the last level, there are no turns available */ + ClockLevelId next_clk_lvl = clk_ntwk.next_level(clk_lvl); + if (!clk_ntwk.valid_level_id(clk_tree, next_clk_lvl)) { + return des_nodes; + } + + /* left turn connection */ + vtr::Point left_des_coord = chan_coord; + Direction left_direction = direction; + t_rr_type left_des_chan_type = chan_type; + if (chan_type == CHANX) { + left_des_chan_type = CHANY; + if (direction == Direction::INC) { + /* + * ^ + * | + * -->+ + */ + left_des_coord.set_y(left_des_coord.y() + 1); + } else { + /* + * +<-- + * | + * v + */ + VTR_ASSERT(direction == Direction::DEC); + left_des_coord.set_x(left_des_coord.x() - 1); + } + } else { + VTR_ASSERT(chan_type == CHANY); + left_des_chan_type = CHANX; + if (direction == Direction::INC) { + /* + * <--+ + * ^ + * | + */ + left_direction = Direction::DEC; + } else { + VTR_ASSERT(direction == Direction::DEC); + /* + * | + * v + * +--> + */ + left_direction = Direction::INC; + left_des_coord.set_x(left_des_coord.x() + 1); + left_des_coord.set_y(left_des_coord.y() - 1); + } + } + RRNodeId left_des_node = clk_rr_lookup.find_node(left_des_coord.x(), left_des_coord.y(), clk_tree, next_clk_lvl, clk_pin, left_direction); + if (rr_graph_view.valid_node(left_des_node)) { + VTR_ASSERT(left_des_chan_type == rr_graph_view.node_type(left_des_node)); + des_nodes.push_back(left_des_node); + } + + /* right turn connection */ + vtr::Point right_des_coord = chan_coord; + Direction right_direction = direction; + t_rr_type right_des_chan_type = chan_type; + if (chan_type == CHANX) { + right_des_chan_type = CHANY; + if (direction == Direction::INC) { + /* + * -->+ + * | + * v + */ + right_direction = Direction::DEC; + } else { + /* + * ^ + * | + * +<-- + */ + VTR_ASSERT(direction == Direction::DEC); + right_direction = Direction::INC; + right_des_coord.set_x(right_des_coord.x() - 1); + right_des_coord.set_y(right_des_coord.y() + 1); + } + } else { + VTR_ASSERT(chan_type == CHANY); + right_des_chan_type = CHANX; + if (direction == Direction::INC) { + /* + * +--> + * ^ + * | + */ + right_des_coord.set_x(right_des_coord.x() + 1); + } else { + VTR_ASSERT(direction == Direction::DEC); + /* + * | + * v + * <--+ + */ + right_des_coord.set_y(right_des_coord.y() - 1); + } + } + RRNodeId right_des_node = clk_rr_lookup.find_node(right_des_coord.x(), right_des_coord.y(), clk_tree, next_clk_lvl, clk_pin, right_direction); + if (rr_graph_view.valid_node(right_des_node)) { + VTR_ASSERT(right_des_chan_type == rr_graph_view.node_type(right_des_node)); + des_nodes.push_back(right_des_node); + } + + return des_nodes; } /******************************************************************** @@ -202,11 +359,11 @@ static void add_rr_graph_block_clock_edges( /* find the driver clock node through lookup */ RRNodeId src_node = clk_rr_lookup.find_node( chan_coord.x(), chan_coord.y(), itree, ilvl, ipin, node_dir); - VTR_ASSERT(src_node); - /* TODO: find the fan-out clock node through lookup */ - for (RRNodeId des_node : find_clock_track2track_node(chan_coord, itree, ilvl, ipin, node_dir)) { + VTR_ASSERT(rr_graph_view.valid_node(src_node)); + /* find the fan-out clock node through lookup */ + for (RRNodeId des_node : find_clock_track2track_node(rr_graph_view, clk_ntwk, clk_rr_lookup, chan_type, chan_coord, itree, ilvl, ipin, node_dir)) { /* Create edges */ - VTR_ASSERT(des_node); + VTR_ASSERT(rr_graph_view.valid_node(des_node)); rr_graph_builder.create_edge(src_node, des_node, clk_ntwk.default_switch()); edge_count++; } From b3dec93eb95e9995a43e0b2f529fb11dce5f653e Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 27 Feb 2023 15:12:59 -0800 Subject: [PATCH 040/166] [core] code format --- .../src/base/clock_network.cpp | 12 +-- .../src/base/clock_network.h | 10 +- .../src/utils/clock_network_utils.cpp | 13 +-- .../src/annotation/append_clock_rr_graph.cpp | 99 ++++++++++--------- .../src/base/openfpga_read_arch_template.h | 2 +- 5 files changed, 69 insertions(+), 67 deletions(-) diff --git a/libs/libclkarchopenfpga/src/base/clock_network.cpp b/libs/libclkarchopenfpga/src/base/clock_network.cpp index 4b8e22200..4c102acec 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.cpp +++ b/libs/libclkarchopenfpga/src/base/clock_network.cpp @@ -155,9 +155,7 @@ std::string ClockNetwork::default_switch_name() const { return default_switch_name_; } -RRSwitchId ClockNetwork::default_switch() const { - return default_switch_id_; -} +RRSwitchId ClockNetwork::default_switch() const { return default_switch_id_; } std::string ClockNetwork::tree_name(const ClockTreeId& tree_id) const { VTR_ASSERT(valid_tree_id(tree_id)); @@ -279,7 +277,6 @@ void ClockNetwork::set_default_switch(const RRSwitchId& switch_id) { default_switch_id_ = switch_id; } - void ClockNetwork::set_default_segment_name(const std::string& name) { default_segment_name_ = name; } @@ -506,12 +503,11 @@ bool ClockNetwork::valid_tree_id(const ClockTreeId& tree_id) const { (tree_id == tree_ids_[tree_id]); } -bool ClockNetwork::valid_level_id(const ClockTreeId& tree_id, const ClockLevelId& lvl_id) const { - return valid_tree_id(tree_id) && - (size_t(lvl_id) < tree_depth(tree_id)); +bool ClockNetwork::valid_level_id(const ClockTreeId& tree_id, + const ClockLevelId& lvl_id) const { + return valid_tree_id(tree_id) && (size_t(lvl_id) < tree_depth(tree_id)); } - bool ClockNetwork::valid_spine_id(const ClockSpineId& spine_id) const { return (size_t(spine_id) < spine_ids_.size()) && (spine_id == spine_ids_[spine_id]); diff --git a/libs/libclkarchopenfpga/src/base/clock_network.h b/libs/libclkarchopenfpga/src/base/clock_network.h index e19138096..be55b67c4 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.h +++ b/libs/libclkarchopenfpga/src/base/clock_network.h @@ -110,9 +110,10 @@ class ClockNetwork { /* Check if there are clock tree */ bool empty() const; bool is_valid() const; - /* Get the level id which is next to the current level - * Note that this follows the same rule in computing levels in update_tree_depth() - * If the rule has been changed, this API should be changed as well + /* Get the level id which is next to the current level + * Note that this follows the same rule in computing levels in + * update_tree_depth() If the rule has been changed, this API should be + * changed as well */ ClockLevelId next_level(const ClockLevelId& lvl) const; @@ -154,7 +155,8 @@ class ClockNetwork { /* Show if the tree id is a valid for data queries */ bool valid_tree_id(const ClockTreeId& tree_id) const; /* Show if the level id is a valid for a given tree */ - bool valid_level_id(const ClockTreeId& tree_id, const ClockLevelId& lvl_id) const; + bool valid_level_id(const ClockTreeId& tree_id, + const ClockLevelId& lvl_id) const; /* Show if the tree id is a valid for data queries */ bool valid_spine_id(const ClockSpineId& spine_id) const; bool valid_spine_switch_point_id( diff --git a/libs/libclkarchopenfpga/src/utils/clock_network_utils.cpp b/libs/libclkarchopenfpga/src/utils/clock_network_utils.cpp index ffda09026..79737b46c 100644 --- a/libs/libclkarchopenfpga/src/utils/clock_network_utils.cpp +++ b/libs/libclkarchopenfpga/src/utils/clock_network_utils.cpp @@ -10,9 +10,8 @@ namespace openfpga { // Begin namespace openfpga * Link all the segments that are defined in a routing resource graph to a given *clock network *******************************************************************/ -static -int link_clock_network_rr_segments(ClockNetwork& clk_ntwk, - const RRGraphView& rr_graph) { +static int link_clock_network_rr_segments(ClockNetwork& clk_ntwk, + const RRGraphView& rr_graph) { /* default segment id */ std::string default_segment_name = clk_ntwk.default_segment_name(); for (size_t rr_seg_id = 0; rr_seg_id < rr_graph.num_rr_segments(); @@ -31,9 +30,8 @@ int link_clock_network_rr_segments(ClockNetwork& clk_ntwk, * Link all the switches that are defined in a routing resource graph to a given *clock network *******************************************************************/ -static -int link_clock_network_rr_switches(ClockNetwork& clk_ntwk, - const RRGraphView& rr_graph) { +static int link_clock_network_rr_switches(ClockNetwork& clk_ntwk, + const RRGraphView& rr_graph) { /* default switch id */ std::string default_switch_name = clk_ntwk.default_switch_name(); for (size_t rr_switch_id = 0; rr_switch_id < rr_graph.num_rr_switches(); @@ -61,8 +59,7 @@ int link_clock_network_rr_graph(ClockNetwork& clk_ntwk, return status; } - return status; + return status; } - } // End of namespace openfpga diff --git a/openfpga/src/annotation/append_clock_rr_graph.cpp b/openfpga/src/annotation/append_clock_rr_graph.cpp index 15278e7ad..d9bf3775d 100644 --- a/openfpga/src/annotation/append_clock_rr_graph.cpp +++ b/openfpga/src/annotation/append_clock_rr_graph.cpp @@ -165,16 +165,16 @@ static void add_rr_graph_clock_nodes(RRGraphBuilder& rr_graph_builder, } /******************************************************************** - * Find the destination nodes for a driver clock node in a given connection block - * There are two types of destination nodes: - * - Straight connection where the driver clock node connects to another clock node - * in the same direction and at the same level as well as clock index - * For example + * Find the destination nodes for a driver clock node in a given connection + *block There are two types of destination nodes: + * - Straight connection where the driver clock node connects to another clock + *node in the same direction and at the same level as well as clock index For + *example * * clk0_lvl0_chanx[1][1] -->------------->---> clk0_lvl0_chanx[2][1] * - * - Turning connections where the driver clock node makes turns to connect other clock nodes - * at 1-level up and in the same clock index + * - Turning connections where the driver clock node makes turns to connect + *other clock nodes at 1-level up and in the same clock index * * * clk0_lvl1_chany[1][2] @@ -186,7 +186,7 @@ static void add_rr_graph_clock_nodes(RRGraphBuilder& rr_graph_builder, * clk0_lvl1_chany[1][1] * * Coordindate system: - * + * * +----------+----------+------------+ * | Grid | CBy | Grid | * | [x][y+1] | [x][y+1] | [x+1][y+1] | @@ -197,29 +197,25 @@ static void add_rr_graph_clock_nodes(RRGraphBuilder& rr_graph_builder, * | Grid | CBy | Grid | * | [x][y] | [x][y] | [x+1][y] | * +----------+----------+------------+ - * + * *******************************************************************/ -static -std::vector find_clock_track2track_node(const RRGraphView& rr_graph_view, - const ClockNetwork& clk_ntwk, - const RRClockSpatialLookup& clk_rr_lookup, - const t_rr_type& chan_type, - const vtr::Point& chan_coord, - const ClockTreeId& clk_tree, - const ClockLevelId& clk_lvl, - const ClockTreePinId& clk_pin, - const Direction& direction) { +static std::vector find_clock_track2track_node( + const RRGraphView& rr_graph_view, const ClockNetwork& clk_ntwk, + const RRClockSpatialLookup& clk_rr_lookup, const t_rr_type& chan_type, + const vtr::Point& chan_coord, const ClockTreeId& clk_tree, + const ClockLevelId& clk_lvl, const ClockTreePinId& clk_pin, + const Direction& direction) { std::vector des_nodes; /* Straight connection */ - vtr::Point straight_des_coord = chan_coord; + vtr::Point straight_des_coord = chan_coord; if (chan_type == CHANX) { if (direction == Direction::INC) { straight_des_coord.set_x(straight_des_coord.x() + 1); } else { VTR_ASSERT(direction == Direction::DEC); straight_des_coord.set_x(straight_des_coord.x() - 1); - } + } } else { VTR_ASSERT(chan_type == CHANY); if (direction == Direction::INC) { @@ -227,22 +223,25 @@ std::vector find_clock_track2track_node(const RRGraphView& rr_graph_vi } else { VTR_ASSERT(direction == Direction::DEC); straight_des_coord.set_y(straight_des_coord.y() - 1); - } + } } - RRNodeId straight_des_node = clk_rr_lookup.find_node(straight_des_coord.x(), straight_des_coord.y(), clk_tree, clk_lvl, clk_pin, direction); + RRNodeId straight_des_node = + clk_rr_lookup.find_node(straight_des_coord.x(), straight_des_coord.y(), + clk_tree, clk_lvl, clk_pin, direction); if (rr_graph_view.valid_node(straight_des_node)) { VTR_ASSERT(chan_type == rr_graph_view.node_type(straight_des_node)); des_nodes.push_back(straight_des_node); } - /* Check the next level if this is the last level, there are no turns available */ + /* Check the next level if this is the last level, there are no turns + * available */ ClockLevelId next_clk_lvl = clk_ntwk.next_level(clk_lvl); if (!clk_ntwk.valid_level_id(clk_tree, next_clk_lvl)) { return des_nodes; } /* left turn connection */ - vtr::Point left_des_coord = chan_coord; + vtr::Point left_des_coord = chan_coord; Direction left_direction = direction; t_rr_type left_des_chan_type = chan_type; if (chan_type == CHANX) { @@ -262,7 +261,7 @@ std::vector find_clock_track2track_node(const RRGraphView& rr_graph_vi */ VTR_ASSERT(direction == Direction::DEC); left_des_coord.set_x(left_des_coord.x() - 1); - } + } } else { VTR_ASSERT(chan_type == CHANY); left_des_chan_type = CHANX; @@ -283,16 +282,18 @@ std::vector find_clock_track2track_node(const RRGraphView& rr_graph_vi left_direction = Direction::INC; left_des_coord.set_x(left_des_coord.x() + 1); left_des_coord.set_y(left_des_coord.y() - 1); - } + } } - RRNodeId left_des_node = clk_rr_lookup.find_node(left_des_coord.x(), left_des_coord.y(), clk_tree, next_clk_lvl, clk_pin, left_direction); + RRNodeId left_des_node = + clk_rr_lookup.find_node(left_des_coord.x(), left_des_coord.y(), clk_tree, + next_clk_lvl, clk_pin, left_direction); if (rr_graph_view.valid_node(left_des_node)) { VTR_ASSERT(left_des_chan_type == rr_graph_view.node_type(left_des_node)); des_nodes.push_back(left_des_node); } /* right turn connection */ - vtr::Point right_des_coord = chan_coord; + vtr::Point right_des_coord = chan_coord; Direction right_direction = direction; t_rr_type right_des_chan_type = chan_type; if (chan_type == CHANX) { @@ -314,7 +315,7 @@ std::vector find_clock_track2track_node(const RRGraphView& rr_graph_vi right_direction = Direction::INC; right_des_coord.set_x(right_des_coord.x() - 1); right_des_coord.set_y(right_des_coord.y() + 1); - } + } } else { VTR_ASSERT(chan_type == CHANY); right_des_chan_type = CHANX; @@ -333,9 +334,11 @@ std::vector find_clock_track2track_node(const RRGraphView& rr_graph_vi * <--+ */ right_des_coord.set_y(right_des_coord.y() - 1); - } + } } - RRNodeId right_des_node = clk_rr_lookup.find_node(right_des_coord.x(), right_des_coord.y(), clk_tree, next_clk_lvl, clk_pin, right_direction); + RRNodeId right_des_node = + clk_rr_lookup.find_node(right_des_coord.x(), right_des_coord.y(), clk_tree, + next_clk_lvl, clk_pin, right_direction); if (rr_graph_view.valid_node(right_des_node)) { VTR_ASSERT(right_des_chan_type == rr_graph_view.node_type(right_des_node)); des_nodes.push_back(right_des_node); @@ -348,9 +351,10 @@ std::vector find_clock_track2track_node(const RRGraphView& rr_graph_vi * Add edges for the clock nodes in a given connection block *******************************************************************/ static void add_rr_graph_block_clock_edges( - RRGraphBuilder& rr_graph_builder, size_t& num_edges_to_create, const RRClockSpatialLookup& clk_rr_lookup, - const RRGraphView& rr_graph_view, const ClockNetwork& clk_ntwk, - const vtr::Point chan_coord, const t_rr_type& chan_type) { + RRGraphBuilder& rr_graph_builder, size_t& num_edges_to_create, + const RRClockSpatialLookup& clk_rr_lookup, const RRGraphView& rr_graph_view, + const ClockNetwork& clk_ntwk, const vtr::Point chan_coord, + const t_rr_type& chan_type) { size_t edge_count = 0; for (auto itree : clk_ntwk.trees()) { for (auto ilvl : clk_ntwk.levels(itree)) { @@ -361,13 +365,17 @@ static void add_rr_graph_block_clock_edges( chan_coord.x(), chan_coord.y(), itree, ilvl, ipin, node_dir); VTR_ASSERT(rr_graph_view.valid_node(src_node)); /* find the fan-out clock node through lookup */ - for (RRNodeId des_node : find_clock_track2track_node(rr_graph_view, clk_ntwk, clk_rr_lookup, chan_type, chan_coord, itree, ilvl, ipin, node_dir)) { + for (RRNodeId des_node : find_clock_track2track_node( + rr_graph_view, clk_ntwk, clk_rr_lookup, chan_type, chan_coord, + itree, ilvl, ipin, node_dir)) { /* Create edges */ VTR_ASSERT(rr_graph_view.valid_node(des_node)); - rr_graph_builder.create_edge(src_node, des_node, clk_ntwk.default_switch()); + rr_graph_builder.create_edge(src_node, des_node, + clk_ntwk.default_switch()); edge_count++; } - /* TODO: If this is the clock node at the last level of the tree, should drive some grid IPINs which are clocks */ + /* TODO: If this is the clock node at the last level of the tree, + * should drive some grid IPINs which are clocks */ } } } @@ -415,9 +423,9 @@ static 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, num_edges_to_create, clk_rr_lookup, - rr_graph_view, clk_ntwk, chanx_coord, - CHANX); + add_rr_graph_block_clock_edges(rr_graph_builder, num_edges_to_create, + clk_rr_lookup, rr_graph_view, clk_ntwk, + chanx_coord, CHANX); } } @@ -431,9 +439,9 @@ static 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, num_edges_to_create, clk_rr_lookup, - rr_graph_view, clk_ntwk, chany_coord, - CHANY); + add_rr_graph_block_clock_edges(rr_graph_builder, num_edges_to_create, + clk_rr_lookup, rr_graph_view, clk_ntwk, + chany_coord, CHANY); } } } @@ -485,8 +493,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, - num_clock_edges, + vpr_device_ctx.rr_graph_builder, num_clock_edges, static_cast(clk_rr_lookup), vpr_device_ctx.rr_graph, vpr_device_ctx.grid, vpr_device_ctx.arch->through_channel, clk_ntwk); diff --git a/openfpga/src/base/openfpga_read_arch_template.h b/openfpga/src/base/openfpga_read_arch_template.h index 65daa4f27..9d7f32b0a 100644 --- a/openfpga/src/base/openfpga_read_arch_template.h +++ b/openfpga/src/base/openfpga_read_arch_template.h @@ -238,7 +238,7 @@ int read_openfpga_clock_arch_template(T& openfpga_context, const Command& cmd, /* Build internal links */ openfpga_context.mutable_clock_arch().link(); link_clock_network_rr_graph(openfpga_context.mutable_clock_arch(), - g_vpr_ctx.device().rr_graph); + g_vpr_ctx.device().rr_graph); /* Ensure clean data */ openfpga_context.clock_arch().validate(); if (!openfpga_context.clock_arch().is_valid()) { From 7d0c23c675abe47527bbebca01e017d20ecb9e6f Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 27 Feb 2023 15:16:23 -0800 Subject: [PATCH 041/166] [lib] new api for lowest level clock connections --- libs/libclkarchopenfpga/src/base/clock_network.cpp | 5 +++++ libs/libclkarchopenfpga/src/base/clock_network.h | 2 ++ 2 files changed, 7 insertions(+) diff --git a/libs/libclkarchopenfpga/src/base/clock_network.cpp b/libs/libclkarchopenfpga/src/base/clock_network.cpp index 4c102acec..3dfbe64bc 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.cpp +++ b/libs/libclkarchopenfpga/src/base/clock_network.cpp @@ -508,6 +508,11 @@ bool ClockNetwork::valid_level_id(const ClockTreeId& tree_id, return valid_tree_id(tree_id) && (size_t(lvl_id) < tree_depth(tree_id)); } +bool ClockNetwork::is_last_level(const ClockTreeId& tree_id, + const ClockLevelId& lvl_id) const { + return valid_tree_id(tree_id) && (size_t(lvl_id) == tree_depth(tree_id) - 1); +} + bool ClockNetwork::valid_spine_id(const ClockSpineId& spine_id) const { return (size_t(spine_id) < spine_ids_.size()) && (spine_id == spine_ids_[spine_id]); diff --git a/libs/libclkarchopenfpga/src/base/clock_network.h b/libs/libclkarchopenfpga/src/base/clock_network.h index be55b67c4..7687273e9 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.h +++ b/libs/libclkarchopenfpga/src/base/clock_network.h @@ -157,6 +157,8 @@ class ClockNetwork { /* Show if the level id is a valid for a given tree */ bool valid_level_id(const ClockTreeId& tree_id, const ClockLevelId& lvl_id) const; + /* Identify if the level is the last level of the given tree */ + bool is_last_level(const ClockTreeId& tree_id, const ClockLevelId& lvl) const; /* Show if the tree id is a valid for data queries */ bool valid_spine_id(const ClockSpineId& spine_id) const; bool valid_spine_switch_point_id( From 0dfe96bcf14c8e0fb96c9e4fda7cd9c5788fab54 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 27 Feb 2023 19:37:49 -0800 Subject: [PATCH 042/166] [core] dev --- .../src/annotation/append_clock_rr_graph.cpp | 132 +++++++++++++++--- .../utils/openfpga_physical_tile_utils.cpp | 11 ++ .../src/utils/openfpga_physical_tile_utils.h | 2 + 3 files changed, 129 insertions(+), 16 deletions(-) diff --git a/openfpga/src/annotation/append_clock_rr_graph.cpp b/openfpga/src/annotation/append_clock_rr_graph.cpp index d9bf3775d..eb501bda1 100644 --- a/openfpga/src/annotation/append_clock_rr_graph.cpp +++ b/openfpga/src/annotation/append_clock_rr_graph.cpp @@ -7,6 +7,7 @@ #include "vtr_geometry.h" #include "vtr_log.h" #include "vtr_time.h" +#include "openfpga_physical_tile_utils.h" /* begin namespace openfpga */ namespace openfpga { @@ -165,7 +166,7 @@ static void add_rr_graph_clock_nodes(RRGraphBuilder& rr_graph_builder, } /******************************************************************** - * Find the destination nodes for a driver clock node in a given connection + * Find the destination CHANX|CHANY nodes for a driver clock node in a given connection *block There are two types of destination nodes: * - Straight connection where the driver clock node connects to another clock *node in the same direction and at the same level as well as clock index For @@ -185,7 +186,7 @@ static void add_rr_graph_clock_nodes(RRGraphBuilder& rr_graph_builder, * v * clk0_lvl1_chany[1][1] * - * Coordindate system: + * Coordinate system: * * +----------+----------+------------+ * | Grid | CBy | Grid | @@ -347,14 +348,101 @@ static std::vector find_clock_track2track_node( return des_nodes; } +/******************************************************************** + * Try to find an IPIN of a grid which satisfy the requirement of clock pins + * that has been defined in clock network. If the IPIN does exist in a + * routing resource graph, add it to the node list + *******************************************************************/ +static +void try_find_and_add_clock_track2ipin_node(std::vector& des_nodes, + const DeviceGrid& grids, + const RRGraphView& rr_graph_view, + const vtr::Point& grid_coord, + const e_side& pin_side, + const ClockNetwork& clk_ntwk, + const ClockTreeId& clk_tree, + const ClockTreePinId& clk_pin) { + t_physical_tile_type_ptr grid_type = grids[grid_coord.x()][grid_coord.y()].type; + for (std::string tap_pin_name : clk_ntwk.tap_pin_name(clk_tree, clk_pin)) { + /* tap pin name could be 'io[5:5].a2f[0]' */ + int grid_pin_idx = find_physical_tile_pin_index(grid_type, tap_pin_name); + RRNodeId des_node = rr_graph_view.node_lookup().find_node(grid_coord.x(), grid_coord.y(), IPIN, grid_pin_idx, pin_side); + if (rr_graph_view.valid_node(des_node)) { + des_nodes.push_back(des_node); + } + } +} + +/******************************************************************** + * Find the destination IPIN nodes for a driver clock node in a given connection + *block. + * For CHANX, the IPIN nodes are typically on the BOTTOM and TOP sides of adjacent grids + * For CHANY, the IPIN nodes are typically on the LEFT and RIGHT sides of adjacent grids + * For example + * Grid[1][2] + * ^ + * | + * clk0_lvl2_chanx[1][1] -->---------+ + * | + * v + * Grid[1][1] + * + * Coordinate system: + * + * +----------+----------+------------+ + * | Grid | CBy | Grid | + * | [x][y+1] | [x][y+1] | [x+1][y+1] | + * +----------+----------+------------+ + * | CBx | SB | CBx | + * | [x][y] | [x][y] | [x+1][y] | + * +----------+----------+------------+ + * | Grid | CBy | Grid | + * | [x][y] | [x][y] | [x+1][y] | + * +----------+----------+------------+ + *******************************************************************/ +static std::vector find_clock_track2ipin_node(const DeviceGrid& grids, + const RRGraphView& rr_graph_view, + const t_rr_type& chan_type, + const vtr::Point& chan_coord, + const ClockNetwork& clk_ntwk, + const ClockTreeId& clk_tree, + const ClockTreePinId& clk_pin) { + std::vector des_nodes; + + if (chan_type == CHANX) { + /* Get the clock IPINs at the BOTTOM side of adjacent grids [x][y+1] */ + vtr::Point bot_grid_coord(chan_coord.x(), chan_coord.y() + 1); + try_find_and_add_clock_track2ipin_node(des_nodes, rr_graph_view, bot_grid_coord, BOTTOM, clk_ntwk, clk_tree, clk_pin); + } + /* Get the clock IPINs at the TOP side of adjacent grids [x][y] */ + vtr::Point top_grid_coord(chan_coord.x(), chan_coord.y()); + try_find_and_add_clock_track2ipin_node(des_nodes, rr_graph_view, top_grid_coord, TOP, clk_ntwk, clk_tree, clk_pin); + + } else { + VTR_ASSERT(chan_type == CHANY); + /* Get the clock IPINs at the LEFT side of adjacent grids [x][y+1] */ + vtr::Point left_grid_coord(chan_coord.x() + 1, chan_coord.y()); + try_find_and_add_clock_track2ipin_node(des_nodes, rr_graph_view, left_grid_coord, LEFT, clk_ntwk, clk_tree, clk_pin); + + /* Get the clock IPINs at the RIGHT side of adjacent grids [x][y] */ + vtr::Point right_grid_coord(chan_coord.x(), chan_coord.y()); + try_find_and_add_clock_track2ipin_node(des_nodes, rr_graph_view, right_grid_coord, RIGHT, clk_ntwk, clk_tree, clk_pin); + } + + return des_nodes; +} + /******************************************************************** * Add edges for the clock nodes in a given connection block *******************************************************************/ -static void add_rr_graph_block_clock_edges( - RRGraphBuilder& rr_graph_builder, size_t& num_edges_to_create, - const RRClockSpatialLookup& clk_rr_lookup, const RRGraphView& rr_graph_view, - const ClockNetwork& clk_ntwk, const vtr::Point chan_coord, - const t_rr_type& chan_type) { +static void add_rr_graph_block_clock_edges(RRGraphBuilder& rr_graph_builder, + size_t& num_edges_to_create, + const RRClockSpatialLookup& clk_rr_lookup, + const RRGraphView& rr_graph_view, + const DeviceGrid& grids, + const ClockNetwork& clk_ntwk, + const vtr::Point chan_coord, + const t_rr_type& chan_type) { size_t edge_count = 0; for (auto itree : clk_ntwk.trees()) { for (auto ilvl : clk_ntwk.levels(itree)) { @@ -364,18 +452,30 @@ static void add_rr_graph_block_clock_edges( RRNodeId src_node = clk_rr_lookup.find_node( chan_coord.x(), chan_coord.y(), itree, ilvl, ipin, node_dir); VTR_ASSERT(rr_graph_view.valid_node(src_node)); - /* find the fan-out clock node through lookup */ - for (RRNodeId des_node : find_clock_track2track_node( - rr_graph_view, clk_ntwk, clk_rr_lookup, chan_type, chan_coord, - itree, ilvl, ipin, node_dir)) { - /* Create edges */ - VTR_ASSERT(rr_graph_view.valid_node(des_node)); - rr_graph_builder.create_edge(src_node, des_node, - clk_ntwk.default_switch()); - edge_count++; + if (!clk_ntwk.is_last_level(itree, ilvl)) { + /* find the fan-out clock node through lookup */ + for (RRNodeId des_node : find_clock_track2track_node( + rr_graph_view, clk_ntwk, clk_rr_lookup, chan_type, chan_coord, + itree, ilvl, ipin, node_dir)) { + /* Create edges */ + VTR_ASSERT(rr_graph_view.valid_node(des_node)); + rr_graph_builder.create_edge(src_node, des_node, + clk_ntwk.default_switch()); + edge_count++; + } } /* TODO: If this is the clock node at the last level of the tree, * should drive some grid IPINs which are clocks */ + if (clk_ntwk.is_last_level(itree, ilvl)) { + for (RRNodeId des_node : find_clock_track2ipin_node( + grids, rr_graph_view, chan_type, chan_coord, clk_ntwk, itree, ipin)) { + /* Create edges */ + VTR_ASSERT(rr_graph_view.valid_node(des_node)); + rr_graph_builder.create_edge(src_node, des_node, + clk_ntwk.default_switch()); + edge_count++; + } + } } } } diff --git a/openfpga/src/utils/openfpga_physical_tile_utils.cpp b/openfpga/src/utils/openfpga_physical_tile_utils.cpp index 8003d7123..4a755c678 100644 --- a/openfpga/src/utils/openfpga_physical_tile_utils.cpp +++ b/openfpga/src/utils/openfpga_physical_tile_utils.cpp @@ -116,4 +116,15 @@ std::set find_physical_io_tile_located_sides( return io_sides; } +/******************************************************************** + * Find the pin index of a physical tile which matches the given name. + * For example, + * io[5:5].a2f[1] + * which corresponds to the pin 'a2f[1]' of the 5th subtile 'io' in the physical tile + *******************************************************************/ +int find_physical_tile_pin_index(t_physical_tile_type_ptr physical_tile, std::string pin_name) { + /* TODO: precheck: return unfound pin if subtile does not exist */ +} + + } /* end namespace openfpga */ diff --git a/openfpga/src/utils/openfpga_physical_tile_utils.h b/openfpga/src/utils/openfpga_physical_tile_utils.h index 4a9ce4cd8..cc5ce754e 100644 --- a/openfpga/src/utils/openfpga_physical_tile_utils.h +++ b/openfpga/src/utils/openfpga_physical_tile_utils.h @@ -27,6 +27,8 @@ float find_physical_tile_pin_Fc(t_physical_tile_type_ptr type, const int& pin); std::set find_physical_io_tile_located_sides( const DeviceGrid& grids, t_physical_tile_type_ptr physical_tile); +int find_physical_tile_pin_index(t_physical_tile_type_ptr physical_tile, std::string pin_name); + } /* end namespace openfpga */ #endif From 2df16096160ea1c524f268b743ecbd6d664c46c3 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 27 Feb 2023 21:44:00 -0800 Subject: [PATCH 043/166] [core] add a new API to get pin index from a tile --- .../utils/openfpga_physical_tile_utils.cpp | 62 ++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/openfpga/src/utils/openfpga_physical_tile_utils.cpp b/openfpga/src/utils/openfpga_physical_tile_utils.cpp index 4a755c678..148808173 100644 --- a/openfpga/src/utils/openfpga_physical_tile_utils.cpp +++ b/openfpga/src/utils/openfpga_physical_tile_utils.cpp @@ -12,6 +12,8 @@ #include "openfpga_device_grid_utils.h" #include "openfpga_physical_tile_utils.h" #include "openfpga_side_manager.h" +#include "openfpga_tokenizer.h" +#include "openfpga_port_parser.h" /* begin namespace openfpga */ namespace openfpga { @@ -123,7 +125,65 @@ std::set find_physical_io_tile_located_sides( * which corresponds to the pin 'a2f[1]' of the 5th subtile 'io' in the physical tile *******************************************************************/ int find_physical_tile_pin_index(t_physical_tile_type_ptr physical_tile, std::string pin_name) { - /* TODO: precheck: return unfound pin if subtile does not exist */ + int pin_idx = -1; + /* precheck: return unfound pin if the tile name does not match */ + StringToken tokenizer(pin_name); + std::vector pin_tokens = tokenizer.split("."); + if (pin_tokens.size() != 2) { + VTR_LOG_ERROR("Invalid pin name '%s'. Expect .\n", pin_name.c_str()); + exit(1); + } + PortParser tile_parser(pin_tokens[0]); + BasicPort tile_info = tile_parser.port(); + if (tile_info.get_name() != std::string(physical_tile->name)) { + return pin_idx; + } + if (!tile_info.is_valid()) { + VTR_LOG_ERROR("Invalid pin name '%s' whose subtile index is not valid, expect [0, %lu]\n", pin_name.c_str(), physical_tile->capacity - 1); + exit(1); + } + /* precheck: return unfound pin if the subtile index does not match */ + if (tile_info.get_width() != 1) { + VTR_LOG_ERROR("Invalid pin name '%s' whose subtile index range should be 1. For example, clb[1:1]\n", pin_name.c_str()); + exit(1); + } + if (tile_info.get_lsb() < 0 || tile_info.get_msb() > physical_tile->capacity - 1) { + VTR_LOG_ERROR("Invalid pin name '%s' whose subtile index is out of range, expect [0, %lu]\n", pin_name.c_str(), physical_tile->capacity - 1); + exit(1); + } + /* precheck: return unfound pin if the pin index does not match */ + PortParser pin_parser(pin_tokens[1]); + BasicPort pin_info = pin_parser.port(); + /* precheck: return unfound pin if the subtile index does not match */ + if (pin_info.get_width() != 1) { + VTR_LOG_ERROR("Invalid pin name '%s' whose pin index range should be 1. For example, clb[1:1].I[2:2]\n", pin_name.c_str()); + exit(1); + } + + /* Spot the subtile by using the index */ + for (const t_sub_tile& sub_tile : physical_tile->sub_tiles) { + if (!sub_tile.capacity.is_in_range(tile_info.get_lsb())) { + continue; + } + for (const t_physical_tile_port& sub_tile_port : sub_tile.ports) { + if (std::string(sub_tile_port.name) != pin_info.get_name()) { + continue; + } + if (!pin_info.is_valid()) { + VTR_LOG_ERROR("Invalid pin name '%s' whose pin index is not valid, expect [0, %lu]\n", pin_name.c_str(), sub_tile_port.num_pins - 1); + exit(1); + } + if (pin_info.get_lsb() < 0 || pin_info.get_msb() > sub_tile_port.num_pins - 1) { + VTR_LOG_ERROR("Invalid pin name '%s' whose pin index is out of range, expect [0, %lu]\n", pin_name.c_str(), sub_tile_port.num_pins - 1); + exit(1); + } + /* Reach here, we get the port we want, return the accumulated index */ + size_t accumulated_pin_idx = sub_tile_port.absolute_first_pin_index + sub_tile.num_phy_pins * (tile_info.get_lsb() - sub_tile.capacity.low) + pin_info.get_lsb(); + return accumulated_pin_idx; + } + } + + return pin_idx; } From 3a40c5e15fc040a9b5ff00992ab6a68674df0995 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 27 Feb 2023 21:49:14 -0800 Subject: [PATCH 044/166] [lib] update example of clock arch definition --- libs/libclkarchopenfpga/arch/example.xml | 28 ++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/libs/libclkarchopenfpga/arch/example.xml b/libs/libclkarchopenfpga/arch/example.xml index 3d7acab70..6defe943a 100644 --- a/libs/libclkarchopenfpga/arch/example.xml +++ b/libs/libclkarchopenfpga/arch/example.xml @@ -12,9 +12,29 @@ - - - - + + + + + + + + + + + + + + + + + + + + + + + + From 9f20d2e6392ffe13b4cb9585b4cd6a48dab7f114 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 27 Feb 2023 22:06:13 -0800 Subject: [PATCH 045/166] [lib] now clock arch supports tap points --- .../src/base/clock_network.cpp | 11 +++++++ .../src/base/clock_network.h | 3 ++ .../src/io/clock_network_xml_constants.h | 2 ++ .../src/io/read_xml_clock_network.cpp | 30 ++++++++++++++++--- .../src/io/write_xml_clock_network.cpp | 17 +++++++++++ 5 files changed, 59 insertions(+), 4 deletions(-) diff --git a/libs/libclkarchopenfpga/src/base/clock_network.cpp b/libs/libclkarchopenfpga/src/base/clock_network.cpp index 3dfbe64bc..ad0848137 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.cpp +++ b/libs/libclkarchopenfpga/src/base/clock_network.cpp @@ -230,6 +230,11 @@ vtr::Point ClockNetwork::spine_switch_point( return spine_switch_coords_[spine_id][size_t(switch_point_id)]; } +std::vector ClockNetwork::spine_taps(const ClockSpineId& spine_id) const { + VTR_ASSERT(valid_spine_id(spine_id)); + return spine_taps_[spine_id]; +} + ClockSpineId ClockNetwork::find_spine(const std::string& name) const { auto result = spine_name2id_map_.find(name); if (result == spine_name2id_map_.end()) { @@ -332,6 +337,7 @@ ClockSpineId ClockNetwork::create_spine(const std::string& name) { spine_parents_.emplace_back(); spine_children_.emplace_back(); spine_parent_trees_.emplace_back(); + spine_taps_.emplace_back(); /* Register to the lookup */ VTR_ASSERT(valid_spine_id(spine_id)); @@ -388,6 +394,11 @@ void ClockNetwork::add_spine_switch_point(const ClockSpineId& spine_id, spine_children_[spine_id].push_back(drive_spine_id); } +void ClockNetwork::add_spine_tap(const ClockSpineId& spine_id, const std::string& pin_name) { + VTR_ASSERT(valid_spine_id(spine_id)); + spine_taps_.push_back(pin_name); +} + bool ClockNetwork::link() { for (ClockTreeId tree_id : trees()) { if (!link_tree(tree_id)) { diff --git a/libs/libclkarchopenfpga/src/base/clock_network.h b/libs/libclkarchopenfpga/src/base/clock_network.h index 7687273e9..9a9cd154a 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.h +++ b/libs/libclkarchopenfpga/src/base/clock_network.h @@ -104,6 +104,7 @@ class ClockNetwork { vtr::Point spine_switch_point( const ClockSpineId& spine_id, const ClockSwitchPointId& switch_point_id) const; + std::vector spine_taps(const ClockSpineId& spine_id) const; /* Find a spine with a given name, if not found, return an valid id, otherwise * return an invalid one */ ClockSpineId find_spine(const std::string& name) const; @@ -146,6 +147,7 @@ class ClockNetwork { void add_spine_switch_point(const ClockSpineId& spine_id, const ClockSpineId& drive_spine_id, const vtr::Point& coord); + void add_spine_tap(const ClockSpineId& spine_id, const std::string& pin_name); /* Build internal links between clock tree, spines etc. This is also an * validator to verify the correctness of the clock network. Must run before * using the data! */ @@ -201,6 +203,7 @@ class ClockNetwork { vtr::vector spine_levels_; vtr::vector> spine_start_points_; vtr::vector> spine_end_points_; + vtr::vector> spine_taps_; vtr::vector> spine_switch_points_; vtr::vector>> spine_switch_coords_; vtr::vector spine_parents_; diff --git a/libs/libclkarchopenfpga/src/io/clock_network_xml_constants.h b/libs/libclkarchopenfpga/src/io/clock_network_xml_constants.h index 417e3d9db..8dc9871ec 100644 --- a/libs/libclkarchopenfpga/src/io/clock_network_xml_constants.h +++ b/libs/libclkarchopenfpga/src/io/clock_network_xml_constants.h @@ -21,5 +21,7 @@ constexpr const char* XML_CLOCK_SPINE_SWITCH_POINT_NODE_NAME = "switch_point"; constexpr const char* XML_CLOCK_SPINE_SWITCH_POINT_ATTRIBUTE_TAP = "tap"; constexpr const char* XML_CLOCK_SPINE_SWITCH_POINT_ATTRIBUTE_X = "x"; constexpr const char* XML_CLOCK_SPINE_SWITCH_POINT_ATTRIBUTE_Y = "y"; +constexpr const char* XML_CLOCK_SPINE_TAP_NODE_NAME = "tap"; +constexpr const char* XML_CLOCK_SPINE_TAP_ATTRIBUTE_TILE_PIN = "tile_pin"; #endif diff --git a/libs/libclkarchopenfpga/src/io/read_xml_clock_network.cpp b/libs/libclkarchopenfpga/src/io/read_xml_clock_network.cpp index c8bd9835e..ee1ee34f9 100644 --- a/libs/libclkarchopenfpga/src/io/read_xml_clock_network.cpp +++ b/libs/libclkarchopenfpga/src/io/read_xml_clock_network.cpp @@ -24,6 +24,24 @@ namespace openfpga { // Begin namespace openfpga +/******************************************************************** + * Parse XML codes of a to an object of ClockNetwork + *******************************************************************/ +static void read_xml_clock_spine_tap( + pugi::xml_node& xml_switch_point, const pugiutil::loc_data& loc_data, + ClockNetwork& clk_ntwk, const ClockSpineId& spine_id) { + if (!clk_ntwk.valid_spine_id(spine_id)) { + archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_switch_point), + "Invalid id of a clock spine!\n"); + } + + std::string tile_pin_name = + get_attribute(xml_switch_point, XML_CLOCK_SPINE_TAP_ATTRIBUTE_TILE_PIN, + loc_data) + .as_string(); + clk_ntwk.add_spine_tap(spine_id, tile_pin_name); +} + /******************************************************************** * Parse XML codes of a to an object of ClockNetwork *******************************************************************/ @@ -109,13 +127,17 @@ static void read_xml_clock_spine(pugi::xml_node& xml_spine, for (pugi::xml_node xml_switch_point : xml_spine.children()) { /* Error out if the XML child has an invalid name! */ - if (xml_switch_point.name() != + if (xml_switch_point.name() == std::string(XML_CLOCK_SPINE_SWITCH_POINT_NODE_NAME)) { + read_xml_clock_spine_switch_point(xml_switch_point, loc_data, clk_ntwk, + spine_id); + } else if (xml_switch_point.name() == + std::string(XML_CLOCK_SPINE_TAP_NODE_NAME)) { + read_xml_clock_spine_tap(xml_switch_point, loc_data, clk_ntwk, spine_id); + } else { bad_tag(xml_switch_point, loc_data, xml_spine, - {XML_CLOCK_SPINE_SWITCH_POINT_NODE_NAME}); + {XML_CLOCK_SPINE_SWITCH_POINT_NODE_NAME, XML_CLOCK_SPINE_TAP_NODE_NAME}); } - read_xml_clock_spine_switch_point(xml_switch_point, loc_data, clk_ntwk, - spine_id); } } diff --git a/libs/libclkarchopenfpga/src/io/write_xml_clock_network.cpp b/libs/libclkarchopenfpga/src/io/write_xml_clock_network.cpp index e2524a0ae..7910d6333 100644 --- a/libs/libclkarchopenfpga/src/io/write_xml_clock_network.cpp +++ b/libs/libclkarchopenfpga/src/io/write_xml_clock_network.cpp @@ -23,6 +23,22 @@ namespace openfpga { // Begin namespace openfpga +static int write_xml_clock_spine_taps( + std::fstream& fp, const ClockNetwork& clk_ntwk, const ClockSpineId& spine_id) { + for (const std::string& tile_pin_name : clk_ntwk.spine_taps(spine_id)) { + openfpga::write_tab_to_file(fp, 3); + fp << "<" << XML_CLOCK_SPINE_TAP_NODE_NAME << ""; + + write_xml_attribute( + fp, XML_CLOCK_SPINE_TAP_ATTRIBUTE_TILE_PIN, + tile_pin_name.c_str()); + fp << "/>" + << "\n"; + } + + return 0; +} + static int write_xml_clock_spine_switch_point( std::fstream& fp, const ClockNetwork& clk_ntwk, const ClockSpineId& spine_id, const ClockSwitchPointId& switch_point_id) { @@ -66,6 +82,7 @@ static int write_xml_clock_spine(std::fstream& fp, const ClockNetwork& clk_ntwk, clk_ntwk.spine_switch_points(spine_id)) { write_xml_clock_spine_switch_point(fp, clk_ntwk, spine_id, switch_point_id); } + write_xml_clock_spine_taps(fp, clk_ntwk, spine_id); openfpga::write_tab_to_file(fp, 2); fp << " Date: Mon, 27 Feb 2023 22:31:16 -0800 Subject: [PATCH 046/166] [core] finishing up clock rr_graph appending --- .../src/base/clock_network.cpp | 35 +++++++++++++++++++ .../src/base/clock_network.h | 6 ++++ .../src/annotation/append_clock_rr_graph.cpp | 5 ++- .../utils/openfpga_physical_tile_utils.cpp | 3 +- 4 files changed, 47 insertions(+), 2 deletions(-) diff --git a/libs/libclkarchopenfpga/src/base/clock_network.cpp b/libs/libclkarchopenfpga/src/base/clock_network.cpp index ad0848137..2615000bb 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.cpp +++ b/libs/libclkarchopenfpga/src/base/clock_network.cpp @@ -4,6 +4,8 @@ #include "vtr_assert.h" #include "vtr_log.h" +#include "openfpga_tokenizer.h" +#include "openfpga_port_parser.h" namespace openfpga { // Begin namespace openfpga @@ -235,6 +237,39 @@ std::vector ClockNetwork::spine_taps(const ClockSpineId& spine_id) return spine_taps_[spine_id]; } +std::vector ClockNetwork::spine_flatten_taps(const ClockSpineId& spine_id) const { + VTR_ASSERT(valid_spine_id(spine_id)); + std::vector flatten_taps; + for (const std::string& tap_name : spine_taps_[spine_id]) { + StringToken tokenizer(tap_name); + std::vector pin_tokens = tokenizer.split("."); + if (pin_tokens.size() != 2) { + VTR_LOG_ERROR("Invalid pin name '%s'. Expect .\n", pin_name.c_str()); + exit(1); + } + PortParser tile_parser(pin_tokens[0]); + BasicPort tile_info = tile_parser.port(); + PortParser pin_parser(pin_tokens[1]); + BasicPort pin_info = pin_parser.port(); + if (!tile_info.is_valid()) { + VTR_LOG_ERROR("Invalid pin name '%s' whose subtile index is not valid\n", pin_name.c_str()); + exit(1); + } + if (!pin_info.is_valid()) { + VTR_LOG_ERROR("Invalid pin name '%s' whose pin index is not valid\n", pin_name.c_str()); + exit(1); + } + for (size_t& tile_idx : tile_info.pins()) { + std::string flatten_tile_str = tile_info.get_name() + "[" + std::to_string(tile_idx) + "]"; + for (size_t& pin_idx : pin_info.pins()) { + std::string flatten_pin_str = pin_info.get_name() + "[" + std::to_string(pin_idx) + "]"; + flatten_taps.push_back(flatten_tile_str + "." + flatten_pin_str); + } + } + } + return flatten_taps; +} + ClockSpineId ClockNetwork::find_spine(const std::string& name) const { auto result = spine_name2id_map_.find(name); if (result == spine_name2id_map_.end()) { diff --git a/libs/libclkarchopenfpga/src/base/clock_network.h b/libs/libclkarchopenfpga/src/base/clock_network.h index 9a9cd154a..53e3259c5 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.h +++ b/libs/libclkarchopenfpga/src/base/clock_network.h @@ -104,7 +104,13 @@ class ClockNetwork { vtr::Point spine_switch_point( const ClockSpineId& spine_id, const ClockSwitchPointId& switch_point_id) const; + /* Return the original list of tap pins that is in storage; useful for parsers */ std::vector spine_taps(const ClockSpineId& spine_id) const; + /* Return the list of flatten tap pins. For example: clb[0:1].clk[2:3] is flatten to + * { clb[0].clk[2], clb[1].clk[2], clb[0].clk[3], clb[1].clk[3] } + * Useful to build clock routing resource graph + */ + std::vector spine_flatten_taps(const ClockSpineId& spine_id) const; /* Find a spine with a given name, if not found, return an valid id, otherwise * return an invalid one */ ClockSpineId find_spine(const std::string& name) const; diff --git a/openfpga/src/annotation/append_clock_rr_graph.cpp b/openfpga/src/annotation/append_clock_rr_graph.cpp index eb501bda1..a2277afa3 100644 --- a/openfpga/src/annotation/append_clock_rr_graph.cpp +++ b/openfpga/src/annotation/append_clock_rr_graph.cpp @@ -363,9 +363,12 @@ void try_find_and_add_clock_track2ipin_node(std::vector& des_nodes, const ClockTreeId& clk_tree, const ClockTreePinId& clk_pin) { t_physical_tile_type_ptr grid_type = grids[grid_coord.x()][grid_coord.y()].type; - for (std::string tap_pin_name : clk_ntwk.tap_pin_name(clk_tree, clk_pin)) { + for (std::string tap_pin_name : clk_ntwk.tap_pin_names(clk_tree, clk_pin)) { /* tap pin name could be 'io[5:5].a2f[0]' */ int grid_pin_idx = find_physical_tile_pin_index(grid_type, tap_pin_name); + if (grid_pin_idx == grid_type->num_pins) { + continue; + } RRNodeId des_node = rr_graph_view.node_lookup().find_node(grid_coord.x(), grid_coord.y(), IPIN, grid_pin_idx, pin_side); if (rr_graph_view.valid_node(des_node)) { des_nodes.push_back(des_node); diff --git a/openfpga/src/utils/openfpga_physical_tile_utils.cpp b/openfpga/src/utils/openfpga_physical_tile_utils.cpp index 148808173..18e019ca3 100644 --- a/openfpga/src/utils/openfpga_physical_tile_utils.cpp +++ b/openfpga/src/utils/openfpga_physical_tile_utils.cpp @@ -125,7 +125,8 @@ std::set find_physical_io_tile_located_sides( * which corresponds to the pin 'a2f[1]' of the 5th subtile 'io' in the physical tile *******************************************************************/ int find_physical_tile_pin_index(t_physical_tile_type_ptr physical_tile, std::string pin_name) { - int pin_idx = -1; + /* Deposit an invalid value */ + int pin_idx = physical_tile->num_pins; /* precheck: return unfound pin if the tile name does not match */ StringToken tokenizer(pin_name); std::vector pin_tokens = tokenizer.split("."); From ff69664c14e253faad830ab17f8805174a2226ea Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 27 Feb 2023 22:39:12 -0800 Subject: [PATCH 047/166] [core] syntax --- .../src/base/clock_network.cpp | 8 ++++---- .../src/annotation/append_clock_rr_graph.cpp | 17 ++++++++--------- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/libs/libclkarchopenfpga/src/base/clock_network.cpp b/libs/libclkarchopenfpga/src/base/clock_network.cpp index 2615000bb..f505ed4c2 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.cpp +++ b/libs/libclkarchopenfpga/src/base/clock_network.cpp @@ -244,7 +244,7 @@ std::vector ClockNetwork::spine_flatten_taps(const ClockSpineId& sp StringToken tokenizer(tap_name); std::vector pin_tokens = tokenizer.split("."); if (pin_tokens.size() != 2) { - VTR_LOG_ERROR("Invalid pin name '%s'. Expect .\n", pin_name.c_str()); + VTR_LOG_ERROR("Invalid pin name '%s'. Expect .\n", tap_name.c_str()); exit(1); } PortParser tile_parser(pin_tokens[0]); @@ -252,11 +252,11 @@ std::vector ClockNetwork::spine_flatten_taps(const ClockSpineId& sp PortParser pin_parser(pin_tokens[1]); BasicPort pin_info = pin_parser.port(); if (!tile_info.is_valid()) { - VTR_LOG_ERROR("Invalid pin name '%s' whose subtile index is not valid\n", pin_name.c_str()); + VTR_LOG_ERROR("Invalid pin name '%s' whose subtile index is not valid\n", tap_name.c_str()); exit(1); } if (!pin_info.is_valid()) { - VTR_LOG_ERROR("Invalid pin name '%s' whose pin index is not valid\n", pin_name.c_str()); + VTR_LOG_ERROR("Invalid pin name '%s' whose pin index is not valid\n", tap_name.c_str()); exit(1); } for (size_t& tile_idx : tile_info.pins()) { @@ -431,7 +431,7 @@ void ClockNetwork::add_spine_switch_point(const ClockSpineId& spine_id, void ClockNetwork::add_spine_tap(const ClockSpineId& spine_id, const std::string& pin_name) { VTR_ASSERT(valid_spine_id(spine_id)); - spine_taps_.push_back(pin_name); + spine_taps_[spine_id].push_back(pin_name); } bool ClockNetwork::link() { diff --git a/openfpga/src/annotation/append_clock_rr_graph.cpp b/openfpga/src/annotation/append_clock_rr_graph.cpp index a2277afa3..692127a9e 100644 --- a/openfpga/src/annotation/append_clock_rr_graph.cpp +++ b/openfpga/src/annotation/append_clock_rr_graph.cpp @@ -363,7 +363,7 @@ void try_find_and_add_clock_track2ipin_node(std::vector& des_nodes, const ClockTreeId& clk_tree, const ClockTreePinId& clk_pin) { t_physical_tile_type_ptr grid_type = grids[grid_coord.x()][grid_coord.y()].type; - for (std::string tap_pin_name : clk_ntwk.tap_pin_names(clk_tree, clk_pin)) { + for (std::string tap_pin_name : clk_ntwk.spine_flatten_taps(clk_tree, clk_pin)) { /* tap pin name could be 'io[5:5].a2f[0]' */ int grid_pin_idx = find_physical_tile_pin_index(grid_type, tap_pin_name); if (grid_pin_idx == grid_type->num_pins) { @@ -415,21 +415,20 @@ static std::vector find_clock_track2ipin_node(const DeviceGrid& grids, if (chan_type == CHANX) { /* Get the clock IPINs at the BOTTOM side of adjacent grids [x][y+1] */ vtr::Point bot_grid_coord(chan_coord.x(), chan_coord.y() + 1); - try_find_and_add_clock_track2ipin_node(des_nodes, rr_graph_view, bot_grid_coord, BOTTOM, clk_ntwk, clk_tree, clk_pin); - } + try_find_and_add_clock_track2ipin_node(des_nodes, grids, rr_graph_view, bot_grid_coord, BOTTOM, clk_ntwk, clk_tree, clk_pin); + /* Get the clock IPINs at the TOP side of adjacent grids [x][y] */ vtr::Point top_grid_coord(chan_coord.x(), chan_coord.y()); - try_find_and_add_clock_track2ipin_node(des_nodes, rr_graph_view, top_grid_coord, TOP, clk_ntwk, clk_tree, clk_pin); - + try_find_and_add_clock_track2ipin_node(des_nodes, grids, rr_graph_view, top_grid_coord, TOP, clk_ntwk, clk_tree, clk_pin); } else { VTR_ASSERT(chan_type == CHANY); /* Get the clock IPINs at the LEFT side of adjacent grids [x][y+1] */ vtr::Point left_grid_coord(chan_coord.x() + 1, chan_coord.y()); - try_find_and_add_clock_track2ipin_node(des_nodes, rr_graph_view, left_grid_coord, LEFT, clk_ntwk, clk_tree, clk_pin); + try_find_and_add_clock_track2ipin_node(des_nodes, grids, rr_graph_view, left_grid_coord, LEFT, clk_ntwk, clk_tree, clk_pin); /* Get the clock IPINs at the RIGHT side of adjacent grids [x][y] */ vtr::Point right_grid_coord(chan_coord.x(), chan_coord.y()); - try_find_and_add_clock_track2ipin_node(des_nodes, rr_graph_view, right_grid_coord, RIGHT, clk_ntwk, clk_tree, clk_pin); + try_find_and_add_clock_track2ipin_node(des_nodes, grids, rr_graph_view, right_grid_coord, RIGHT, clk_ntwk, clk_tree, clk_pin); } return des_nodes; @@ -527,7 +526,7 @@ static void add_rr_graph_clock_edges(RRGraphBuilder& rr_graph_builder, continue; } add_rr_graph_block_clock_edges(rr_graph_builder, num_edges_to_create, - clk_rr_lookup, rr_graph_view, clk_ntwk, + clk_rr_lookup, rr_graph_view, grids, clk_ntwk, chanx_coord, CHANX); } } @@ -543,7 +542,7 @@ static void add_rr_graph_clock_edges(RRGraphBuilder& rr_graph_builder, continue; } add_rr_graph_block_clock_edges(rr_graph_builder, num_edges_to_create, - clk_rr_lookup, rr_graph_view, clk_ntwk, + clk_rr_lookup, rr_graph_view, grids, clk_ntwk, chany_coord, CHANY); } } From 2735b708d35210dd3a55c42851271ef33f7ecf47 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 27 Feb 2023 22:59:44 -0800 Subject: [PATCH 048/166] [core] reworked the tapping XML syntax --- libs/libclkarchopenfpga/arch/example.xml | 26 +++------- .../src/base/clock_network.cpp | 24 ++++++---- .../src/base/clock_network.h | 13 ++--- .../src/io/clock_network_xml_constants.h | 5 +- .../src/io/read_xml_clock_network.cpp | 48 +++++++++++++------ .../src/io/write_xml_clock_network.cpp | 20 +++++--- .../src/annotation/append_clock_rr_graph.cpp | 2 +- 7 files changed, 77 insertions(+), 61 deletions(-) diff --git a/libs/libclkarchopenfpga/arch/example.xml b/libs/libclkarchopenfpga/arch/example.xml index 6defe943a..ac6e722dd 100644 --- a/libs/libclkarchopenfpga/arch/example.xml +++ b/libs/libclkarchopenfpga/arch/example.xml @@ -12,29 +12,15 @@ - + + + + + - - - - - - - - - - - - - - - - - - - + diff --git a/libs/libclkarchopenfpga/src/base/clock_network.cpp b/libs/libclkarchopenfpga/src/base/clock_network.cpp index f505ed4c2..0b13d49e4 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.cpp +++ b/libs/libclkarchopenfpga/src/base/clock_network.cpp @@ -232,15 +232,15 @@ vtr::Point ClockNetwork::spine_switch_point( return spine_switch_coords_[spine_id][size_t(switch_point_id)]; } -std::vector ClockNetwork::spine_taps(const ClockSpineId& spine_id) const { - VTR_ASSERT(valid_spine_id(spine_id)); - return spine_taps_[spine_id]; +std::vector ClockNetwork::tree_taps(const ClockTreeId& tree_id) const { + VTR_ASSERT(valid_tree_id(tree_id)); + return tree_taps_[tree_id]; } -std::vector ClockNetwork::spine_flatten_taps(const ClockSpineId& spine_id) const { - VTR_ASSERT(valid_spine_id(spine_id)); +std::vector ClockNetwork::tree_flatten_taps(const ClockTreeId& tree_id, const ClockTreePinId& clk_pin_id) const { + VTR_ASSERT(valid_tree_id(tree_id)); std::vector flatten_taps; - for (const std::string& tap_name : spine_taps_[spine_id]) { + for (const std::string& tap_name : tree_taps_[tree_id]) { StringToken tokenizer(tap_name); std::vector pin_tokens = tokenizer.split("."); if (pin_tokens.size() != 2) { @@ -262,6 +262,9 @@ std::vector ClockNetwork::spine_flatten_taps(const ClockSpineId& sp for (size_t& tile_idx : tile_info.pins()) { std::string flatten_tile_str = tile_info.get_name() + "[" + std::to_string(tile_idx) + "]"; for (size_t& pin_idx : pin_info.pins()) { + if (pin_idx != size_t(clk_pin_id)) { + continue; + } std::string flatten_pin_str = pin_info.get_name() + "[" + std::to_string(pin_idx) + "]"; flatten_taps.push_back(flatten_tile_str + "." + flatten_pin_str); } @@ -307,6 +310,7 @@ void ClockNetwork::reserve_trees(const size_t& num_trees) { tree_names_.reserve(num_trees); tree_widths_.reserve(num_trees); tree_top_spines_.reserve(num_trees); + tree_taps_.reserve(num_trees); } void ClockNetwork::set_default_segment(const RRSegmentId& seg_id) { @@ -333,6 +337,7 @@ ClockTreeId ClockNetwork::create_tree(const std::string& name, size_t width) { tree_names_.push_back(name); tree_widths_.push_back(width); tree_depths_.emplace_back(); + tree_taps_.emplace_back(); tree_top_spines_.emplace_back(); /* Register to fast look-up */ @@ -372,7 +377,6 @@ ClockSpineId ClockNetwork::create_spine(const std::string& name) { spine_parents_.emplace_back(); spine_children_.emplace_back(); spine_parent_trees_.emplace_back(); - spine_taps_.emplace_back(); /* Register to the lookup */ VTR_ASSERT(valid_spine_id(spine_id)); @@ -429,9 +433,9 @@ void ClockNetwork::add_spine_switch_point(const ClockSpineId& spine_id, spine_children_[spine_id].push_back(drive_spine_id); } -void ClockNetwork::add_spine_tap(const ClockSpineId& spine_id, const std::string& pin_name) { - VTR_ASSERT(valid_spine_id(spine_id)); - spine_taps_[spine_id].push_back(pin_name); +void ClockNetwork::add_tree_tap(const ClockTreeId& tree_id, const std::string& pin_name) { + VTR_ASSERT(valid_tree_id(tree_id)); + tree_taps_[tree_id].push_back(pin_name); } bool ClockNetwork::link() { diff --git a/libs/libclkarchopenfpga/src/base/clock_network.h b/libs/libclkarchopenfpga/src/base/clock_network.h index 53e3259c5..99951d055 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.h +++ b/libs/libclkarchopenfpga/src/base/clock_network.h @@ -105,12 +105,13 @@ class ClockNetwork { const ClockSpineId& spine_id, const ClockSwitchPointId& switch_point_id) const; /* Return the original list of tap pins that is in storage; useful for parsers */ - std::vector spine_taps(const ClockSpineId& spine_id) const; - /* Return the list of flatten tap pins. For example: clb[0:1].clk[2:3] is flatten to - * { clb[0].clk[2], clb[1].clk[2], clb[0].clk[3], clb[1].clk[3] } + std::vector tree_taps(const ClockTreeId& tree_id) const; + /* Return the list of flatten tap pins. For example: clb[0:1].clk[2:2] is flatten to + * { clb[0].clk[2], clb[1].clk[2] } * Useful to build clock routing resource graph + * Note that the clk_pin_id limits only 1 clock to be accessed */ - std::vector spine_flatten_taps(const ClockSpineId& spine_id) const; + std::vector tree_flatten_taps(const ClockTreeId& tree_id, const ClockTreePinId& clk_pin_id) const; /* Find a spine with a given name, if not found, return an valid id, otherwise * return an invalid one */ ClockSpineId find_spine(const std::string& name) const; @@ -153,7 +154,7 @@ class ClockNetwork { void add_spine_switch_point(const ClockSpineId& spine_id, const ClockSpineId& drive_spine_id, const vtr::Point& coord); - void add_spine_tap(const ClockSpineId& spine_id, const std::string& pin_name); + void add_tree_tap(const ClockTreeId& tree_id, const std::string& pin_name); /* Build internal links between clock tree, spines etc. This is also an * validator to verify the correctness of the clock network. Must run before * using the data! */ @@ -202,6 +203,7 @@ class ClockNetwork { vtr::vector tree_widths_; vtr::vector tree_depths_; vtr::vector> tree_top_spines_; + vtr::vector> tree_taps_; /* Basic information of each spine */ vtr::vector spine_ids_; @@ -209,7 +211,6 @@ class ClockNetwork { vtr::vector spine_levels_; vtr::vector> spine_start_points_; vtr::vector> spine_end_points_; - vtr::vector> spine_taps_; vtr::vector> spine_switch_points_; vtr::vector>> spine_switch_coords_; vtr::vector spine_parents_; diff --git a/libs/libclkarchopenfpga/src/io/clock_network_xml_constants.h b/libs/libclkarchopenfpga/src/io/clock_network_xml_constants.h index 8dc9871ec..569fdde7a 100644 --- a/libs/libclkarchopenfpga/src/io/clock_network_xml_constants.h +++ b/libs/libclkarchopenfpga/src/io/clock_network_xml_constants.h @@ -21,7 +21,8 @@ constexpr const char* XML_CLOCK_SPINE_SWITCH_POINT_NODE_NAME = "switch_point"; constexpr const char* XML_CLOCK_SPINE_SWITCH_POINT_ATTRIBUTE_TAP = "tap"; constexpr const char* XML_CLOCK_SPINE_SWITCH_POINT_ATTRIBUTE_X = "x"; constexpr const char* XML_CLOCK_SPINE_SWITCH_POINT_ATTRIBUTE_Y = "y"; -constexpr const char* XML_CLOCK_SPINE_TAP_NODE_NAME = "tap"; -constexpr const char* XML_CLOCK_SPINE_TAP_ATTRIBUTE_TILE_PIN = "tile_pin"; +constexpr const char* XML_CLOCK_TREE_TAPS_NODE_NAME = "taps"; +constexpr const char* XML_CLOCK_TREE_TAP_NODE_NAME = "tap"; +constexpr const char* XML_CLOCK_TREE_TAP_ATTRIBUTE_TILE_PIN = "tile_pin"; #endif diff --git a/libs/libclkarchopenfpga/src/io/read_xml_clock_network.cpp b/libs/libclkarchopenfpga/src/io/read_xml_clock_network.cpp index ee1ee34f9..3791be016 100644 --- a/libs/libclkarchopenfpga/src/io/read_xml_clock_network.cpp +++ b/libs/libclkarchopenfpga/src/io/read_xml_clock_network.cpp @@ -27,19 +27,36 @@ namespace openfpga { // Begin namespace openfpga /******************************************************************** * Parse XML codes of a to an object of ClockNetwork *******************************************************************/ -static void read_xml_clock_spine_tap( - pugi::xml_node& xml_switch_point, const pugiutil::loc_data& loc_data, - ClockNetwork& clk_ntwk, const ClockSpineId& spine_id) { - if (!clk_ntwk.valid_spine_id(spine_id)) { - archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_switch_point), - "Invalid id of a clock spine!\n"); +static void read_xml_clock_tree_tap( + pugi::xml_node& xml_tap, const pugiutil::loc_data& loc_data, + ClockNetwork& clk_ntwk, const ClockTreeId& tree_id) { + if (!clk_ntwk.valid_tree_id(tree_id)) { + archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_tap), + "Invalid id of a clock tree!\n"); } std::string tile_pin_name = - get_attribute(xml_switch_point, XML_CLOCK_SPINE_TAP_ATTRIBUTE_TILE_PIN, + get_attribute(xml_tap, XML_CLOCK_TREE_TAP_ATTRIBUTE_TILE_PIN, loc_data) .as_string(); - clk_ntwk.add_spine_tap(spine_id, tile_pin_name); + clk_ntwk.add_tree_tap(tree_id, tile_pin_name); +} + + +static void read_xml_clock_tree_taps( + pugi::xml_node& xml_taps, const pugiutil::loc_data& loc_data, + ClockNetwork& clk_ntwk, const ClockTreeId& tree_id) { + for (pugi::xml_node xml_tap : xml_taps.children()) { + /* Error out if the XML child has an invalid name! */ + if (xml_tap.name() == + std::string(XML_CLOCK_TREE_TAP_NODE_NAME)) { + read_xml_clock_tree_tap(xml_tap, loc_data, clk_ntwk, + tree_id); + } else { + bad_tag(xml_taps, loc_data, xml_tap, + {XML_CLOCK_TREE_TAP_NODE_NAME}); + } + } } /******************************************************************** @@ -131,12 +148,9 @@ static void read_xml_clock_spine(pugi::xml_node& xml_spine, std::string(XML_CLOCK_SPINE_SWITCH_POINT_NODE_NAME)) { read_xml_clock_spine_switch_point(xml_switch_point, loc_data, clk_ntwk, spine_id); - } else if (xml_switch_point.name() == - std::string(XML_CLOCK_SPINE_TAP_NODE_NAME)) { - read_xml_clock_spine_tap(xml_switch_point, loc_data, clk_ntwk, spine_id); } else { bad_tag(xml_switch_point, loc_data, xml_spine, - {XML_CLOCK_SPINE_SWITCH_POINT_NODE_NAME, XML_CLOCK_SPINE_TAP_NODE_NAME}); + {XML_CLOCK_SPINE_SWITCH_POINT_NODE_NAME}); } } } @@ -164,10 +178,14 @@ static void read_xml_clock_tree(pugi::xml_node& xml_clk_tree, for (pugi::xml_node xml_spine : xml_clk_tree.children()) { /* Error out if the XML child has an invalid name! */ - if (xml_spine.name() != std::string(XML_CLOCK_SPINE_NODE_NAME)) { - bad_tag(xml_spine, loc_data, xml_clk_tree, {XML_CLOCK_SPINE_NODE_NAME}); + if (xml_spine.name() == std::string(XML_CLOCK_SPINE_NODE_NAME)) { + read_xml_clock_spine(xml_spine, loc_data, clk_ntwk, tree_id); + } else if (xml_spine.name() == + std::string(XML_CLOCK_TREE_TAPS_NODE_NAME)) { + read_xml_clock_tree_taps(xml_spine, loc_data, clk_ntwk, tree_id); + } else { + bad_tag(xml_spine, loc_data, xml_clk_tree, {XML_CLOCK_SPINE_NODE_NAME, XML_CLOCK_TREE_TAPS_NODE_NAME}); } - read_xml_clock_spine(xml_spine, loc_data, clk_ntwk, tree_id); } } diff --git a/libs/libclkarchopenfpga/src/io/write_xml_clock_network.cpp b/libs/libclkarchopenfpga/src/io/write_xml_clock_network.cpp index 7910d6333..b350cafd1 100644 --- a/libs/libclkarchopenfpga/src/io/write_xml_clock_network.cpp +++ b/libs/libclkarchopenfpga/src/io/write_xml_clock_network.cpp @@ -23,19 +23,24 @@ namespace openfpga { // Begin namespace openfpga -static int write_xml_clock_spine_taps( - std::fstream& fp, const ClockNetwork& clk_ntwk, const ClockSpineId& spine_id) { - for (const std::string& tile_pin_name : clk_ntwk.spine_taps(spine_id)) { - openfpga::write_tab_to_file(fp, 3); - fp << "<" << XML_CLOCK_SPINE_TAP_NODE_NAME << ""; +static int write_xml_clock_tree_taps( + std::fstream& fp, const ClockNetwork& clk_ntwk, const ClockTreeId& tree_id) { + openfpga::write_tab_to_file(fp, 3); + fp << "<" << XML_CLOCK_TREE_TAPS_NODE_NAME << ">\n"; + for (const std::string& tile_pin_name : clk_ntwk.tree_taps(tree_id)) { + openfpga::write_tab_to_file(fp, 4); + fp << "<" << XML_CLOCK_TREE_TAP_NODE_NAME << ""; write_xml_attribute( - fp, XML_CLOCK_SPINE_TAP_ATTRIBUTE_TILE_PIN, + fp, XML_CLOCK_TREE_TAP_ATTRIBUTE_TILE_PIN, tile_pin_name.c_str()); fp << "/>" << "\n"; } + openfpga::write_tab_to_file(fp, 3); + fp << "\n"; + return 0; } @@ -82,7 +87,6 @@ static int write_xml_clock_spine(std::fstream& fp, const ClockNetwork& clk_ntwk, clk_ntwk.spine_switch_points(spine_id)) { write_xml_clock_spine_switch_point(fp, clk_ntwk, spine_id, switch_point_id); } - write_xml_clock_spine_taps(fp, clk_ntwk, spine_id); openfpga::write_tab_to_file(fp, 2); fp << "" diff --git a/openfpga/src/annotation/append_clock_rr_graph.cpp b/openfpga/src/annotation/append_clock_rr_graph.cpp index 692127a9e..51c96c046 100644 --- a/openfpga/src/annotation/append_clock_rr_graph.cpp +++ b/openfpga/src/annotation/append_clock_rr_graph.cpp @@ -363,7 +363,7 @@ void try_find_and_add_clock_track2ipin_node(std::vector& des_nodes, const ClockTreeId& clk_tree, const ClockTreePinId& clk_pin) { t_physical_tile_type_ptr grid_type = grids[grid_coord.x()][grid_coord.y()].type; - for (std::string tap_pin_name : clk_ntwk.spine_flatten_taps(clk_tree, clk_pin)) { + for (std::string tap_pin_name : clk_ntwk.tree_flatten_taps(clk_tree, clk_pin)) { /* tap pin name could be 'io[5:5].a2f[0]' */ int grid_pin_idx = find_physical_tile_pin_index(grid_type, tap_pin_name); if (grid_pin_idx == grid_type->num_pins) { From 8d5c21b14d5e8f798eb33f31f09f82ea01c41d7a Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 27 Feb 2023 23:00:15 -0800 Subject: [PATCH 049/166] [core] code format --- .../src/base/clock_network.cpp | 30 +++--- .../src/base/clock_network.h | 15 +-- .../src/io/read_xml_clock_network.cpp | 33 +++---- .../src/io/write_xml_clock_network.cpp | 10 +- .../src/annotation/append_clock_rr_graph.cpp | 96 ++++++++++--------- .../utils/openfpga_physical_tile_utils.cpp | 53 +++++++--- .../src/utils/openfpga_physical_tile_utils.h | 3 +- 7 files changed, 137 insertions(+), 103 deletions(-) diff --git a/libs/libclkarchopenfpga/src/base/clock_network.cpp b/libs/libclkarchopenfpga/src/base/clock_network.cpp index 0b13d49e4..d53e5bbef 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.cpp +++ b/libs/libclkarchopenfpga/src/base/clock_network.cpp @@ -2,10 +2,10 @@ #include +#include "openfpga_port_parser.h" +#include "openfpga_tokenizer.h" #include "vtr_assert.h" #include "vtr_log.h" -#include "openfpga_tokenizer.h" -#include "openfpga_port_parser.h" namespace openfpga { // Begin namespace openfpga @@ -232,19 +232,22 @@ vtr::Point ClockNetwork::spine_switch_point( return spine_switch_coords_[spine_id][size_t(switch_point_id)]; } -std::vector ClockNetwork::tree_taps(const ClockTreeId& tree_id) const { +std::vector ClockNetwork::tree_taps( + const ClockTreeId& tree_id) const { VTR_ASSERT(valid_tree_id(tree_id)); return tree_taps_[tree_id]; } -std::vector ClockNetwork::tree_flatten_taps(const ClockTreeId& tree_id, const ClockTreePinId& clk_pin_id) const { +std::vector ClockNetwork::tree_flatten_taps( + const ClockTreeId& tree_id, const ClockTreePinId& clk_pin_id) const { VTR_ASSERT(valid_tree_id(tree_id)); std::vector flatten_taps; for (const std::string& tap_name : tree_taps_[tree_id]) { StringToken tokenizer(tap_name); std::vector pin_tokens = tokenizer.split("."); if (pin_tokens.size() != 2) { - VTR_LOG_ERROR("Invalid pin name '%s'. Expect .\n", tap_name.c_str()); + VTR_LOG_ERROR("Invalid pin name '%s'. Expect .\n", + tap_name.c_str()); exit(1); } PortParser tile_parser(pin_tokens[0]); @@ -252,23 +255,27 @@ std::vector ClockNetwork::tree_flatten_taps(const ClockTreeId& tree PortParser pin_parser(pin_tokens[1]); BasicPort pin_info = pin_parser.port(); if (!tile_info.is_valid()) { - VTR_LOG_ERROR("Invalid pin name '%s' whose subtile index is not valid\n", tap_name.c_str()); + VTR_LOG_ERROR("Invalid pin name '%s' whose subtile index is not valid\n", + tap_name.c_str()); exit(1); } if (!pin_info.is_valid()) { - VTR_LOG_ERROR("Invalid pin name '%s' whose pin index is not valid\n", tap_name.c_str()); + VTR_LOG_ERROR("Invalid pin name '%s' whose pin index is not valid\n", + tap_name.c_str()); exit(1); } for (size_t& tile_idx : tile_info.pins()) { - std::string flatten_tile_str = tile_info.get_name() + "[" + std::to_string(tile_idx) + "]"; + std::string flatten_tile_str = + tile_info.get_name() + "[" + std::to_string(tile_idx) + "]"; for (size_t& pin_idx : pin_info.pins()) { if (pin_idx != size_t(clk_pin_id)) { continue; } - std::string flatten_pin_str = pin_info.get_name() + "[" + std::to_string(pin_idx) + "]"; + std::string flatten_pin_str = + pin_info.get_name() + "[" + std::to_string(pin_idx) + "]"; flatten_taps.push_back(flatten_tile_str + "." + flatten_pin_str); } - } + } } return flatten_taps; } @@ -433,7 +440,8 @@ void ClockNetwork::add_spine_switch_point(const ClockSpineId& spine_id, spine_children_[spine_id].push_back(drive_spine_id); } -void ClockNetwork::add_tree_tap(const ClockTreeId& tree_id, const std::string& pin_name) { +void ClockNetwork::add_tree_tap(const ClockTreeId& tree_id, + const std::string& pin_name) { VTR_ASSERT(valid_tree_id(tree_id)); tree_taps_[tree_id].push_back(pin_name); } diff --git a/libs/libclkarchopenfpga/src/base/clock_network.h b/libs/libclkarchopenfpga/src/base/clock_network.h index 99951d055..d29f5711e 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.h +++ b/libs/libclkarchopenfpga/src/base/clock_network.h @@ -104,14 +104,15 @@ class ClockNetwork { vtr::Point spine_switch_point( const ClockSpineId& spine_id, const ClockSwitchPointId& switch_point_id) const; - /* Return the original list of tap pins that is in storage; useful for parsers */ - std::vector tree_taps(const ClockTreeId& tree_id) const; - /* Return the list of flatten tap pins. For example: clb[0:1].clk[2:2] is flatten to - * { clb[0].clk[2], clb[1].clk[2] } - * Useful to build clock routing resource graph - * Note that the clk_pin_id limits only 1 clock to be accessed + /* Return the original list of tap pins that is in storage; useful for parsers */ - std::vector tree_flatten_taps(const ClockTreeId& tree_id, const ClockTreePinId& clk_pin_id) const; + std::vector tree_taps(const ClockTreeId& tree_id) const; + /* Return the list of flatten tap pins. For example: clb[0:1].clk[2:2] is + * flatten to { clb[0].clk[2], clb[1].clk[2] } Useful to build clock routing + * resource graph Note that the clk_pin_id limits only 1 clock to be accessed + */ + std::vector tree_flatten_taps( + const ClockTreeId& tree_id, const ClockTreePinId& clk_pin_id) const; /* Find a spine with a given name, if not found, return an valid id, otherwise * return an invalid one */ ClockSpineId find_spine(const std::string& name) const; diff --git a/libs/libclkarchopenfpga/src/io/read_xml_clock_network.cpp b/libs/libclkarchopenfpga/src/io/read_xml_clock_network.cpp index 3791be016..5db46c6dd 100644 --- a/libs/libclkarchopenfpga/src/io/read_xml_clock_network.cpp +++ b/libs/libclkarchopenfpga/src/io/read_xml_clock_network.cpp @@ -27,34 +27,31 @@ namespace openfpga { // Begin namespace openfpga /******************************************************************** * Parse XML codes of a to an object of ClockNetwork *******************************************************************/ -static void read_xml_clock_tree_tap( - pugi::xml_node& xml_tap, const pugiutil::loc_data& loc_data, - ClockNetwork& clk_ntwk, const ClockTreeId& tree_id) { +static void read_xml_clock_tree_tap(pugi::xml_node& xml_tap, + const pugiutil::loc_data& loc_data, + ClockNetwork& clk_ntwk, + const ClockTreeId& tree_id) { if (!clk_ntwk.valid_tree_id(tree_id)) { archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_tap), "Invalid id of a clock tree!\n"); } std::string tile_pin_name = - get_attribute(xml_tap, XML_CLOCK_TREE_TAP_ATTRIBUTE_TILE_PIN, - loc_data) + get_attribute(xml_tap, XML_CLOCK_TREE_TAP_ATTRIBUTE_TILE_PIN, loc_data) .as_string(); clk_ntwk.add_tree_tap(tree_id, tile_pin_name); } - -static void read_xml_clock_tree_taps( - pugi::xml_node& xml_taps, const pugiutil::loc_data& loc_data, - ClockNetwork& clk_ntwk, const ClockTreeId& tree_id) { +static void read_xml_clock_tree_taps(pugi::xml_node& xml_taps, + const pugiutil::loc_data& loc_data, + ClockNetwork& clk_ntwk, + const ClockTreeId& tree_id) { for (pugi::xml_node xml_tap : xml_taps.children()) { /* Error out if the XML child has an invalid name! */ - if (xml_tap.name() == - std::string(XML_CLOCK_TREE_TAP_NODE_NAME)) { - read_xml_clock_tree_tap(xml_tap, loc_data, clk_ntwk, - tree_id); + if (xml_tap.name() == std::string(XML_CLOCK_TREE_TAP_NODE_NAME)) { + read_xml_clock_tree_tap(xml_tap, loc_data, clk_ntwk, tree_id); } else { - bad_tag(xml_taps, loc_data, xml_tap, - {XML_CLOCK_TREE_TAP_NODE_NAME}); + bad_tag(xml_taps, loc_data, xml_tap, {XML_CLOCK_TREE_TAP_NODE_NAME}); } } } @@ -180,11 +177,11 @@ static void read_xml_clock_tree(pugi::xml_node& xml_clk_tree, /* Error out if the XML child has an invalid name! */ if (xml_spine.name() == std::string(XML_CLOCK_SPINE_NODE_NAME)) { read_xml_clock_spine(xml_spine, loc_data, clk_ntwk, tree_id); - } else if (xml_spine.name() == - std::string(XML_CLOCK_TREE_TAPS_NODE_NAME)) { + } else if (xml_spine.name() == std::string(XML_CLOCK_TREE_TAPS_NODE_NAME)) { read_xml_clock_tree_taps(xml_spine, loc_data, clk_ntwk, tree_id); } else { - bad_tag(xml_spine, loc_data, xml_clk_tree, {XML_CLOCK_SPINE_NODE_NAME, XML_CLOCK_TREE_TAPS_NODE_NAME}); + bad_tag(xml_spine, loc_data, xml_clk_tree, + {XML_CLOCK_SPINE_NODE_NAME, XML_CLOCK_TREE_TAPS_NODE_NAME}); } } } diff --git a/libs/libclkarchopenfpga/src/io/write_xml_clock_network.cpp b/libs/libclkarchopenfpga/src/io/write_xml_clock_network.cpp index b350cafd1..6430bf43c 100644 --- a/libs/libclkarchopenfpga/src/io/write_xml_clock_network.cpp +++ b/libs/libclkarchopenfpga/src/io/write_xml_clock_network.cpp @@ -23,17 +23,17 @@ namespace openfpga { // Begin namespace openfpga -static int write_xml_clock_tree_taps( - std::fstream& fp, const ClockNetwork& clk_ntwk, const ClockTreeId& tree_id) { +static int write_xml_clock_tree_taps(std::fstream& fp, + const ClockNetwork& clk_ntwk, + const ClockTreeId& tree_id) { openfpga::write_tab_to_file(fp, 3); fp << "<" << XML_CLOCK_TREE_TAPS_NODE_NAME << ">\n"; for (const std::string& tile_pin_name : clk_ntwk.tree_taps(tree_id)) { openfpga::write_tab_to_file(fp, 4); fp << "<" << XML_CLOCK_TREE_TAP_NODE_NAME << ""; - write_xml_attribute( - fp, XML_CLOCK_TREE_TAP_ATTRIBUTE_TILE_PIN, - tile_pin_name.c_str()); + write_xml_attribute(fp, XML_CLOCK_TREE_TAP_ATTRIBUTE_TILE_PIN, + tile_pin_name.c_str()); fp << "/>" << "\n"; } diff --git a/openfpga/src/annotation/append_clock_rr_graph.cpp b/openfpga/src/annotation/append_clock_rr_graph.cpp index 51c96c046..a682ac525 100644 --- a/openfpga/src/annotation/append_clock_rr_graph.cpp +++ b/openfpga/src/annotation/append_clock_rr_graph.cpp @@ -1,13 +1,13 @@ #include "append_clock_rr_graph.h" #include "command_exit_codes.h" +#include "openfpga_physical_tile_utils.h" #include "rr_graph_builder_utils.h" #include "rr_graph_cost.h" #include "vtr_assert.h" #include "vtr_geometry.h" #include "vtr_log.h" #include "vtr_time.h" -#include "openfpga_physical_tile_utils.h" /* begin namespace openfpga */ namespace openfpga { @@ -166,8 +166,8 @@ static void add_rr_graph_clock_nodes(RRGraphBuilder& rr_graph_builder, } /******************************************************************** - * Find the destination CHANX|CHANY nodes for a driver clock node in a given connection - *block There are two types of destination nodes: + * Find the destination CHANX|CHANY nodes for a driver clock node in a given + *connection block There are two types of destination nodes: * - Straight connection where the driver clock node connects to another clock *node in the same direction and at the same level as well as clock index For *example @@ -350,26 +350,25 @@ static std::vector find_clock_track2track_node( /******************************************************************** * Try to find an IPIN of a grid which satisfy the requirement of clock pins - * that has been defined in clock network. If the IPIN does exist in a + * that has been defined in clock network. If the IPIN does exist in a * routing resource graph, add it to the node list *******************************************************************/ -static -void try_find_and_add_clock_track2ipin_node(std::vector& des_nodes, - const DeviceGrid& grids, - const RRGraphView& rr_graph_view, - const vtr::Point& grid_coord, - const e_side& pin_side, - const ClockNetwork& clk_ntwk, - const ClockTreeId& clk_tree, - const ClockTreePinId& clk_pin) { - t_physical_tile_type_ptr grid_type = grids[grid_coord.x()][grid_coord.y()].type; - for (std::string tap_pin_name : clk_ntwk.tree_flatten_taps(clk_tree, clk_pin)) { +static void try_find_and_add_clock_track2ipin_node( + std::vector& des_nodes, const DeviceGrid& grids, + const RRGraphView& rr_graph_view, const vtr::Point& grid_coord, + const e_side& pin_side, const ClockNetwork& clk_ntwk, + const ClockTreeId& clk_tree, const ClockTreePinId& clk_pin) { + t_physical_tile_type_ptr grid_type = + grids[grid_coord.x()][grid_coord.y()].type; + for (std::string tap_pin_name : + clk_ntwk.tree_flatten_taps(clk_tree, clk_pin)) { /* tap pin name could be 'io[5:5].a2f[0]' */ int grid_pin_idx = find_physical_tile_pin_index(grid_type, tap_pin_name); if (grid_pin_idx == grid_type->num_pins) { continue; } - RRNodeId des_node = rr_graph_view.node_lookup().find_node(grid_coord.x(), grid_coord.y(), IPIN, grid_pin_idx, pin_side); + RRNodeId des_node = rr_graph_view.node_lookup().find_node( + grid_coord.x(), grid_coord.y(), IPIN, grid_pin_idx, pin_side); if (rr_graph_view.valid_node(des_node)) { des_nodes.push_back(des_node); } @@ -378,11 +377,10 @@ void try_find_and_add_clock_track2ipin_node(std::vector& des_nodes, /******************************************************************** * Find the destination IPIN nodes for a driver clock node in a given connection - *block. - * For CHANX, the IPIN nodes are typically on the BOTTOM and TOP sides of adjacent grids - * For CHANY, the IPIN nodes are typically on the LEFT and RIGHT sides of adjacent grids - * For example - * Grid[1][2] + *block. + * For CHANX, the IPIN nodes are typically on the BOTTOM and TOP sides of + *adjacent grids For CHANY, the IPIN nodes are typically on the LEFT and RIGHT + *sides of adjacent grids For example Grid[1][2] * ^ * | * clk0_lvl2_chanx[1][1] -->---------+ @@ -403,32 +401,38 @@ void try_find_and_add_clock_track2ipin_node(std::vector& des_nodes, * | [x][y] | [x][y] | [x+1][y] | * +----------+----------+------------+ *******************************************************************/ -static std::vector find_clock_track2ipin_node(const DeviceGrid& grids, - const RRGraphView& rr_graph_view, - const t_rr_type& chan_type, - const vtr::Point& chan_coord, - const ClockNetwork& clk_ntwk, - const ClockTreeId& clk_tree, - const ClockTreePinId& clk_pin) { +static std::vector find_clock_track2ipin_node( + const DeviceGrid& grids, const RRGraphView& rr_graph_view, + const t_rr_type& chan_type, const vtr::Point& chan_coord, + const ClockNetwork& clk_ntwk, const ClockTreeId& clk_tree, + const ClockTreePinId& clk_pin) { std::vector des_nodes; if (chan_type == CHANX) { /* Get the clock IPINs at the BOTTOM side of adjacent grids [x][y+1] */ vtr::Point bot_grid_coord(chan_coord.x(), chan_coord.y() + 1); - try_find_and_add_clock_track2ipin_node(des_nodes, grids, rr_graph_view, bot_grid_coord, BOTTOM, clk_ntwk, clk_tree, clk_pin); + try_find_and_add_clock_track2ipin_node(des_nodes, grids, rr_graph_view, + bot_grid_coord, BOTTOM, clk_ntwk, + clk_tree, clk_pin); /* Get the clock IPINs at the TOP side of adjacent grids [x][y] */ vtr::Point top_grid_coord(chan_coord.x(), chan_coord.y()); - try_find_and_add_clock_track2ipin_node(des_nodes, grids, rr_graph_view, top_grid_coord, TOP, clk_ntwk, clk_tree, clk_pin); + try_find_and_add_clock_track2ipin_node(des_nodes, grids, rr_graph_view, + top_grid_coord, TOP, clk_ntwk, + clk_tree, clk_pin); } else { VTR_ASSERT(chan_type == CHANY); /* Get the clock IPINs at the LEFT side of adjacent grids [x][y+1] */ vtr::Point left_grid_coord(chan_coord.x() + 1, chan_coord.y()); - try_find_and_add_clock_track2ipin_node(des_nodes, grids, rr_graph_view, left_grid_coord, LEFT, clk_ntwk, clk_tree, clk_pin); + try_find_and_add_clock_track2ipin_node(des_nodes, grids, rr_graph_view, + left_grid_coord, LEFT, clk_ntwk, + clk_tree, clk_pin); /* Get the clock IPINs at the RIGHT side of adjacent grids [x][y] */ vtr::Point right_grid_coord(chan_coord.x(), chan_coord.y()); - try_find_and_add_clock_track2ipin_node(des_nodes, grids, rr_graph_view, right_grid_coord, RIGHT, clk_ntwk, clk_tree, clk_pin); + try_find_and_add_clock_track2ipin_node(des_nodes, grids, rr_graph_view, + right_grid_coord, RIGHT, clk_ntwk, + clk_tree, clk_pin); } return des_nodes; @@ -437,14 +441,11 @@ static std::vector find_clock_track2ipin_node(const DeviceGrid& grids, /******************************************************************** * Add edges for the clock nodes in a given connection block *******************************************************************/ -static void add_rr_graph_block_clock_edges(RRGraphBuilder& rr_graph_builder, - size_t& num_edges_to_create, - const RRClockSpatialLookup& clk_rr_lookup, - const RRGraphView& rr_graph_view, - const DeviceGrid& grids, - const ClockNetwork& clk_ntwk, - const vtr::Point chan_coord, - const t_rr_type& chan_type) { +static void add_rr_graph_block_clock_edges( + RRGraphBuilder& rr_graph_builder, size_t& num_edges_to_create, + const RRClockSpatialLookup& clk_rr_lookup, const RRGraphView& rr_graph_view, + const DeviceGrid& grids, const ClockNetwork& clk_ntwk, + const vtr::Point chan_coord, const t_rr_type& chan_type) { size_t edge_count = 0; for (auto itree : clk_ntwk.trees()) { for (auto ilvl : clk_ntwk.levels(itree)) { @@ -457,8 +458,8 @@ static void add_rr_graph_block_clock_edges(RRGraphBuilder& rr_graph_builder, if (!clk_ntwk.is_last_level(itree, ilvl)) { /* find the fan-out clock node through lookup */ for (RRNodeId des_node : find_clock_track2track_node( - rr_graph_view, clk_ntwk, clk_rr_lookup, chan_type, chan_coord, - itree, ilvl, ipin, node_dir)) { + rr_graph_view, clk_ntwk, clk_rr_lookup, chan_type, + chan_coord, itree, ilvl, ipin, node_dir)) { /* Create edges */ VTR_ASSERT(rr_graph_view.valid_node(des_node)); rr_graph_builder.create_edge(src_node, des_node, @@ -470,7 +471,8 @@ static void add_rr_graph_block_clock_edges(RRGraphBuilder& rr_graph_builder, * should drive some grid IPINs which are clocks */ if (clk_ntwk.is_last_level(itree, ilvl)) { for (RRNodeId des_node : find_clock_track2ipin_node( - grids, rr_graph_view, chan_type, chan_coord, clk_ntwk, itree, ipin)) { + grids, rr_graph_view, chan_type, chan_coord, clk_ntwk, itree, + ipin)) { /* Create edges */ VTR_ASSERT(rr_graph_view.valid_node(des_node)); rr_graph_builder.create_edge(src_node, des_node, @@ -526,8 +528,8 @@ static void add_rr_graph_clock_edges(RRGraphBuilder& rr_graph_builder, continue; } add_rr_graph_block_clock_edges(rr_graph_builder, num_edges_to_create, - clk_rr_lookup, rr_graph_view, grids, clk_ntwk, - chanx_coord, CHANX); + clk_rr_lookup, rr_graph_view, grids, + clk_ntwk, chanx_coord, CHANX); } } @@ -542,8 +544,8 @@ static void add_rr_graph_clock_edges(RRGraphBuilder& rr_graph_builder, continue; } add_rr_graph_block_clock_edges(rr_graph_builder, num_edges_to_create, - clk_rr_lookup, rr_graph_view, grids, clk_ntwk, - chany_coord, CHANY); + clk_rr_lookup, rr_graph_view, grids, + clk_ntwk, chany_coord, CHANY); } } } diff --git a/openfpga/src/utils/openfpga_physical_tile_utils.cpp b/openfpga/src/utils/openfpga_physical_tile_utils.cpp index 18e019ca3..614ade73c 100644 --- a/openfpga/src/utils/openfpga_physical_tile_utils.cpp +++ b/openfpga/src/utils/openfpga_physical_tile_utils.cpp @@ -11,9 +11,9 @@ /* Headers from openfpgautil library */ #include "openfpga_device_grid_utils.h" #include "openfpga_physical_tile_utils.h" +#include "openfpga_port_parser.h" #include "openfpga_side_manager.h" #include "openfpga_tokenizer.h" -#include "openfpga_port_parser.h" /* begin namespace openfpga */ namespace openfpga { @@ -122,16 +122,19 @@ std::set find_physical_io_tile_located_sides( * Find the pin index of a physical tile which matches the given name. * For example, * io[5:5].a2f[1] - * which corresponds to the pin 'a2f[1]' of the 5th subtile 'io' in the physical tile + * which corresponds to the pin 'a2f[1]' of the 5th subtile 'io' in the physical + *tile *******************************************************************/ -int find_physical_tile_pin_index(t_physical_tile_type_ptr physical_tile, std::string pin_name) { +int find_physical_tile_pin_index(t_physical_tile_type_ptr physical_tile, + std::string pin_name) { /* Deposit an invalid value */ int pin_idx = physical_tile->num_pins; /* precheck: return unfound pin if the tile name does not match */ StringToken tokenizer(pin_name); std::vector pin_tokens = tokenizer.split("."); if (pin_tokens.size() != 2) { - VTR_LOG_ERROR("Invalid pin name '%s'. Expect .\n", pin_name.c_str()); + VTR_LOG_ERROR("Invalid pin name '%s'. Expect .\n", + pin_name.c_str()); exit(1); } PortParser tile_parser(pin_tokens[0]); @@ -140,16 +143,26 @@ int find_physical_tile_pin_index(t_physical_tile_type_ptr physical_tile, std::st return pin_idx; } if (!tile_info.is_valid()) { - VTR_LOG_ERROR("Invalid pin name '%s' whose subtile index is not valid, expect [0, %lu]\n", pin_name.c_str(), physical_tile->capacity - 1); + VTR_LOG_ERROR( + "Invalid pin name '%s' whose subtile index is not valid, expect [0, " + "%lu]\n", + pin_name.c_str(), physical_tile->capacity - 1); exit(1); } /* precheck: return unfound pin if the subtile index does not match */ if (tile_info.get_width() != 1) { - VTR_LOG_ERROR("Invalid pin name '%s' whose subtile index range should be 1. For example, clb[1:1]\n", pin_name.c_str()); + VTR_LOG_ERROR( + "Invalid pin name '%s' whose subtile index range should be 1. For " + "example, clb[1:1]\n", + pin_name.c_str()); exit(1); } - if (tile_info.get_lsb() < 0 || tile_info.get_msb() > physical_tile->capacity - 1) { - VTR_LOG_ERROR("Invalid pin name '%s' whose subtile index is out of range, expect [0, %lu]\n", pin_name.c_str(), physical_tile->capacity - 1); + if (tile_info.get_lsb() < 0 || + tile_info.get_msb() > physical_tile->capacity - 1) { + VTR_LOG_ERROR( + "Invalid pin name '%s' whose subtile index is out of range, expect [0, " + "%lu]\n", + pin_name.c_str(), physical_tile->capacity - 1); exit(1); } /* precheck: return unfound pin if the pin index does not match */ @@ -157,7 +170,10 @@ int find_physical_tile_pin_index(t_physical_tile_type_ptr physical_tile, std::st BasicPort pin_info = pin_parser.port(); /* precheck: return unfound pin if the subtile index does not match */ if (pin_info.get_width() != 1) { - VTR_LOG_ERROR("Invalid pin name '%s' whose pin index range should be 1. For example, clb[1:1].I[2:2]\n", pin_name.c_str()); + VTR_LOG_ERROR( + "Invalid pin name '%s' whose pin index range should be 1. For example, " + "clb[1:1].I[2:2]\n", + pin_name.c_str()); exit(1); } @@ -171,15 +187,25 @@ int find_physical_tile_pin_index(t_physical_tile_type_ptr physical_tile, std::st continue; } if (!pin_info.is_valid()) { - VTR_LOG_ERROR("Invalid pin name '%s' whose pin index is not valid, expect [0, %lu]\n", pin_name.c_str(), sub_tile_port.num_pins - 1); + VTR_LOG_ERROR( + "Invalid pin name '%s' whose pin index is not valid, expect [0, " + "%lu]\n", + pin_name.c_str(), sub_tile_port.num_pins - 1); exit(1); } - if (pin_info.get_lsb() < 0 || pin_info.get_msb() > sub_tile_port.num_pins - 1) { - VTR_LOG_ERROR("Invalid pin name '%s' whose pin index is out of range, expect [0, %lu]\n", pin_name.c_str(), sub_tile_port.num_pins - 1); + if (pin_info.get_lsb() < 0 || + pin_info.get_msb() > sub_tile_port.num_pins - 1) { + VTR_LOG_ERROR( + "Invalid pin name '%s' whose pin index is out of range, expect [0, " + "%lu]\n", + pin_name.c_str(), sub_tile_port.num_pins - 1); exit(1); } /* Reach here, we get the port we want, return the accumulated index */ - size_t accumulated_pin_idx = sub_tile_port.absolute_first_pin_index + sub_tile.num_phy_pins * (tile_info.get_lsb() - sub_tile.capacity.low) + pin_info.get_lsb(); + size_t accumulated_pin_idx = + sub_tile_port.absolute_first_pin_index + + sub_tile.num_phy_pins * (tile_info.get_lsb() - sub_tile.capacity.low) + + pin_info.get_lsb(); return accumulated_pin_idx; } } @@ -187,5 +213,4 @@ int find_physical_tile_pin_index(t_physical_tile_type_ptr physical_tile, std::st return pin_idx; } - } /* end namespace openfpga */ diff --git a/openfpga/src/utils/openfpga_physical_tile_utils.h b/openfpga/src/utils/openfpga_physical_tile_utils.h index cc5ce754e..1ac98f321 100644 --- a/openfpga/src/utils/openfpga_physical_tile_utils.h +++ b/openfpga/src/utils/openfpga_physical_tile_utils.h @@ -27,7 +27,8 @@ float find_physical_tile_pin_Fc(t_physical_tile_type_ptr type, const int& pin); std::set find_physical_io_tile_located_sides( const DeviceGrid& grids, t_physical_tile_type_ptr physical_tile); -int find_physical_tile_pin_index(t_physical_tile_type_ptr physical_tile, std::string pin_name); +int find_physical_tile_pin_index(t_physical_tile_type_ptr physical_tile, + std::string pin_name); } /* end namespace openfpga */ From 6f2572324ee09a1111d9e56d0c02a361db6ba2aa Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 28 Feb 2023 11:52:38 -0800 Subject: [PATCH 050/166] [core] developing route clock rr_graph command --- .../src/annotation/append_clock_rr_graph.cpp | 4 +- .../src/annotation/route_clock_rr_graph.cpp | 50 +++++++++++++++++++ .../src/annotation/route_clock_rr_graph.h | 26 ++++++++++ .../src/base/openfpga_link_arch_template.h | 18 +++++++ .../base/openfpga_setup_command_template.h | 42 ++++++++++++++++ 5 files changed, 138 insertions(+), 2 deletions(-) create mode 100644 openfpga/src/annotation/route_clock_rr_graph.cpp create mode 100644 openfpga/src/annotation/route_clock_rr_graph.h diff --git a/openfpga/src/annotation/append_clock_rr_graph.cpp b/openfpga/src/annotation/append_clock_rr_graph.cpp index a682ac525..78ff37802 100644 --- a/openfpga/src/annotation/append_clock_rr_graph.cpp +++ b/openfpga/src/annotation/append_clock_rr_graph.cpp @@ -467,7 +467,7 @@ static void add_rr_graph_block_clock_edges( edge_count++; } } - /* TODO: If this is the clock node at the last level of the tree, + /* If this is the clock node at the last level of the tree, * should drive some grid IPINs which are clocks */ if (clk_ntwk.is_last_level(itree, ilvl)) { for (RRNodeId des_node : find_clock_track2ipin_node( @@ -594,7 +594,7 @@ int append_clock_rr_graph(DeviceContext& vpr_device_ctx, VTR_ASSERT(num_clock_nodes + orig_num_nodes == vpr_device_ctx.rr_graph.num_nodes()); - /* TODO: Add edges between clock nodes*/ + /* Add edges between clock nodes*/ size_t num_clock_edges = 0; add_rr_graph_clock_edges( vpr_device_ctx.rr_graph_builder, num_clock_edges, diff --git a/openfpga/src/annotation/route_clock_rr_graph.cpp b/openfpga/src/annotation/route_clock_rr_graph.cpp new file mode 100644 index 000000000..fe1b61ed3 --- /dev/null +++ b/openfpga/src/annotation/route_clock_rr_graph.cpp @@ -0,0 +1,50 @@ +#include "route_clock_rr_graph.h" + +#include "command_exit_codes.h" +#include "vtr_assert.h" +#include "vtr_geometry.h" +#include "vtr_log.h" +#include "vtr_time.h" + +/* begin namespace openfpga */ +namespace openfpga { + +/******************************************************************** + * Append a programmable clock network to an existing routing resource graph + * This function will do the following jobs: + * - Estimate the number of clock nodes and pre-allocate memory + * - Add clock nodes + * - Build edges between clock nodes + * - Sanity checks + *******************************************************************/ +int route_clock_rr_graph(VprRoutingAnnotation& vpr_routing_annotation, + const DeviceContext& vpr_device_ctx, + const RRClockSpatialLookup& clk_rr_lookup, + const ClockNetwork& clk_ntwk, const bool& verbose) { + vtr::ScopedStartFinishTimer timer( + "Route programmable clock network based on routing resource graph"); + + /* Skip if there is no clock tree */ + if (clk_ntwk.num_trees()) { + VTR_LOG( + "Skip due to 0 clock trees.\nDouble check your clock architecture " + "definition if this is unexpected\n"); + return CMD_EXEC_SUCCESS; + } + + /* Report any clock structure we do not support yet! */ + if (clk_ntwk.num_trees() > 1) { + VTR_LOG( + "Currently only support 1 clock tree in programmable clock " + "architecture\nPlease update your clock architecture definition\n"); + return CMD_EXEC_FATAL_ERROR; + } + + /* TODO: Route spines one by one */ + + /* TODO: Sanity checks */ + + return CMD_EXEC_SUCCESS; +} + +} /* end namespace openfpga */ diff --git a/openfpga/src/annotation/route_clock_rr_graph.h b/openfpga/src/annotation/route_clock_rr_graph.h new file mode 100644 index 000000000..5e5eda9e9 --- /dev/null +++ b/openfpga/src/annotation/route_clock_rr_graph.h @@ -0,0 +1,26 @@ +#ifndef ROUTE_CLOCK_RR_GRAPH_H +#define ROUTE_CLOCK_RR_GRAPH_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +#include "clock_network.h" +#include "rr_clock_spatial_lookup.h" +#include "vpr_context.h" +#include "vpr_routing_annotation.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ + +/* begin namespace openfpga */ +namespace openfpga { + +int route_clock_rr_graph(VprRoutingAnnotation& vpr_routing_annotation, + const DeviceContext& vpr_device_ctx, + const RRClockSpatialLookup& clk_rr_lookup, + const ClockNetwork& clk_ntwk, const bool& verbose); + +} /* end namespace openfpga */ + +#endif diff --git a/openfpga/src/base/openfpga_link_arch_template.h b/openfpga/src/base/openfpga_link_arch_template.h index 28612bfe7..759cc0c1f 100644 --- a/openfpga/src/base/openfpga_link_arch_template.h +++ b/openfpga/src/base/openfpga_link_arch_template.h @@ -23,6 +23,7 @@ #include "openfpga_rr_graph_support.h" #include "pb_type_utils.h" #include "read_activity.h" +#include "route_clock_rr_graph.h" #include "vpr_device_annotation.h" #include "vtr_assert.h" #include "vtr_log.h" @@ -203,6 +204,23 @@ int append_clock_rr_graph_template(T& openfpga_ctx, const Command& cmd, openfpga_ctx.clock_arch(), cmd_context.option_enable(cmd, opt_verbose)); } +/******************************************************************** + * Top-level function to route a clock network based on the clock spines + * defined in clock architecture + *******************************************************************/ +template +int route_clock_rr_graph_template(T& openfpga_ctx, const Command& cmd, + const CommandContext& cmd_context) { + vtr::ScopedStartFinishTimer timer("Route clock routing resource graph"); + + CommandOptionId opt_verbose = cmd.option("verbose"); + + return route_clock_rr_graph( + openfpga_ctx.mutable_vpr_routing_annotation(), g_vpr_ctx.device(), + openfpga_ctx.clock_rr_lookup(), openfpga_ctx.clock_arch(), + cmd_context.option_enable(cmd, opt_verbose)); +} + } /* end namespace openfpga */ #endif diff --git a/openfpga/src/base/openfpga_setup_command_template.h b/openfpga/src/base/openfpga_setup_command_template.h index c22f114e4..fe8652344 100644 --- a/openfpga/src/base/openfpga_setup_command_template.h +++ b/openfpga/src/base/openfpga_setup_command_template.h @@ -656,6 +656,35 @@ ShellCommandId add_append_clock_rr_graph_command_template( return shell_cmd_id; } +/******************************************************************** + * - Add a command to Shell environment: route_clock_rr_graph + * - Add associated options + * - Add command dependency + *******************************************************************/ +template +ShellCommandId add_route_clock_rr_graph_command_template( + openfpga::Shell& shell, const ShellCommandClassId& cmd_class_id, + const std::vector& dependent_cmds, const bool& hidden) { + Command shell_cmd("route_clock_rr_graph"); + + /* Add an option '--verbose' */ + shell_cmd.add_option("verbose", false, "Show verbose outputs"); + + /* Add command 'pb_pin_fixup' to the Shell */ + ShellCommandId shell_cmd_id = shell.add_command( + shell_cmd, + "Route clock network based on routing resource graph built by VPR.", + hidden); + shell.set_command_class(shell_cmd_id, cmd_class_id); + shell.set_command_execute_function(shell_cmd_id, + route_clock_rr_graph_template); + + /* Add command dependency to the Shell */ + shell.set_command_dependency(shell_cmd_id, dependent_cmds); + + return shell_cmd_id; +} + template void add_setup_command_templates(openfpga::Shell& shell, const bool& hidden = false) { @@ -769,6 +798,19 @@ void add_setup_command_templates(openfpga::Shell& shell, shell, openfpga_setup_cmd_class, append_clock_rr_graph_dependent_cmds, hidden); + /******************************** + * Command 'route_clock_rr_graph' + */ + /* The 'route_clock_rr_graph' command should NOT be executed before + * 'read_openfpga_clock_arch' and 'link_arch' */ + std::vector route_clock_rr_graph_dependent_cmds; + route_clock_rr_graph_dependent_cmds.push_back( + read_openfpga_clock_arch_cmd_id); + route_clock_rr_graph_dependent_cmds.push_back(link_arch_cmd_id); + add_route_clock_rr_graph_command_template( + shell, openfpga_setup_cmd_class, route_clock_rr_graph_dependent_cmds, + hidden); + /******************************** * Command 'write_gsb' */ From bd2608d3e03338d0fccfa524f5db7bdeffdb959b Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 28 Feb 2023 15:41:37 -0800 Subject: [PATCH 051/166] [core] dev --- .../src/annotation/route_clock_rr_graph.cpp | 72 +++++++++++++++++-- 1 file changed, 67 insertions(+), 5 deletions(-) diff --git a/openfpga/src/annotation/route_clock_rr_graph.cpp b/openfpga/src/annotation/route_clock_rr_graph.cpp index fe1b61ed3..b26122a9f 100644 --- a/openfpga/src/annotation/route_clock_rr_graph.cpp +++ b/openfpga/src/annotation/route_clock_rr_graph.cpp @@ -10,12 +10,68 @@ namespace openfpga { /******************************************************************** - * Append a programmable clock network to an existing routing resource graph + * Route a clock tree on an existing routing resource graph + * The strategy is to route spine one by one + * - route the spine from the starting point to the ending point + * - route the spine-to-spine switching points + * - route the spine-to-IPIN connections (only for the last level) + *******************************************************************/ +static +int route_clock_tree_rr_graph() { + for (auto ispine : clk_ntwk.spines(clk_tree)) { + for (auto ipin : clk_ntwk.pins(clk_tree)) { + /* Route the spine from starting point to ending point */ + std::vector> spine_coords = clk_ntwk.spine_coords(ispine); + for (size_t icoord = 0; icoord < spine_coords.size() - 1; ++icoord) { + vtr::Point src_coord = spine_coords[icoord]; + vtr::Point des_coord = spine_coords[icoord + 1]; + Direction src_spine_direction = clk_ntwk.spine_direction(ispine); + Direction des_spine_direction = clk_ntwk.spine_direction(ispine); + ClockLevelId src_spine_level = clk_ntwk.spine_level(ispine); + ClockLevelId des_spine_level = clk_ntwk.spine_level(ispine); + RRNodeId src_node = clk_rr_lookup.find_node(src_coord.x(), src_coord.y(), clk_tree, src_spine_level, ipin, src_spine_direction); + RRNodeId des_node = clk_rr_lookup.find_node(des_coord.x(), des_coord.y(), clk_tree, des_spine_level, ipin, des_spine_direction); + vpr_routing_annotation.set_rr_node_prev_node(rr_graph, des_node, src_node); + } + /* Route the spine-to-spine switching points */ + for (ClockSwitchPointId switch_point_id : clk_ntwk.spine_switch_points(ispine)) { + vtr::Point src_coord = clk_ntwk.spine_switch_point(ispine, switch_point_id); + ClockSpineId des_spine = clk_ntwk.spine_switch_point_tap(ispine, switch_point_id); + vtr::Point des_coord = clk_ntwk.spine_start_point(des_spine); + Direction src_spine_direction = clk_ntwk.spine_direction(ispine); + Direction des_spine_direction = clk_ntwk.spine_direction(des_spine); + ClockLevelId src_spine_level = clk_ntwk.spine_level(ispine); + ClockLevelId des_spine_level = clk_ntwk.spine_level(des_spine); + RRNodeId src_node = clk_rr_lookup.find_node(src_coord.x(), src_coord.y(), clk_tree, src_spine_level, ipin, src_spine_direction); + RRNodeId des_node = clk_rr_lookup.find_node(des_coord.x(), des_coord.y(), clk_tree, des_spine_level, ipin, des_spine_direction); + vpr_routing_annotation.set_rr_node_prev_node(rr_graph, des_node, src_node); + } + /* Route the spine-to-IPIN connections (only for the last level) */ + if (clk_ntwk.is_last_level(clk_tree, ispine)) { + /* Connect to any fan-out node which is IPIN */ + for (size_t icoord = 0; icoord < spine_coords.size(); ++icoord) { + vtr::Point src_coord = spine_coords[icoord]; + Direction src_spine_direction = clk_ntwk.spine_direction(ispine); + ClockLevelId src_spine_level = clk_ntwk.spine_level(ispine); + RRNodeId src_node = clk_rr_lookup.find_node(src_coord.x(), src_coord.y(), clk_tree, src_spine_level, ipin, src_spine_direction); + for (RREdgeId edge : rr_graph.edges(src_node)) { + RRNodeId des_node = rr_graph.edge_sink_node(edge); + if (rr_graph.node_type(des_node) == IPIN) { + vpr_routing_annotation.set_rr_node_prev_node(rr_graph, des_node, src_node); + } + } + } + } + } + } + return CMD_EXEC_SUCCESS; +} + +/******************************************************************** + * Route a clock network based on an existing routing resource graph * This function will do the following jobs: - * - Estimate the number of clock nodes and pre-allocate memory - * - Add clock nodes - * - Build edges between clock nodes - * - Sanity checks + * - configure the routing annotation w.r.t. the clock node connections + * - quick check to ensure routing is valid *******************************************************************/ int route_clock_rr_graph(VprRoutingAnnotation& vpr_routing_annotation, const DeviceContext& vpr_device_ctx, @@ -41,6 +97,12 @@ int route_clock_rr_graph(VprRoutingAnnotation& vpr_routing_annotation, } /* TODO: Route spines one by one */ + for (auto itree : clk_ntwk.trees()) { + int status = route_clock_tree_rr_graph(); + if (status == CMD_EXEC_FATAL_ERROR) { + return status; + } + } /* TODO: Sanity checks */ From 2ff8fb87379517e72057c594934a289f0a983506 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 28 Feb 2023 16:52:54 -0800 Subject: [PATCH 052/166] [core] wrapping up clock routing command --- .../src/base/clock_network.cpp | 56 +++++++++++++ .../src/base/clock_network.h | 9 +++ .../src/annotation/route_clock_rr_graph.cpp | 81 ++++++++++++------- 3 files changed, 119 insertions(+), 27 deletions(-) diff --git a/libs/libclkarchopenfpga/src/base/clock_network.cpp b/libs/libclkarchopenfpga/src/base/clock_network.cpp index d53e5bbef..a8a065ffe 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.cpp +++ b/libs/libclkarchopenfpga/src/base/clock_network.cpp @@ -68,6 +68,15 @@ std::vector ClockNetwork::pins( return ret; } +std::vector ClockNetwork::pins( + const ClockTreeId& tree_id) const { + std::vector ret; + for (size_t i = 0; i < tree_width(tree_id); ++i) { + ret.push_back(ClockTreePinId(i)); + } + return ret; +} + /************************************************************************ * Public Accessors : Basic data query ***********************************************************************/ @@ -206,6 +215,48 @@ vtr::Point ClockNetwork::spine_end_point( return spine_end_points_[spine_id]; } +ClockLevelId ClockNetwork::spine_level(const ClockSpineId& spine_id) const { + VTR_ASSERT(valid_spine_id(spine_id)); + if (is_dirty_) { + VTR_LOG_ERROR("Unable to identify spine level when data is still dirty!\n"); + exit(1); + } + return ClockLevelId(spine_levels_[spine_id]); +} + +std::vector> ClockNetwork::spine_coordinates( + const ClockSpineId& spine_id) const { + vtr::Point start_coord = spine_start_point(spine_id); + vtr::Point end_coord = spine_end_point(spine_id); + std::vector> coords; + if (Direction::INC == spine_direction(spine_id)) { + if (CHANX == spine_track_type(spine_id)) { + for (int ix = start_coord.x(); ix <= end_coord.x(); ix++) { + coords.push_back(vtr::Point(ix, start_coord.y())); + } + } else { + VTR_ASSERT(CHANY == spine_track_type(spine_id)); + for (int iy = start_coord.y(); iy <= end_coord.y(); iy++) { + coords.push_back(vtr::Point(start_coord.x(), iy)); + } + } + } else { + VTR_ASSERT(Direction::DEC == spine_direction(spine_id)); + if (CHANX == spine_track_type(spine_id)) { + for (int ix = start_coord.x(); ix >= end_coord.x(); ix--) { + coords.push_back(vtr::Point(ix, start_coord.y())); + } + } else { + VTR_ASSERT(CHANY == spine_track_type(spine_id)); + for (int iy = start_coord.y(); iy >= end_coord.y(); iy--) { + coords.push_back(vtr::Point(start_coord.x(), iy)); + } + } + } + + return coords; +} + std::vector ClockNetwork::spine_switch_points( const ClockSpineId& spine_id) const { VTR_ASSERT(valid_spine_id(spine_id)); @@ -571,6 +622,11 @@ bool ClockNetwork::is_last_level(const ClockTreeId& tree_id, return valid_tree_id(tree_id) && (size_t(lvl_id) == tree_depth(tree_id) - 1); } +bool ClockNetwork::is_last_level(const ClockSpineId& spine_id) const { + return spine_level(spine_id) == + ClockLevelId(tree_depth(spine_parent_trees_[spine_id]) - 1); +} + bool ClockNetwork::valid_spine_id(const ClockSpineId& spine_id) const { return (size_t(spine_id) < spine_ids_.size()) && (spine_id == spine_ids_[spine_id]); diff --git a/libs/libclkarchopenfpga/src/base/clock_network.h b/libs/libclkarchopenfpga/src/base/clock_network.h index d29f5711e..14ab3fab4 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.h +++ b/libs/libclkarchopenfpga/src/base/clock_network.h @@ -59,6 +59,7 @@ class ClockNetwork { const ClockLevelId& level, const t_rr_type& track_type, const Direction& direction) const; + std::vector pins(const ClockTreeId& tree_id) const; public: /* Public Accessors: Basic data query */ /* Return the number of routing tracks required by a selected clock tree at a @@ -80,6 +81,12 @@ class ClockNetwork { std::string spine_name(const ClockSpineId& spine_id) const; vtr::Point spine_start_point(const ClockSpineId& spine_id) const; vtr::Point spine_end_point(const ClockSpineId& spine_id) const; + /* Return the level where the spine locates in the multi-layer clock tree + * structure */ + ClockLevelId spine_level(const ClockSpineId& spine_id) const; + /* Return the list of coordinates that a spine will go across */ + std::vector> spine_coordinates( + const ClockSpineId& spine_id) const; /* Identify the direction of a spine, depending on its starting and ending * points * - CHANX represents a horizental routing track @@ -169,6 +176,8 @@ class ClockNetwork { const ClockLevelId& lvl_id) const; /* Identify if the level is the last level of the given tree */ bool is_last_level(const ClockTreeId& tree_id, const ClockLevelId& lvl) const; + /* Identify if the spine is at the last level of its tree */ + bool is_last_level(const ClockSpineId& spine_id) const; /* Show if the tree id is a valid for data queries */ bool valid_spine_id(const ClockSpineId& spine_id) const; bool valid_spine_switch_point_id( diff --git a/openfpga/src/annotation/route_clock_rr_graph.cpp b/openfpga/src/annotation/route_clock_rr_graph.cpp index b26122a9f..47a70f965 100644 --- a/openfpga/src/annotation/route_clock_rr_graph.cpp +++ b/openfpga/src/annotation/route_clock_rr_graph.cpp @@ -16,48 +16,73 @@ namespace openfpga { * - route the spine-to-spine switching points * - route the spine-to-IPIN connections (only for the last level) *******************************************************************/ -static -int route_clock_tree_rr_graph() { +static int route_clock_tree_rr_graph( + VprRoutingAnnotation& vpr_routing_annotation, const RRGraphView& rr_graph, + const RRClockSpatialLookup& clk_rr_lookup, const ClockNetwork& clk_ntwk, + const ClockTreeId clk_tree) { for (auto ispine : clk_ntwk.spines(clk_tree)) { for (auto ipin : clk_ntwk.pins(clk_tree)) { /* Route the spine from starting point to ending point */ - std::vector> spine_coords = clk_ntwk.spine_coords(ispine); + std::vector> spine_coords = + clk_ntwk.spine_coordinates(ispine); for (size_t icoord = 0; icoord < spine_coords.size() - 1; ++icoord) { - vtr::Point src_coord = spine_coords[icoord]; - vtr::Point des_coord = spine_coords[icoord + 1]; + vtr::Point src_coord = spine_coords[icoord]; + vtr::Point des_coord = spine_coords[icoord + 1]; Direction src_spine_direction = clk_ntwk.spine_direction(ispine); Direction des_spine_direction = clk_ntwk.spine_direction(ispine); - ClockLevelId src_spine_level = clk_ntwk.spine_level(ispine); - ClockLevelId des_spine_level = clk_ntwk.spine_level(ispine); - RRNodeId src_node = clk_rr_lookup.find_node(src_coord.x(), src_coord.y(), clk_tree, src_spine_level, ipin, src_spine_direction); - RRNodeId des_node = clk_rr_lookup.find_node(des_coord.x(), des_coord.y(), clk_tree, des_spine_level, ipin, des_spine_direction); - vpr_routing_annotation.set_rr_node_prev_node(rr_graph, des_node, src_node); + ClockLevelId src_spine_level = clk_ntwk.spine_level(ispine); + ClockLevelId des_spine_level = clk_ntwk.spine_level(ispine); + RRNodeId src_node = + clk_rr_lookup.find_node(src_coord.x(), src_coord.y(), clk_tree, + src_spine_level, ipin, src_spine_direction); + RRNodeId des_node = + clk_rr_lookup.find_node(des_coord.x(), des_coord.y(), clk_tree, + des_spine_level, ipin, des_spine_direction); + VTR_ASSERT(rr_graph.valid_node(src_node)); + VTR_ASSERT(rr_graph.valid_node(des_node)); + vpr_routing_annotation.set_rr_node_prev_node(rr_graph, des_node, + src_node); } /* Route the spine-to-spine switching points */ - for (ClockSwitchPointId switch_point_id : clk_ntwk.spine_switch_points(ispine)) { - vtr::Point src_coord = clk_ntwk.spine_switch_point(ispine, switch_point_id); - ClockSpineId des_spine = clk_ntwk.spine_switch_point_tap(ispine, switch_point_id); - vtr::Point des_coord = clk_ntwk.spine_start_point(des_spine); + for (ClockSwitchPointId switch_point_id : + clk_ntwk.spine_switch_points(ispine)) { + vtr::Point src_coord = + clk_ntwk.spine_switch_point(ispine, switch_point_id); + ClockSpineId des_spine = + clk_ntwk.spine_switch_point_tap(ispine, switch_point_id); + vtr::Point des_coord = clk_ntwk.spine_start_point(des_spine); Direction src_spine_direction = clk_ntwk.spine_direction(ispine); Direction des_spine_direction = clk_ntwk.spine_direction(des_spine); - ClockLevelId src_spine_level = clk_ntwk.spine_level(ispine); - ClockLevelId des_spine_level = clk_ntwk.spine_level(des_spine); - RRNodeId src_node = clk_rr_lookup.find_node(src_coord.x(), src_coord.y(), clk_tree, src_spine_level, ipin, src_spine_direction); - RRNodeId des_node = clk_rr_lookup.find_node(des_coord.x(), des_coord.y(), clk_tree, des_spine_level, ipin, des_spine_direction); - vpr_routing_annotation.set_rr_node_prev_node(rr_graph, des_node, src_node); + ClockLevelId src_spine_level = clk_ntwk.spine_level(ispine); + ClockLevelId des_spine_level = clk_ntwk.spine_level(des_spine); + RRNodeId src_node = + clk_rr_lookup.find_node(src_coord.x(), src_coord.y(), clk_tree, + src_spine_level, ipin, src_spine_direction); + RRNodeId des_node = + clk_rr_lookup.find_node(des_coord.x(), des_coord.y(), clk_tree, + des_spine_level, ipin, des_spine_direction); + VTR_ASSERT(rr_graph.valid_node(src_node)); + VTR_ASSERT(rr_graph.valid_node(des_node)); + vpr_routing_annotation.set_rr_node_prev_node(rr_graph, des_node, + src_node); } /* Route the spine-to-IPIN connections (only for the last level) */ - if (clk_ntwk.is_last_level(clk_tree, ispine)) { + if (clk_ntwk.is_last_level(ispine)) { /* Connect to any fan-out node which is IPIN */ for (size_t icoord = 0; icoord < spine_coords.size(); ++icoord) { - vtr::Point src_coord = spine_coords[icoord]; + vtr::Point src_coord = spine_coords[icoord]; Direction src_spine_direction = clk_ntwk.spine_direction(ispine); - ClockLevelId src_spine_level = clk_ntwk.spine_level(ispine); - RRNodeId src_node = clk_rr_lookup.find_node(src_coord.x(), src_coord.y(), clk_tree, src_spine_level, ipin, src_spine_direction); - for (RREdgeId edge : rr_graph.edges(src_node)) { + ClockLevelId src_spine_level = clk_ntwk.spine_level(ispine); + RRNodeId src_node = + clk_rr_lookup.find_node(src_coord.x(), src_coord.y(), clk_tree, + src_spine_level, ipin, src_spine_direction); + for (RREdgeId edge : rr_graph.edge_range(src_node)) { RRNodeId des_node = rr_graph.edge_sink_node(edge); if (rr_graph.node_type(des_node) == IPIN) { - vpr_routing_annotation.set_rr_node_prev_node(rr_graph, des_node, src_node); + VTR_ASSERT(rr_graph.valid_node(src_node)); + VTR_ASSERT(rr_graph.valid_node(des_node)); + vpr_routing_annotation.set_rr_node_prev_node(rr_graph, des_node, + src_node); } } } @@ -96,9 +121,11 @@ int route_clock_rr_graph(VprRoutingAnnotation& vpr_routing_annotation, return CMD_EXEC_FATAL_ERROR; } - /* TODO: Route spines one by one */ + /* Route spines one by one */ for (auto itree : clk_ntwk.trees()) { - int status = route_clock_tree_rr_graph(); + int status = + route_clock_tree_rr_graph(vpr_routing_annotation, vpr_device_ctx.rr_graph, + clk_rr_lookup, clk_ntwk, itree); if (status == CMD_EXEC_FATAL_ERROR) { return status; } From 7732907623cafc3547dadbe9c7a5f26b03a7314d Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 28 Feb 2023 17:01:11 -0800 Subject: [PATCH 053/166] [core] format --- openfpga/src/annotation/route_clock_rr_graph.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/openfpga/src/annotation/route_clock_rr_graph.cpp b/openfpga/src/annotation/route_clock_rr_graph.cpp index 47a70f965..1b4e8a206 100644 --- a/openfpga/src/annotation/route_clock_rr_graph.cpp +++ b/openfpga/src/annotation/route_clock_rr_graph.cpp @@ -19,12 +19,16 @@ namespace openfpga { static int route_clock_tree_rr_graph( VprRoutingAnnotation& vpr_routing_annotation, const RRGraphView& rr_graph, const RRClockSpatialLookup& clk_rr_lookup, const ClockNetwork& clk_ntwk, - const ClockTreeId clk_tree) { + const ClockTreeId clk_tree, const bool& verbose) { for (auto ispine : clk_ntwk.spines(clk_tree)) { + VTR_LOGV(verbose, "Routing spine '%s'...\n", + clk_ntwk.spine_name(ispine).c_str()); for (auto ipin : clk_ntwk.pins(clk_tree)) { /* Route the spine from starting point to ending point */ std::vector> spine_coords = clk_ntwk.spine_coordinates(ispine); + VTR_LOGV(verbose, "Routing backbone of spine '%s'...\n", + clk_ntwk.spine_name(ispine).c_str()); for (size_t icoord = 0; icoord < spine_coords.size() - 1; ++icoord) { vtr::Point src_coord = spine_coords[icoord]; vtr::Point des_coord = spine_coords[icoord + 1]; @@ -44,6 +48,8 @@ static int route_clock_tree_rr_graph( src_node); } /* Route the spine-to-spine switching points */ + VTR_LOGV(verbose, "Routing switch points of spine '%s'...\n", + clk_ntwk.spine_name(ispine).c_str()); for (ClockSwitchPointId switch_point_id : clk_ntwk.spine_switch_points(ispine)) { vtr::Point src_coord = @@ -68,6 +74,8 @@ static int route_clock_tree_rr_graph( } /* Route the spine-to-IPIN connections (only for the last level) */ if (clk_ntwk.is_last_level(ispine)) { + VTR_LOGV(verbose, "Routing clock taps of spine '%s'...\n", + clk_ntwk.spine_name(ispine).c_str()); /* Connect to any fan-out node which is IPIN */ for (size_t icoord = 0; icoord < spine_coords.size(); ++icoord) { vtr::Point src_coord = spine_coords[icoord]; @@ -123,12 +131,15 @@ int route_clock_rr_graph(VprRoutingAnnotation& vpr_routing_annotation, /* Route spines one by one */ for (auto itree : clk_ntwk.trees()) { + VTR_LOGV(verbose, "Routing clock tree '%s'...\n", + clk_ntwk.tree_name(itree).c_str()); int status = route_clock_tree_rr_graph(vpr_routing_annotation, vpr_device_ctx.rr_graph, - clk_rr_lookup, clk_ntwk, itree); + clk_rr_lookup, clk_ntwk, itree, verbose); if (status == CMD_EXEC_FATAL_ERROR) { return status; } + VTR_LOGV(verbose, "Done\n"); } /* TODO: Sanity checks */ From 9baaf9ea06e90170a9b823ef431482a1e7287bcd Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 28 Feb 2023 20:40:14 -0800 Subject: [PATCH 054/166] [core] fix compiler warnings --- openfpga/src/utils/openfpga_physical_tile_utils.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/openfpga/src/utils/openfpga_physical_tile_utils.cpp b/openfpga/src/utils/openfpga_physical_tile_utils.cpp index 614ade73c..c4272ab09 100644 --- a/openfpga/src/utils/openfpga_physical_tile_utils.cpp +++ b/openfpga/src/utils/openfpga_physical_tile_utils.cpp @@ -157,8 +157,7 @@ int find_physical_tile_pin_index(t_physical_tile_type_ptr physical_tile, pin_name.c_str()); exit(1); } - if (tile_info.get_lsb() < 0 || - tile_info.get_msb() > physical_tile->capacity - 1) { + if (tile_info.get_msb() > size_t(physical_tile->capacity) - 1) { VTR_LOG_ERROR( "Invalid pin name '%s' whose subtile index is out of range, expect [0, " "%lu]\n", @@ -193,8 +192,7 @@ int find_physical_tile_pin_index(t_physical_tile_type_ptr physical_tile, pin_name.c_str(), sub_tile_port.num_pins - 1); exit(1); } - if (pin_info.get_lsb() < 0 || - pin_info.get_msb() > sub_tile_port.num_pins - 1) { + if (pin_info.get_msb() > size_t(sub_tile_port.num_pins) - 1) { VTR_LOG_ERROR( "Invalid pin name '%s' whose pin index is out of range, expect [0, " "%lu]\n", From 780dec6b1b2775e0e6f1111643d482ccc22a618b Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 28 Feb 2023 21:46:57 -0800 Subject: [PATCH 055/166] [test] add a new test to validate the programmable clock arch --- .../k4_N4_40nm_Ntwk1clk2lvl_cc_openfpga.xml | 197 ++++++++++ .../example_clkntwk_script.openfpga | 75 ++++ .../regression_test_scripts/basic_reg_test.sh | 3 + .../config/clk_arch_1clk_2layer.xml | 17 + .../homo_1clock_2layer/config/task.conf | 47 +++ .../k4_N4_tileable_Ntwk1clk2lvl_40nm.xml | 338 ++++++++++++++++++ 6 files changed, 677 insertions(+) create mode 100644 openfpga_flow/openfpga_arch/k4_N4_40nm_Ntwk1clk2lvl_cc_openfpga.xml create mode 100644 openfpga_flow/openfpga_shell_scripts/example_clkntwk_script.openfpga create mode 100644 openfpga_flow/tasks/basic_tests/clock_network/homo_1clock_2layer/config/clk_arch_1clk_2layer.xml create mode 100644 openfpga_flow/tasks/basic_tests/clock_network/homo_1clock_2layer/config/task.conf create mode 100644 openfpga_flow/vpr_arch/k4_N4_tileable_Ntwk1clk2lvl_40nm.xml diff --git a/openfpga_flow/openfpga_arch/k4_N4_40nm_Ntwk1clk2lvl_cc_openfpga.xml b/openfpga_flow/openfpga_arch/k4_N4_40nm_Ntwk1clk2lvl_cc_openfpga.xml new file mode 100644 index 000000000..398fed3e2 --- /dev/null +++ b/openfpga_flow/openfpga_arch/k4_N4_40nm_Ntwk1clk2lvl_cc_openfpga.xml @@ -0,0 +1,197 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + + + + + 10e-12 5e-12 5e-12 + + + 10e-12 5e-12 5e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/openfpga_flow/openfpga_shell_scripts/example_clkntwk_script.openfpga b/openfpga_flow/openfpga_shell_scripts/example_clkntwk_script.openfpga new file mode 100644 index 000000000..112f758fd --- /dev/null +++ b/openfpga_flow/openfpga_shell_scripts/example_clkntwk_script.openfpga @@ -0,0 +1,75 @@ +# Run VPR for the 'and' design +#--write_rr_graph example_rr_graph.xml +vpr ${VPR_ARCH_FILE} ${VPR_TESTBENCH_BLIF} \ + --clock_modeling ideal \ + --device ${OPENFPGA_VPR_DEVICE_LAYOUT} \ + --route_chan_width ${OPENFPGA_VPR_ROUTE_CHAN_WIDTH} + +# Read OpenFPGA architecture definition +read_openfpga_arch -f ${OPENFPGA_ARCH_FILE} + +# Read OpenFPGA simulation settings +read_openfpga_simulation_setting -f ${OPENFPGA_SIM_SETTING_FILE} + +# Read OpenFPGA clock architecture +read_openfpga_clock_arch -f ${OPENFPGA_CLOCK_ARCH_FILE} + +# Append clock network to vpr's routing resource graph +append_clock_rr_graph + +# Annotate the OpenFPGA architecture to VPR data base +# to debug use --verbose options +link_openfpga_arch --activity_file ${ACTIVITY_FILE} --sort_gsb_chan_node_in_edges + +# Route clock based on clock network definition +route_clock_rr_graph + +# Check and correct any naming conflicts in the BLIF netlist +check_netlist_naming_conflict --fix --report ./netlist_renaming.xml + +# Apply fix-up to Look-Up Table truth tables based on packing results +lut_truth_table_fixup + +# Build the module graph +# - Enabled compression on routing architecture modules +# - Enable pin duplication on grid modules +build_fabric --compress_routing #--verbose + +# Write the fabric hierarchy of module graph to a file +# This is used by hierarchical PnR flows +write_fabric_hierarchy --file ./fabric_hierarchy.txt + +# Repack the netlist to physical pbs +# This must be done before bitstream generator and testbench generation +# Strongly recommend it is done after all the fix-up have been applied +repack #--verbose + +# Build the bitstream +# - Output the fabric-independent bitstream to a file +build_architecture_bitstream --verbose --write_file fabric_independent_bitstream.xml + +# Build fabric-dependent bitstream +build_fabric_bitstream --verbose + +# Write fabric-dependent bitstream +write_fabric_bitstream --file fabric_bitstream.bit --format plain_text + +# Write the Verilog netlist for FPGA fabric +# - Enable the use of explicit port mapping in Verilog netlist +write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --print_user_defined_template --verbose + +# Write the Verilog testbench for FPGA fabric +# - We suggest the use of same output directory as fabric Verilog netlists +# - Must specify the reference benchmark file if you want to output any testbenches +# - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA +# - Enable pre-configured top-level testbench which is a fast verification skipping programming phase +# - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init --bitstream fabric_bitstream.bit +write_preconfigured_fabric_wrapper --embed_bitstream iverilog --file ./SRC --explicit_port_mapping +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping + +# Finish and exit OpenFPGA +exit + +# Note : +# To run verification at the end of the flow maintain source in ./SRC directory diff --git a/openfpga_flow/regression_test_scripts/basic_reg_test.sh b/openfpga_flow/regression_test_scripts/basic_reg_test.sh index a8f6c82aa..848941b69 100755 --- a/openfpga_flow/regression_test_scripts/basic_reg_test.sh +++ b/openfpga_flow/regression_test_scripts/basic_reg_test.sh @@ -163,6 +163,9 @@ run-task basic_tests/global_tile_ports/global_tile_reset $@ run-task basic_tests/global_tile_ports/global_tile_4clock $@ run-task basic_tests/global_tile_ports/global_tile_4clock_pin $@ +echo -e "Testing programmable clock architecture"; +run-task basic_tests/clock_network/homo_1clock_2layer $@ + echo -e "Testing configuration chain of a K4N4 FPGA using .blif generated by yosys+verific"; run-task basic_tests/verific_test $@ diff --git a/openfpga_flow/tasks/basic_tests/clock_network/homo_1clock_2layer/config/clk_arch_1clk_2layer.xml b/openfpga_flow/tasks/basic_tests/clock_network/homo_1clock_2layer/config/clk_arch_1clk_2layer.xml new file mode 100644 index 000000000..330da638d --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/clock_network/homo_1clock_2layer/config/clk_arch_1clk_2layer.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/openfpga_flow/tasks/basic_tests/clock_network/homo_1clock_2layer/config/task.conf b/openfpga_flow/tasks/basic_tests/clock_network/homo_1clock_2layer/config/task.conf new file mode 100644 index 000000000..3b0bc7f72 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/clock_network/homo_1clock_2layer/config/task.conf @@ -0,0 +1,47 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = true +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=yosys_vpr + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/example_clkntwk_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_Ntwk1clk2lvl_cc_openfpga.xml +openfpga_clock_arch_file=${TASK_DIR}/config/clk_arch_1clk_2layer.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout=2x2 +openfpga_vpr_route_chan_width=20 + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_Ntwk1clk2lvl_40nm.xml + +[BENCHMARKS] +#bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v +#bench1=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/or2/or2.v +bench2=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2_latch/and2_latch.v + +[SYNTHESIS_PARAM] +bench_read_verilog_options_common = -nolatches +bench0_top = and2 +bench0_chan_width = 300 + +bench1_top = or2 +bench1_chan_width = 300 + +bench2_top = and2_latch +bench2_chan_width = 300 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= +vpr_fpga_verilog_formal_verification_top_netlist= diff --git a/openfpga_flow/vpr_arch/k4_N4_tileable_Ntwk1clk2lvl_40nm.xml b/openfpga_flow/vpr_arch/k4_N4_tileable_Ntwk1clk2lvl_40nm.xml new file mode 100644 index 000000000..586cae9b7 --- /dev/null +++ b/openfpga_flow/vpr_arch/k4_N4_tileable_Ntwk1clk2lvl_40nm.xml @@ -0,0 +1,338 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + io.outpad io.inpad + io.outpad io.inpad + io.outpad io.inpad + io.outpad io.inpad + + + + + + + + + + + + + + + + clb.clk + clb.I[0:4] clb.O[0:1] + clb.I[5:9] clb.O[2:3] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 1 1 1 1 + 1 1 1 1 + + + + 1 1 1 1 1 + 1 1 1 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 261e-12 + 261e-12 + 261e-12 + 261e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 5917446fbef9049a6962f4677b57be36dc77eaf7 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 28 Feb 2023 22:01:49 -0800 Subject: [PATCH 056/166] [arch] code format --- openfpga_flow/vpr_arch/k4_N4_tileable_Ntwk1clk2lvl_40nm.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openfpga_flow/vpr_arch/k4_N4_tileable_Ntwk1clk2lvl_40nm.xml b/openfpga_flow/vpr_arch/k4_N4_tileable_Ntwk1clk2lvl_40nm.xml index 586cae9b7..5d5371df5 100644 --- a/openfpga_flow/vpr_arch/k4_N4_tileable_Ntwk1clk2lvl_40nm.xml +++ b/openfpga_flow/vpr_arch/k4_N4_tileable_Ntwk1clk2lvl_40nm.xml @@ -67,7 +67,7 @@ clb.clk clb.I[0:4] clb.O[0:1] clb.I[5:9] clb.O[2:3] - + From 60ff29898749db3fc6af1051cb6130fbc341fafe Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 28 Feb 2023 22:36:41 -0800 Subject: [PATCH 057/166] [lib] add new feature to enable clock tree connection to global ports of tiles --- .../src/read_xml_tile_annotation.cpp | 8 ++++++++ libs/libarchopenfpga/src/tile_annotation.cpp | 13 +++++++++++++ libs/libarchopenfpga/src/tile_annotation.h | 5 +++++ .../src/write_xml_tile_annotation.cpp | 8 ++++++++ 4 files changed, 34 insertions(+) diff --git a/libs/libarchopenfpga/src/read_xml_tile_annotation.cpp b/libs/libarchopenfpga/src/read_xml_tile_annotation.cpp index 219c562f4..6b27d0017 100644 --- a/libs/libarchopenfpga/src/read_xml_tile_annotation.cpp +++ b/libs/libarchopenfpga/src/read_xml_tile_annotation.cpp @@ -89,6 +89,14 @@ static void read_xml_tile_global_port_annotation( get_attribute(xml_tile, "is_clock", loc_data, pugiutil::ReqOpt::OPTIONAL) .as_bool(false)); + /* Get clock tree attributes if this is a clock */ + if (tile_annotation.global_port_is_clock(tile_global_port_id)) { + tile_annotation.set_global_port_clock_arch_tree_name( + tile_global_port_id, get_attribute(xml_tile, "clock_arch_tree_name", + loc_data, pugiutil::ReqOpt::OPTIONAL) + .as_string()); + } + /* Get is_set attributes */ tile_annotation.set_global_port_is_set( tile_global_port_id, diff --git a/libs/libarchopenfpga/src/tile_annotation.cpp b/libs/libarchopenfpga/src/tile_annotation.cpp index cf8712ab8..7cf41f02e 100644 --- a/libs/libarchopenfpga/src/tile_annotation.cpp +++ b/libs/libarchopenfpga/src/tile_annotation.cpp @@ -71,6 +71,12 @@ size_t TileAnnotation::global_port_default_value( return global_port_default_values_[global_port_id]; } +std::string TileAnnotation::global_port_clock_arch_tree_name( + const TileGlobalPortId& global_port_id) const { + VTR_ASSERT(valid_global_port_id(global_port_id)); + return global_port_clock_arch_tree_names_[global_port_id]; +} + /************************************************************************ * Public Mutators ***********************************************************************/ @@ -91,6 +97,7 @@ TileGlobalPortId TileAnnotation::create_global_port( global_port_tile_ports_.emplace_back(); global_port_tile_coordinates_.emplace_back(); global_port_is_clock_.push_back(false); + global_port_clock_arch_tree_names_.emplace_back(); global_port_is_set_.push_back(false); global_port_is_reset_.push_back(false); global_port_default_values_.push_back(0); @@ -116,6 +123,12 @@ void TileAnnotation::set_global_port_is_clock( global_port_is_clock_[global_port_id] = is_clock; } +void TileAnnotation::set_global_port_clock_arch_tree_name( + const TileGlobalPortId& global_port_id, const std::string& clock_tree_name) { + VTR_ASSERT(valid_global_port_id(global_port_id)); + global_port_clock_arch_tree_names_[global_port_id] = clock_tree_name; +} + void TileAnnotation::set_global_port_is_set( const TileGlobalPortId& global_port_id, const bool& is_set) { VTR_ASSERT(valid_global_port_id(global_port_id)); diff --git a/libs/libarchopenfpga/src/tile_annotation.h b/libs/libarchopenfpga/src/tile_annotation.h index bf699be53..ddf951109 100644 --- a/libs/libarchopenfpga/src/tile_annotation.h +++ b/libs/libarchopenfpga/src/tile_annotation.h @@ -51,6 +51,8 @@ class TileAnnotation { bool global_port_is_clock(const TileGlobalPortId& global_port_id) const; bool global_port_is_set(const TileGlobalPortId& global_port_id) const; bool global_port_is_reset(const TileGlobalPortId& global_port_id) const; + std::string global_port_clock_arch_tree_name( + const TileGlobalPortId& global_port_id) const; size_t global_port_default_value( const TileGlobalPortId& global_port_id) const; @@ -66,6 +68,8 @@ class TileAnnotation { const vtr::Point& tile_coord); void set_global_port_is_clock(const TileGlobalPortId& global_port_id, const bool& is_clock); + void set_global_port_clock_arch_tree_name( + const TileGlobalPortId& global_port_id, const std::string& clock_tree_name); void set_global_port_is_set(const TileGlobalPortId& global_port_id, const bool& is_set); void set_global_port_is_reset(const TileGlobalPortId& global_port_id, @@ -91,6 +95,7 @@ class TileAnnotation { global_port_tile_coordinates_; vtr::vector> global_port_tile_ports_; vtr::vector global_port_is_clock_; + vtr::vector global_port_clock_arch_tree_names_; vtr::vector global_port_is_reset_; vtr::vector global_port_is_set_; vtr::vector global_port_default_values_; diff --git a/libs/libarchopenfpga/src/write_xml_tile_annotation.cpp b/libs/libarchopenfpga/src/write_xml_tile_annotation.cpp index f0d42b54d..af6bab25a 100644 --- a/libs/libarchopenfpga/src/write_xml_tile_annotation.cpp +++ b/libs/libarchopenfpga/src/write_xml_tile_annotation.cpp @@ -36,6 +36,14 @@ static void write_xml_tile_annotation_global_port( write_xml_attribute(fp, "is_clock", tile_annotation.global_port_is_clock(global_port_id)); + if (tile_annotation.global_port_is_clock(global_port_id) && + !tile_annotation.global_port_clock_arch_tree_name(global_port_id) + .empty()) { + write_xml_attribute( + fp, "clock_arch_tree_name", + tile_annotation.global_port_clock_arch_tree_name(global_port_id).c_str()); + } + write_xml_attribute(fp, "is_set", tile_annotation.global_port_is_set(global_port_id)); From 099d9f32f42316ca97f01d340ae852acbc90cb45 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 1 Mar 2023 16:08:15 -0800 Subject: [PATCH 058/166] [core] dev --- .../src/base/clock_network.cpp | 8 + .../fabric/build_top_module_connection.cpp | 302 +++++++++++------- 2 files changed, 188 insertions(+), 122 deletions(-) diff --git a/libs/libclkarchopenfpga/src/base/clock_network.cpp b/libs/libclkarchopenfpga/src/base/clock_network.cpp index a8a065ffe..73a53d343 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.cpp +++ b/libs/libclkarchopenfpga/src/base/clock_network.cpp @@ -331,6 +331,14 @@ std::vector ClockNetwork::tree_flatten_taps( return flatten_taps; } +ClockTreeId ClockNetwork::find_tree(const std::string& name) const { + auto result = tree_name2id_map_.find(name); + if (result == tree_name2id_map_.end()) { + return ClockTreeId::INVALID(); + } + return result->second; +} + ClockSpineId ClockNetwork::find_spine(const std::string& name) const { auto result = spine_name2id_map_.find(name); if (result == spine_name2id_map_.end()) { diff --git a/openfpga/src/fabric/build_top_module_connection.cpp b/openfpga/src/fabric/build_top_module_connection.cpp index 01c3a5a01..b6ba80f2a 100644 --- a/openfpga/src/fabric/build_top_module_connection.cpp +++ b/openfpga/src/fabric/build_top_module_connection.cpp @@ -974,6 +974,175 @@ static int build_top_module_global_net_for_given_grid_module( return CMD_EXEC_SUCCESS; } +/******************************************************************** + * Add nets between a global port and its sinks at each grid modules + *******************************************************************/ +static +int build_top_module_global_net_from_grid_modules( + ModuleManager& module_manager, const ModuleId& top_module, const ModulePortId& top_module_port, + const TileAnnotation& tile_annotation, const TileGlobalPortId& tile_global_port, + const VprDeviceAnnotation& vpr_device_annotation, const DeviceGrid& grids, + const vtr::Matrix& grid_instance_ids) { + int status = CMD_EXEC_SUCCESS; + for (size_t tile_info_id = 0; + tile_info_id < + tile_annotation.global_port_tile_names(tile_global_port).size(); + ++tile_info_id) { + std::string tile_name = + tile_annotation.global_port_tile_names(tile_global_port)[tile_info_id]; + BasicPort tile_port = + tile_annotation.global_port_tile_ports(tile_global_port)[tile_info_id]; + /* Find the coordinates for the wanted tiles */ + vtr::Point start_coord(1, 1); + vtr::Point end_coord(grids.width() - 1, grids.height() - 1); + vtr::Point range = tile_annotation.global_port_tile_coordinates( + tile_global_port)[tile_info_id]; + bool out_of_range = false; + + /* -1 means all the x should be considered */ + if (size_t(-1) != range.x()) { + if ((range.x() < start_coord.x()) || (range.x() > end_coord.x())) { + out_of_range = true; + } else { + /* Set the range */ + start_coord.set_x(range.x()); + end_coord.set_x(range.x()); + } + } + + /* -1 means all the y should be considered */ + if (size_t(-1) != range.y()) { + if ((range.y() < start_coord.y()) || (range.y() > end_coord.y())) { + out_of_range = true; + } else { + /* Set the range */ + start_coord.set_y(range.y()); + end_coord.set_y(range.y()); + } + } + + /* Error out immediately if the coordinate is not valid! */ + if (true == out_of_range) { + VTR_LOG_ERROR( + "Coordinate (%lu, %lu) in tile annotation for tile '%s' is out of " + "range (%lu:%lu, %lu:%lu)!", + range.x(), range.y(), tile_name.c_str(), start_coord.x(), + end_coord.x(), start_coord.y(), end_coord.y()); + return CMD_EXEC_FATAL_ERROR; + } + + /* Spot the port from child modules from core grids */ + for (size_t ix = start_coord.x(); ix < end_coord.x(); ++ix) { + for (size_t iy = start_coord.y(); iy < end_coord.y(); ++iy) { + /* Bypass EMPTY tiles */ + if (true == is_empty_type(grids[ix][iy].type)) { + continue; + } + /* Skip width or height > 1 tiles (mostly heterogeneous blocks) */ + if ((0 < grids[ix][iy].width_offset) || + (0 < grids[ix][iy].height_offset)) { + continue; + } + + /* Bypass the tiles whose names do not match */ + if (std::string(grids[ix][iy].type->name) != tile_name) { + continue; + } + + /* Create nets and finish connection build-up */ + status = build_top_module_global_net_for_given_grid_module( + module_manager, top_module, top_module_port, tile_annotation, + tile_global_port, tile_port, vpr_device_annotation, grids, + vtr::Point(ix, iy), NUM_SIDES, grid_instance_ids); + if (CMD_EXEC_FATAL_ERROR == status) { + return status; + } + } + } + + /* Walk through all the grids on the perimeter, which are I/O grids */ + for (const e_side& io_side : FPGA_SIDES_CLOCKWISE) { + for (const vtr::Point& io_coordinate : + io_coordinates[io_side]) { + /* Bypass EMPTY grid */ + if (true == + is_empty_type(grids[io_coordinate.x()][io_coordinate.y()].type)) { + continue; + } + + /* Skip width or height > 1 tiles (mostly heterogeneous blocks) */ + if ((0 < grids[io_coordinate.x()][io_coordinate.y()].width_offset) || + (0 < grids[io_coordinate.x()][io_coordinate.y()].height_offset)) { + continue; + } + + /* Bypass the tiles whose names do not match */ + if (std::string( + grids[io_coordinate.x()][io_coordinate.y()].type->name) != + tile_name) { + continue; + } + + /* Check if the coordinate satisfy the tile coordinate defintion + * - Bypass if the x is a specific number (!= -1), and io_coordinate + * is different + * - Bypass if the y is a specific number (!= -1), and io_coordinate + * is different + */ + if ((size_t(-1) != range.x()) && (range.x() != io_coordinate.x())) { + continue; + } + if ((size_t(-1) != range.y()) && (range.y() != io_coordinate.y())) { + continue; + } + + /* Create nets and finish connection build-up */ + status = build_top_module_global_net_for_given_grid_module( + module_manager, top_module, top_module_port, tile_annotation, + tile_global_port, tile_port, vpr_device_annotation, grids, + io_coordinate, io_side, grid_instance_ids); + if (CMD_EXEC_FATAL_ERROR == status) { + return status; + } + } + } + } + + return status; +} + +/******************************************************************** + * Add nets between a global port and its sinks at an entry point of clock tree + *******************************************************************/ +int build_top_module_global_net_from_clock_arch_tree( + ModuleManager& module_manager, const ModuleId& top_module, const ModulePortId& top_module_port, + const ClockNetwork& clk_ntwk, const std::string& clk_tree_name, const RRClockSpatialLookup& rr_clock_lookup) { + int status = CMD_EXEC_SUCCESS; + + /* Ensure the clock arch tree name is valid */ + ClockTreeId clk_tree = clk_ntwk.find_tree(clk_tree_name); + if (!clk_ntwk.valid_tree_id(clk_tree)) { + VTR_LOG("Fail to find a matched clock tree '%s' in the clock architecture definition", clk_tree_name.c_str()); + return CMD_EXEC_FATAL_ERROR; + } + + /* Ensure the clock tree width matches the global port size */ + if (clk_ntwk.tree_width(clk_tree) != module_manager.module_port(top_module, top_module_port).get_width()) { + VTR_LOG("Clock tree '%s' does not have the same width '%lu' as the port '%'s of FPGA top module", clk_tree_name.c_str(), clk_ntwk.tree_width(clk_tree), module_manager.module_port(top_module, top_module_port).get_name().c_str()); + return CMD_EXEC_FATAL_ERROR; + } + + for (ClockTreePinId pin : clk_ntwk.pins(clk_tree)) { + /* TODO: Find the routing resource node of the entry point */ + + /* TODO: Get the connection block module and instance at the entry point */ + + /* TODO: Add the module net */ + } + + return status; +} + /******************************************************************** * Add global ports from grid ports that are defined as global in tile *annotation @@ -1025,128 +1194,17 @@ int add_top_module_global_ports_from_grid_modules( top_module, tile_annotation.global_port_name(tile_global_port)); VTR_ASSERT(ModulePortId::INVALID() != top_module_port); - for (size_t tile_info_id = 0; - tile_info_id < - tile_annotation.global_port_tile_names(tile_global_port).size(); - ++tile_info_id) { - std::string tile_name = - tile_annotation.global_port_tile_names(tile_global_port)[tile_info_id]; - BasicPort tile_port = - tile_annotation.global_port_tile_ports(tile_global_port)[tile_info_id]; - /* Find the coordinates for the wanted tiles */ - vtr::Point start_coord(1, 1); - vtr::Point end_coord(grids.width() - 1, grids.height() - 1); - vtr::Point range = tile_annotation.global_port_tile_coordinates( - tile_global_port)[tile_info_id]; - bool out_of_range = false; - - /* -1 means all the x should be considered */ - if (size_t(-1) != range.x()) { - if ((range.x() < start_coord.x()) || (range.x() > end_coord.x())) { - out_of_range = true; - } else { - /* Set the range */ - start_coord.set_x(range.x()); - end_coord.set_x(range.x()); - } - } - - /* -1 means all the y should be considered */ - if (size_t(-1) != range.y()) { - if ((range.y() < start_coord.y()) || (range.y() > end_coord.y())) { - out_of_range = true; - } else { - /* Set the range */ - start_coord.set_y(range.y()); - end_coord.set_y(range.y()); - } - } - - /* Error out immediately if the coordinate is not valid! */ - if (true == out_of_range) { - VTR_LOG_ERROR( - "Coordinate (%lu, %lu) in tile annotation for tile '%s' is out of " - "range (%lu:%lu, %lu:%lu)!", - range.x(), range.y(), tile_name.c_str(), start_coord.x(), - end_coord.x(), start_coord.y(), end_coord.y()); - return CMD_EXEC_FATAL_ERROR; - } - - /* Spot the port from child modules from core grids */ - for (size_t ix = start_coord.x(); ix < end_coord.x(); ++ix) { - for (size_t iy = start_coord.y(); iy < end_coord.y(); ++iy) { - /* Bypass EMPTY tiles */ - if (true == is_empty_type(grids[ix][iy].type)) { - continue; - } - /* Skip width or height > 1 tiles (mostly heterogeneous blocks) */ - if ((0 < grids[ix][iy].width_offset) || - (0 < grids[ix][iy].height_offset)) { - continue; - } - - /* Bypass the tiles whose names do not match */ - if (std::string(grids[ix][iy].type->name) != tile_name) { - continue; - } - - /* Create nets and finish connection build-up */ - status = build_top_module_global_net_for_given_grid_module( - module_manager, top_module, top_module_port, tile_annotation, - tile_global_port, tile_port, vpr_device_annotation, grids, - vtr::Point(ix, iy), NUM_SIDES, grid_instance_ids); - if (CMD_EXEC_FATAL_ERROR == status) { - return status; - } - } - } - - /* Walk through all the grids on the perimeter, which are I/O grids */ - for (const e_side& io_side : FPGA_SIDES_CLOCKWISE) { - for (const vtr::Point& io_coordinate : - io_coordinates[io_side]) { - /* Bypass EMPTY grid */ - if (true == - is_empty_type(grids[io_coordinate.x()][io_coordinate.y()].type)) { - continue; - } - - /* Skip width or height > 1 tiles (mostly heterogeneous blocks) */ - if ((0 < grids[io_coordinate.x()][io_coordinate.y()].width_offset) || - (0 < grids[io_coordinate.x()][io_coordinate.y()].height_offset)) { - continue; - } - - /* Bypass the tiles whose names do not match */ - if (std::string( - grids[io_coordinate.x()][io_coordinate.y()].type->name) != - tile_name) { - continue; - } - - /* Check if the coordinate satisfy the tile coordinate defintion - * - Bypass if the x is a specific number (!= -1), and io_coordinate - * is different - * - Bypass if the y is a specific number (!= -1), and io_coordinate - * is different - */ - if ((size_t(-1) != range.x()) && (range.x() != io_coordinate.x())) { - continue; - } - if ((size_t(-1) != range.y()) && (range.y() != io_coordinate.y())) { - continue; - } - - /* Create nets and finish connection build-up */ - status = build_top_module_global_net_for_given_grid_module( - module_manager, top_module, top_module_port, tile_annotation, - tile_global_port, tile_port, vpr_device_annotation, grids, - io_coordinate, io_side, grid_instance_ids); - if (CMD_EXEC_FATAL_ERROR == status) { - return status; - } - } - } + /* There are two cases when building the nets: + * - If the net will go through a dedicated clock tree network, the net will drive an input of a routing block + * - If the net will be directly wired to tiles, the net will drive an input of a tile + */ + if (!tile_annotation.global_port_clock_arch_tree_name(tile_global_port).empty()) { + status = build_top_module_global_net_from_clock_arch_tree(module_manager, top_module, top_module_port); + } else { + status = build_top_module_global_net_from_grid_modules(module_manager, top_module, top_module_port, tile_annotation, tile_global_port, vpr_device_annotation, grids, grid_instance_ids); + } + if (status == CMD_EXEC_FATAL_ERROR) { + return status; } } From 974263f0fa70cbc3d3c6866c7c251d79efa9c28e Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 1 Mar 2023 23:27:29 -0800 Subject: [PATCH 059/166] [core] dev --- openfpga/src/fabric/build_top_module_connection.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/openfpga/src/fabric/build_top_module_connection.cpp b/openfpga/src/fabric/build_top_module_connection.cpp index b6ba80f2a..f54253988 100644 --- a/openfpga/src/fabric/build_top_module_connection.cpp +++ b/openfpga/src/fabric/build_top_module_connection.cpp @@ -1116,6 +1116,7 @@ int build_top_module_global_net_from_grid_modules( *******************************************************************/ int build_top_module_global_net_from_clock_arch_tree( ModuleManager& module_manager, const ModuleId& top_module, const ModulePortId& top_module_port, + const std::map>& cb_instance_ids, const ClockNetwork& clk_ntwk, const std::string& clk_tree_name, const RRClockSpatialLookup& rr_clock_lookup) { int status = CMD_EXEC_SUCCESS; @@ -1133,11 +1134,13 @@ int build_top_module_global_net_from_clock_arch_tree( } for (ClockTreePinId pin : clk_ntwk.pins(clk_tree)) { - /* TODO: Find the routing resource node of the entry point */ + for (ClockSpineId spine : clk_ntwk.tree_top_spines(clk_tree)) { + /* TODO: Find the routing resource node of the entry point, the rr_clock_lookup needs an API to find the ptc of a node */ - /* TODO: Get the connection block module and instance at the entry point */ + /* TODO: Get the connection block module and instance at the entry point */ - /* TODO: Add the module net */ + /* TODO: Add the module net */ + } } return status; From 46510388beef927d2789e00ebde60f07aa4c1138 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 2 Mar 2023 12:33:26 -0800 Subject: [PATCH 060/166] [core] now fabric generator can wire clock ports to routing blocks --- .../src/base/clock_network.cpp | 6 + .../src/base/clock_network.h | 4 + openfpga/src/annotation/device_rr_gsb.cpp | 20 ++++ openfpga/src/annotation/device_rr_gsb.h | 3 + openfpga/src/fabric/build_device_module.cpp | 1 + openfpga/src/fabric/build_top_module.cpp | 6 +- openfpga/src/fabric/build_top_module.h | 5 +- .../fabric/build_top_module_connection.cpp | 111 +++++++++++++----- .../src/fabric/build_top_module_connection.h | 7 +- 9 files changed, 131 insertions(+), 32 deletions(-) diff --git a/libs/libclkarchopenfpga/src/base/clock_network.cpp b/libs/libclkarchopenfpga/src/base/clock_network.cpp index 73a53d343..7f8e83908 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.cpp +++ b/libs/libclkarchopenfpga/src/base/clock_network.cpp @@ -187,6 +187,12 @@ size_t ClockNetwork::tree_depth(const ClockTreeId& tree_id) const { return tree_depths_[tree_id] + 1; } +std::vector ClockNetwork::tree_top_spines( + const ClockTreeId& tree_id) const { + VTR_ASSERT(valid_tree_id(tree_id)); + return tree_top_spines_[tree_id]; +} + std::vector ClockNetwork::spines( const ClockTreeId& tree_id) const { std::vector ret; diff --git a/libs/libclkarchopenfpga/src/base/clock_network.h b/libs/libclkarchopenfpga/src/base/clock_network.h index 14ab3fab4..e77e2b56f 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.h +++ b/libs/libclkarchopenfpga/src/base/clock_network.h @@ -78,6 +78,7 @@ class ClockNetwork { std::string tree_name(const ClockTreeId& tree_id) const; size_t tree_width(const ClockTreeId& tree_id) const; size_t tree_depth(const ClockTreeId& tree_id) const; + std::vector tree_top_spines(const ClockTreeId& tree_id) const; std::string spine_name(const ClockSpineId& spine_id) const; vtr::Point spine_start_point(const ClockSpineId& spine_id) const; vtr::Point spine_end_point(const ClockSpineId& spine_id) const; @@ -123,6 +124,9 @@ class ClockNetwork { /* Find a spine with a given name, if not found, return an valid id, otherwise * return an invalid one */ ClockSpineId find_spine(const std::string& name) const; + /* Find a tree with a given name, if not found, return an valid id, otherwise + * return an invalid one */ + ClockTreeId find_tree(const std::string& name) const; /* Check if there are clock tree */ bool empty() const; bool is_valid() const; diff --git a/openfpga/src/annotation/device_rr_gsb.cpp b/openfpga/src/annotation/device_rr_gsb.cpp index 341cd8993..9811bdcab 100644 --- a/openfpga/src/annotation/device_rr_gsb.cpp +++ b/openfpga/src/annotation/device_rr_gsb.cpp @@ -43,6 +43,26 @@ const RRGSB& DeviceRRGSB::get_gsb(const size_t& x, const size_t& y) const { return get_gsb(coordinate); } +/* Get a rr switch block in the array with a coordinate */ +const RRGSB& DeviceRRGSB::get_gsb_by_cb_coordinate( + const t_rr_type& cb_type, const vtr::Point& coordinate) const { + vtr::Point gsb_coord = coordinate; + /* TODO move the coordinate conversion to RRGSB */ + switch (cb_type) { + case CHANX: + break; + case CHANY: + gsb_coord.set_y(gsb_coord.y() - 1); + break; + default: + VTR_LOG("Invalid type of connection block!\n"); + exit(1); + } + VTR_ASSERT(validate_coordinate(gsb_coord)); + + return rr_gsb_[gsb_coord.x()][gsb_coord.y()]; +} + /* get the number of unique mirrors of switch blocks */ size_t DeviceRRGSB::get_num_cb_unique_module(const t_rr_type& cb_type) const { VTR_ASSERT(validate_cb_type(cb_type)); diff --git a/openfpga/src/annotation/device_rr_gsb.h b/openfpga/src/annotation/device_rr_gsb.h index 0856486d2..5873bb192 100644 --- a/openfpga/src/annotation/device_rr_gsb.h +++ b/openfpga/src/annotation/device_rr_gsb.h @@ -38,6 +38,9 @@ class DeviceRRGSB { const; /* Get a rr switch block in the array with a coordinate */ const RRGSB& get_gsb(const size_t& x, const size_t& y) const; /* Get a rr switch block in the array with a coordinate */ + /* Get a gsb using its connection block coordinate */ + const RRGSB& get_gsb_by_cb_coordinate( + const t_rr_type& cb_type, const vtr::Point& coordinate) const; size_t get_num_gsb_unique_module() const; /* get the number of unique mirrors of GSB */ size_t get_num_sb_unique_module() diff --git a/openfpga/src/fabric/build_device_module.cpp b/openfpga/src/fabric/build_device_module.cpp index bcfbfdf45..97ba9e219 100644 --- a/openfpga/src/fabric/build_device_module.cpp +++ b/openfpga/src/fabric/build_device_module.cpp @@ -101,6 +101,7 @@ int build_device_module_graph( /* Build FPGA fabric top-level module */ status = build_top_module( module_manager, decoder_lib, blwl_sr_banks, openfpga_ctx.arch().circuit_lib, + openfpga_ctx.clock_arch(), openfpga_ctx.clock_rr_lookup(), openfpga_ctx.vpr_device_annotation(), vpr_device_ctx.grid, openfpga_ctx.arch().tile_annotations, vpr_device_ctx.rr_graph, openfpga_ctx.device_rr_gsb(), openfpga_ctx.tile_direct(), diff --git a/openfpga/src/fabric/build_top_module.cpp b/openfpga/src/fabric/build_top_module.cpp index d20e3d355..7d5b168ce 100644 --- a/openfpga/src/fabric/build_top_module.cpp +++ b/openfpga/src/fabric/build_top_module.cpp @@ -431,7 +431,8 @@ static void add_top_module_io_children( int build_top_module( ModuleManager& module_manager, DecoderLibrary& decoder_lib, MemoryBankShiftRegisterBanks& blwl_sr_banks, - const CircuitLibrary& circuit_lib, + const CircuitLibrary& circuit_lib, const ClockNetwork& clk_ntwk, + const RRClockSpatialLookup& rr_clock_lookup, const VprDeviceAnnotation& vpr_device_annotation, const DeviceGrid& grids, const TileAnnotation& tile_annotation, const RRGraphView& rr_graph, const DeviceRRGSB& device_rr_gsb, const TileDirect& tile_direct, @@ -494,7 +495,8 @@ int build_top_module( * annotation */ status = add_top_module_global_ports_from_grid_modules( module_manager, top_module, tile_annotation, vpr_device_annotation, grids, - grid_instance_ids); + rr_graph, device_rr_gsb, cb_instance_ids, grid_instance_ids, clk_ntwk, + rr_clock_lookup); if (CMD_EXEC_FATAL_ERROR == status) { return status; } diff --git a/openfpga/src/fabric/build_top_module.h b/openfpga/src/fabric/build_top_module.h index 613f88990..9a4fb8fe0 100644 --- a/openfpga/src/fabric/build_top_module.h +++ b/openfpga/src/fabric/build_top_module.h @@ -9,6 +9,7 @@ #include "arch_direct.h" #include "circuit_library.h" +#include "clock_network.h" #include "config_protocol.h" #include "decoder_library.h" #include "device_grid.h" @@ -16,6 +17,7 @@ #include "fabric_key.h" #include "memory_bank_shift_register_banks.h" #include "module_manager.h" +#include "rr_clock_spatial_lookup.h" #include "rr_graph_view.h" #include "tile_annotation.h" #include "tile_direct.h" @@ -32,7 +34,8 @@ namespace openfpga { int build_top_module( ModuleManager& module_manager, DecoderLibrary& decoder_lib, MemoryBankShiftRegisterBanks& blwl_sr_banks, - const CircuitLibrary& circuit_lib, + const CircuitLibrary& circuit_lib, const ClockNetwork& clk_ntwk, + const RRClockSpatialLookup& rr_clock_lookup, const VprDeviceAnnotation& vpr_device_annotation, const DeviceGrid& grids, const TileAnnotation& tile_annotation, const RRGraphView& rr_graph, const DeviceRRGSB& device_rr_gsb, const TileDirect& tile_direct, diff --git a/openfpga/src/fabric/build_top_module_connection.cpp b/openfpga/src/fabric/build_top_module_connection.cpp index f54253988..18b4f2ee9 100644 --- a/openfpga/src/fabric/build_top_module_connection.cpp +++ b/openfpga/src/fabric/build_top_module_connection.cpp @@ -977,13 +977,17 @@ static int build_top_module_global_net_for_given_grid_module( /******************************************************************** * Add nets between a global port and its sinks at each grid modules *******************************************************************/ -static -int build_top_module_global_net_from_grid_modules( - ModuleManager& module_manager, const ModuleId& top_module, const ModulePortId& top_module_port, - const TileAnnotation& tile_annotation, const TileGlobalPortId& tile_global_port, +static int build_top_module_global_net_from_grid_modules( + ModuleManager& module_manager, const ModuleId& top_module, + const ModulePortId& top_module_port, const TileAnnotation& tile_annotation, + const TileGlobalPortId& tile_global_port, const VprDeviceAnnotation& vpr_device_annotation, const DeviceGrid& grids, const vtr::Matrix& grid_instance_ids) { int status = CMD_EXEC_SUCCESS; + + std::map>> io_coordinates = + generate_perimeter_grid_coordinates(grids); + for (size_t tile_info_id = 0; tile_info_id < tile_annotation.global_port_tile_names(tile_global_port).size(); @@ -1026,8 +1030,8 @@ int build_top_module_global_net_from_grid_modules( VTR_LOG_ERROR( "Coordinate (%lu, %lu) in tile annotation for tile '%s' is out of " "range (%lu:%lu, %lu:%lu)!", - range.x(), range.y(), tile_name.c_str(), start_coord.x(), - end_coord.x(), start_coord.y(), end_coord.y()); + range.x(), range.y(), tile_name.c_str(), start_coord.x(), end_coord.x(), + start_coord.y(), end_coord.y()); return CMD_EXEC_FATAL_ERROR; } @@ -1062,8 +1066,7 @@ int build_top_module_global_net_from_grid_modules( /* Walk through all the grids on the perimeter, which are I/O grids */ for (const e_side& io_side : FPGA_SIDES_CLOCKWISE) { - for (const vtr::Point& io_coordinate : - io_coordinates[io_side]) { + for (const vtr::Point& io_coordinate : io_coordinates[io_side]) { /* Bypass EMPTY grid */ if (true == is_empty_type(grids[io_coordinate.x()][io_coordinate.y()].type)) { @@ -1114,32 +1117,75 @@ int build_top_module_global_net_from_grid_modules( /******************************************************************** * Add nets between a global port and its sinks at an entry point of clock tree *******************************************************************/ -int build_top_module_global_net_from_clock_arch_tree( - ModuleManager& module_manager, const ModuleId& top_module, const ModulePortId& top_module_port, +static int build_top_module_global_net_from_clock_arch_tree( + ModuleManager& module_manager, const ModuleId& top_module, + const ModulePortId& top_module_port, const RRGraphView& rr_graph, + const DeviceRRGSB& device_rr_gsb, const std::map>& cb_instance_ids, - const ClockNetwork& clk_ntwk, const std::string& clk_tree_name, const RRClockSpatialLookup& rr_clock_lookup) { + const ClockNetwork& clk_ntwk, const std::string& clk_tree_name, + const RRClockSpatialLookup& rr_clock_lookup) { int status = CMD_EXEC_SUCCESS; /* Ensure the clock arch tree name is valid */ ClockTreeId clk_tree = clk_ntwk.find_tree(clk_tree_name); if (!clk_ntwk.valid_tree_id(clk_tree)) { - VTR_LOG("Fail to find a matched clock tree '%s' in the clock architecture definition", clk_tree_name.c_str()); + VTR_LOG( + "Fail to find a matched clock tree '%s' in the clock architecture " + "definition", + clk_tree_name.c_str()); return CMD_EXEC_FATAL_ERROR; } /* Ensure the clock tree width matches the global port size */ - if (clk_ntwk.tree_width(clk_tree) != module_manager.module_port(top_module, top_module_port).get_width()) { - VTR_LOG("Clock tree '%s' does not have the same width '%lu' as the port '%'s of FPGA top module", clk_tree_name.c_str(), clk_ntwk.tree_width(clk_tree), module_manager.module_port(top_module, top_module_port).get_name().c_str()); + if (clk_ntwk.tree_width(clk_tree) != + module_manager.module_port(top_module, top_module_port).get_width()) { + VTR_LOG( + "Clock tree '%s' does not have the same width '%lu' as the port '%'s of " + "FPGA top module", + clk_tree_name.c_str(), clk_ntwk.tree_width(clk_tree), + module_manager.module_port(top_module, top_module_port) + .get_name() + .c_str()); return CMD_EXEC_FATAL_ERROR; } for (ClockTreePinId pin : clk_ntwk.pins(clk_tree)) { + BasicPort src_port = + module_manager.module_port(top_module, top_module_port); + /* Add the module net */ + ModuleNetId net = create_module_source_pin_net( + module_manager, top_module, top_module, 0, top_module_port, + src_port.pins()[size_t(pin)]); + VTR_ASSERT(ModuleNetId::INVALID() != net); + for (ClockSpineId spine : clk_ntwk.tree_top_spines(clk_tree)) { - /* TODO: Find the routing resource node of the entry point, the rr_clock_lookup needs an API to find the ptc of a node */ - - /* TODO: Get the connection block module and instance at the entry point */ - - /* TODO: Add the module net */ + vtr::Point entry_point = clk_ntwk.spine_start_point(spine); + Direction entry_dir = clk_ntwk.spine_direction(spine); + t_rr_type entry_track_type = clk_ntwk.spine_track_type(spine); + /* Find the routing resource node of the entry point */ + RRNodeId entry_rr_node = + rr_clock_lookup.find_node(entry_point.x(), entry_point.y(), clk_tree, + clk_ntwk.spine_level(spine), pin, entry_dir); + + /* Get the connection block module and instance at the entry point */ + const RRGSB& rr_gsb = device_rr_gsb.get_gsb_by_cb_coordinate( + entry_track_type, vtr::Point(entry_point.x(), entry_point.y())); + ModuleId cb_module = + module_manager.find_module(generate_connection_block_module_name( + entry_track_type, + vtr::Point(entry_point.x(), entry_point.y()))); + size_t cb_instance = + cb_instance_ids.at(entry_track_type)[entry_point.x()][entry_point.y()]; + ModulePinInfo des_pin_info = find_connection_block_module_chan_port( + module_manager, cb_module, rr_graph, rr_gsb, entry_track_type, + entry_rr_node); + + /* Configure the net sink */ + BasicPort sink_port = + module_manager.module_port(cb_module, des_pin_info.first); + module_manager.add_module_net_sink(top_module, net, cb_module, + cb_instance, des_pin_info.first, + sink_port.pins()[des_pin_info.second]); } } @@ -1154,7 +1200,10 @@ int add_top_module_global_ports_from_grid_modules( ModuleManager& module_manager, const ModuleId& top_module, const TileAnnotation& tile_annotation, const VprDeviceAnnotation& vpr_device_annotation, const DeviceGrid& grids, - const vtr::Matrix& grid_instance_ids) { + const RRGraphView& rr_graph, const DeviceRRGSB& device_rr_gsb, + const std::map>& cb_instance_ids, + const vtr::Matrix& grid_instance_ids, const ClockNetwork& clk_ntwk, + const RRClockSpatialLookup& rr_clock_lookup) { int status = CMD_EXEC_SUCCESS; /* Add the global ports which are NOT yet added to the top-level module @@ -1187,9 +1236,6 @@ int add_top_module_global_ports_from_grid_modules( } /* Add module nets */ - std::map>> io_coordinates = - generate_perimeter_grid_coordinates(grids); - for (const TileGlobalPortId& tile_global_port : tile_annotation.global_ports()) { /* Must found one valid port! */ @@ -1198,13 +1244,22 @@ int add_top_module_global_ports_from_grid_modules( VTR_ASSERT(ModulePortId::INVALID() != top_module_port); /* There are two cases when building the nets: - * - If the net will go through a dedicated clock tree network, the net will drive an input of a routing block - * - If the net will be directly wired to tiles, the net will drive an input of a tile + * - If the net will go through a dedicated clock tree network, the net will + * drive an input of a routing block + * - If the net will be directly wired to tiles, the net will drive an input + * of a tile */ - if (!tile_annotation.global_port_clock_arch_tree_name(tile_global_port).empty()) { - status = build_top_module_global_net_from_clock_arch_tree(module_manager, top_module, top_module_port); + if (!tile_annotation.global_port_clock_arch_tree_name(tile_global_port) + .empty()) { + status = build_top_module_global_net_from_clock_arch_tree( + module_manager, top_module, top_module_port, rr_graph, device_rr_gsb, + cb_instance_ids, clk_ntwk, + tile_annotation.global_port_clock_arch_tree_name(tile_global_port), + rr_clock_lookup); } else { - status = build_top_module_global_net_from_grid_modules(module_manager, top_module, top_module_port, tile_annotation, tile_global_port, vpr_device_annotation, grids, grid_instance_ids); + status = build_top_module_global_net_from_grid_modules( + module_manager, top_module, top_module_port, tile_annotation, + tile_global_port, vpr_device_annotation, grids, grid_instance_ids); } if (status == CMD_EXEC_FATAL_ERROR) { return status; diff --git a/openfpga/src/fabric/build_top_module_connection.h b/openfpga/src/fabric/build_top_module_connection.h index 3fb1860a1..908e6cfdc 100644 --- a/openfpga/src/fabric/build_top_module_connection.h +++ b/openfpga/src/fabric/build_top_module_connection.h @@ -6,9 +6,11 @@ *******************************************************************/ #include +#include "clock_network.h" #include "device_grid.h" #include "device_rr_gsb.h" #include "module_manager.h" +#include "rr_clock_spatial_lookup.h" #include "rr_graph_view.h" #include "tile_annotation.h" #include "vpr_device_annotation.h" @@ -34,7 +36,10 @@ int add_top_module_global_ports_from_grid_modules( ModuleManager& module_manager, const ModuleId& top_module, const TileAnnotation& tile_annotation, const VprDeviceAnnotation& vpr_device_annotation, const DeviceGrid& grids, - const vtr::Matrix& grid_instance_ids); + const RRGraphView& rr_graph, const DeviceRRGSB& device_rr_gsb, + const std::map>& cb_instance_ids, + const vtr::Matrix& grid_instance_ids, const ClockNetwork& clk_ntwk, + const RRClockSpatialLookup& rr_clock_lookup); } /* end namespace openfpga */ From b9f7c72a96292a25ab97f2b43271050aeb62adbc Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 2 Mar 2023 18:16:59 -0800 Subject: [PATCH 061/166] [test] fixed some bugs in arch --- .../clock_network/homo_1clock_2layer/config/task.conf | 4 ++-- openfpga_flow/vpr_arch/k4_N4_tileable_Ntwk1clk2lvl_40nm.xml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/openfpga_flow/tasks/basic_tests/clock_network/homo_1clock_2layer/config/task.conf b/openfpga_flow/tasks/basic_tests/clock_network/homo_1clock_2layer/config/task.conf index 3b0bc7f72..d88210133 100644 --- a/openfpga_flow/tasks/basic_tests/clock_network/homo_1clock_2layer/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/clock_network/homo_1clock_2layer/config/task.conf @@ -18,10 +18,10 @@ fpga_flow=yosys_vpr [OpenFPGA_SHELL] openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/example_clkntwk_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_Ntwk1clk2lvl_cc_openfpga.xml -openfpga_clock_arch_file=${TASK_DIR}/config/clk_arch_1clk_2layer.xml +openfpga_clock_arch_file=${PATH:TASK_DIR}/config/clk_arch_1clk_2layer.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml openfpga_vpr_device_layout=2x2 -openfpga_vpr_route_chan_width=20 +openfpga_vpr_route_chan_width=24 [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_Ntwk1clk2lvl_40nm.xml diff --git a/openfpga_flow/vpr_arch/k4_N4_tileable_Ntwk1clk2lvl_40nm.xml b/openfpga_flow/vpr_arch/k4_N4_tileable_Ntwk1clk2lvl_40nm.xml index 5d5371df5..24f0704d0 100644 --- a/openfpga_flow/vpr_arch/k4_N4_tileable_Ntwk1clk2lvl_40nm.xml +++ b/openfpga_flow/vpr_arch/k4_N4_tileable_Ntwk1clk2lvl_40nm.xml @@ -170,8 +170,8 @@ reasonable. Using a tile length of 90 nm, corresponding to the length of a Stratix IV tile if it were square. --> - 1 1 1 1 1 - 1 1 1 1 + 1 1 + 1 From 02b50e346438e766cb53b52f8ef02e67a263b612 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 2 Mar 2023 21:33:32 -0800 Subject: [PATCH 062/166] [lib] now clock spine requires explicit definition of track type and direction when coordinate is vague --- .../src/base/clock_network.cpp | 61 ++++++++++++++++++- .../src/base/clock_network.h | 12 ++++ .../src/io/clock_network_xml_constants.h | 2 + .../src/io/read_xml_clock_network.cpp | 53 ++++++++++++++++ .../src/io/write_xml_clock_network.cpp | 4 ++ .../config/clk_arch_1clk_2layer.xml | 8 +-- 6 files changed, 133 insertions(+), 7 deletions(-) diff --git a/libs/libclkarchopenfpga/src/base/clock_network.cpp b/libs/libclkarchopenfpga/src/base/clock_network.cpp index 7f8e83908..cfdfed633 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.cpp +++ b/libs/libclkarchopenfpga/src/base/clock_network.cpp @@ -82,7 +82,10 @@ std::vector ClockNetwork::pins( ***********************************************************************/ t_rr_type ClockNetwork::spine_track_type(const ClockSpineId& spine_id) const { VTR_ASSERT(valid_spine_start_end_points(spine_id)); - if (spine_start_point(spine_id).y() == spine_end_point(spine_id).y()) { + if ((spine_start_point(spine_id).x() == spine_end_point(spine_id).x()) + && (spine_start_point(spine_id).y() == spine_end_point(spine_id).y())) { + return spine_track_types_[spine_id]; + } else if (spine_start_point(spine_id).y() == spine_end_point(spine_id).y()) { return CHANX; } return CHANY; @@ -91,12 +94,16 @@ t_rr_type ClockNetwork::spine_track_type(const ClockSpineId& spine_id) const { Direction ClockNetwork::spine_direction(const ClockSpineId& spine_id) const { VTR_ASSERT(valid_spine_start_end_points(spine_id)); if (spine_track_type(spine_id) == CHANX) { - if (spine_start_point(spine_id).x() < spine_end_point(spine_id).x()) { + if (spine_start_point(spine_id).x() == spine_end_point(spine_id).x()) { + return spine_directions_[spine_id]; + } else if (spine_start_point(spine_id).x() < spine_end_point(spine_id).x()) { return Direction::INC; } } else { VTR_ASSERT(spine_track_type(spine_id) == CHANY); - if (spine_start_point(spine_id).y() < spine_end_point(spine_id).y()) { + if (spine_start_point(spine_id).y() == spine_end_point(spine_id).y()) { + return spine_directions_[spine_id]; + } else if (spine_start_point(spine_id).y() < spine_end_point(spine_id).y()) { return Direction::INC; } } @@ -370,6 +377,8 @@ void ClockNetwork::reserve_spines(const size_t& num_spines) { spine_levels_.reserve(num_spines); spine_start_points_.reserve(num_spines); spine_end_points_.reserve(num_spines); + spine_directions_.reserve(num_spines); + spine_track_types_.reserve(num_spines); spine_switch_points_.reserve(num_spines); spine_switch_coords_.reserve(num_spines); spine_parents_.reserve(num_spines); @@ -444,6 +453,8 @@ ClockSpineId ClockNetwork::create_spine(const std::string& name) { spine_levels_.emplace_back(0); spine_start_points_.emplace_back(); spine_end_points_.emplace_back(); + spine_directions_.emplace_back(Direction::NUM_DIRECTIONS); + spine_track_types_.emplace_back(NUM_RR_TYPES); spine_switch_points_.emplace_back(); spine_switch_coords_.emplace_back(); spine_parents_.emplace_back(); @@ -484,6 +495,19 @@ void ClockNetwork::set_spine_end_point(const ClockSpineId& spine_id, spine_end_points_[spine_id] = coord; } +void ClockNetwork::set_spine_direction(const ClockSpineId& spine_id, + const Direction& dir) { + VTR_ASSERT(valid_spine_id(spine_id)); + spine_directions_[spine_id] = dir; +} + +void ClockNetwork::set_spine_track_type(const ClockSpineId& spine_id, + const t_rr_type& type) { + VTR_ASSERT(valid_spine_id(spine_id)); + spine_track_types_[spine_id] = type; +} + + void ClockNetwork::add_spine_switch_point(const ClockSpineId& spine_id, const ClockSpineId& drive_spine_id, const vtr::Point& coord) { @@ -542,6 +566,19 @@ bool ClockNetwork::validate_tree() const { spine_end_point(spine_id).y()); return false; } + /* Ensure valid track types */ + if (spine_track_type(spine_id) != spine_track_types_[spine_id]) { + VTR_LOG_ERROR( + "Spine '%s' has a mismatch between inferred track type '%s' against user-defined track type '%s'\n", + spine_name(spine_id).c_str(), rr_node_typename[spine_track_type(spine_id)], rr_node_typename[spine_track_types_[spine_id]]); + return false; + } + if (spine_direction(spine_id) != spine_directions_[spine_id]) { + VTR_LOG_ERROR( + "Spine '%s' has a mismatch between inferred direction '%s' against user-defined direction '%s'\n", + spine_name(spine_id).c_str(), DIRECTION_STRING[size_t(spine_direction(spine_id))], DIRECTION_STRING[size_t(spine_directions_[spine_id])]); + return false; + } /* parent spine and child spine should be in different track type */ ClockSpineId parent_spine = spine_parents_[spine_id]; if (valid_spine_id(parent_spine)) { @@ -577,6 +614,9 @@ bool ClockNetwork::link_tree(const ClockTreeId& tree_id) { if (!update_tree_depth(tree_id)) { return false; } + if (!update_spine_attributes(tree_id)) { + return false; + } return true; } @@ -618,6 +658,16 @@ bool ClockNetwork::update_tree_depth(const ClockTreeId& tree_id) { return true; } +bool ClockNetwork::update_spine_attributes(const ClockTreeId& tree_id) { + size_t depth = 0; + for (ClockSpineId spine_id : spines(tree_id)) { + spine_track_types_[spine_id] = spine_track_type(spine_id); + spine_directions_[spine_id] = spine_direction(spine_id); + } + return true; +} + + /************************************************************************ * Internal invalidators/validators ***********************************************************************/ @@ -665,4 +715,9 @@ bool ClockNetwork::valid_spine_start_end_points( return true; } +bool ClockNetwork::is_vague_coordinate(const ClockSpineId& spine_id) const { + return ((spine_start_point(spine_id).x() == spine_end_point(spine_id).x()) && + (spine_start_point(spine_id).y() == spine_end_point(spine_id).y())); +} + } // End of namespace openfpga diff --git a/libs/libclkarchopenfpga/src/base/clock_network.h b/libs/libclkarchopenfpga/src/base/clock_network.h index e77e2b56f..34ee8bf3c 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.h +++ b/libs/libclkarchopenfpga/src/base/clock_network.h @@ -163,6 +163,10 @@ class ClockNetwork { const vtr::Point& coord); void set_spine_end_point(const ClockSpineId& spine_id, const vtr::Point& coord); + void set_spine_direction(const ClockSpineId& spine_id, + const Direction& dir); + void set_spine_track_type(const ClockSpineId& spine_id, + const t_rr_type& type); void add_spine_switch_point(const ClockSpineId& spine_id, const ClockSpineId& drive_spine_id, const vtr::Point& coord); @@ -191,6 +195,10 @@ class ClockNetwork { * X-direction spine or a Y-direction spine. Diagonal spine is not supported! */ bool valid_spine_start_end_points(const ClockSpineId& spine_id) const; + /* Definition of a vague coordinate is that start_x == end_x && start_y == end_y + * In such situation, we need specific track type and direction to be provided by user + */ + bool is_vague_coordinate(const ClockSpineId& spine_id) const; /* Validate the internal data. Required to ensure clean data before usage. If * validation is successful, is_valid() will return true */ bool validate() const; @@ -209,6 +217,8 @@ class ClockNetwork { bool rec_update_spine_level(const ClockSpineId& spine_id); /* Require sort_tree_spines() to called before! */ bool update_tree_depth(const ClockTreeId& tree_id); + /* Infer track type and directions for each spine by their coordinates */ + bool update_spine_attributes(const ClockTreeId& tree_id); private: /* Internal data */ /* Basic information of each tree */ @@ -225,6 +235,8 @@ class ClockNetwork { vtr::vector spine_levels_; vtr::vector> spine_start_points_; vtr::vector> spine_end_points_; + vtr::vector spine_directions_; + vtr::vector spine_track_types_; vtr::vector> spine_switch_points_; vtr::vector>> spine_switch_coords_; vtr::vector spine_parents_; diff --git a/libs/libclkarchopenfpga/src/io/clock_network_xml_constants.h b/libs/libclkarchopenfpga/src/io/clock_network_xml_constants.h index 569fdde7a..db7216f2d 100644 --- a/libs/libclkarchopenfpga/src/io/clock_network_xml_constants.h +++ b/libs/libclkarchopenfpga/src/io/clock_network_xml_constants.h @@ -17,6 +17,8 @@ constexpr const char* XML_CLOCK_SPINE_ATTRIBUTE_START_X = "start_x"; constexpr const char* XML_CLOCK_SPINE_ATTRIBUTE_START_Y = "start_y"; constexpr const char* XML_CLOCK_SPINE_ATTRIBUTE_END_X = "end_x"; constexpr const char* XML_CLOCK_SPINE_ATTRIBUTE_END_Y = "end_y"; +constexpr const char* XML_CLOCK_SPINE_ATTRIBUTE_TYPE = "type"; +constexpr const char* XML_CLOCK_SPINE_ATTRIBUTE_DIRECTION = "direction"; constexpr const char* XML_CLOCK_SPINE_SWITCH_POINT_NODE_NAME = "switch_point"; constexpr const char* XML_CLOCK_SPINE_SWITCH_POINT_ATTRIBUTE_TAP = "tap"; constexpr const char* XML_CLOCK_SPINE_SWITCH_POINT_ATTRIBUTE_X = "x"; diff --git a/libs/libclkarchopenfpga/src/io/read_xml_clock_network.cpp b/libs/libclkarchopenfpga/src/io/read_xml_clock_network.cpp index 5db46c6dd..f5fd17abe 100644 --- a/libs/libclkarchopenfpga/src/io/read_xml_clock_network.cpp +++ b/libs/libclkarchopenfpga/src/io/read_xml_clock_network.cpp @@ -94,6 +94,37 @@ static void read_xml_clock_spine_switch_point( vtr::Point(tap_x, tap_y)); } +/******************************************************************** + * Convert string to the enumerate of model type + *******************************************************************/ +static t_rr_type string_to_track_type( + const std::string& type_string) { + for (size_t itype = 0; itype < NUM_RR_TYPES; ++itype) { + if (std::string(rr_node_typename[itype]) == type_string) { + return static_cast(itype); + } + } + + /* Reach here, we have an invalid value, error out */ + return NUM_RR_TYPES; +} + +/******************************************************************** + * Convert string to the enumerate of model type + *******************************************************************/ +static Direction string_to_direction( + const std::string& type_string) { + for (size_t itype = 0; itype < size_t(Direction::NUM_DIRECTIONS); ++itype) { + if (std::string(DIRECTION_STRING[itype]) == type_string) { + return static_cast(itype); + } + } + + /* Reach here, we have an invalid value, error out */ + return Direction::NUM_DIRECTIONS; +} + + /******************************************************************** * Parse XML codes of a to an object of ClockNetwork *******************************************************************/ @@ -139,6 +170,28 @@ static void read_xml_clock_spine(pugi::xml_node& xml_spine, .as_int(); clk_ntwk.set_spine_end_point(spine_id, vtr::Point(end_x, end_y)); + if (clk_ntwk.is_vague_coordinate(spine_id)) { + std::string track_type_name = + get_attribute(xml_spine, XML_CLOCK_SPINE_ATTRIBUTE_TYPE, loc_data) + .as_string(); + t_rr_type track_type = string_to_track_type(track_type_name); + if (CHANX != track_type && CHANY != track_type) { + archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_spine), + "Invalid track type! Expect '%s' or '%s'!\n", rr_node_typename[CHANX], rr_node_typename[CHANY]); + } + clk_ntwk.set_spine_track_type(spine_id, track_type); + + std::string direction_name = + get_attribute(xml_spine, XML_CLOCK_SPINE_ATTRIBUTE_DIRECTION, loc_data) + .as_string(); + Direction direction_type = string_to_direction(direction_name); + if (Direction::INC != direction_type && Direction::DEC != direction_type) { + archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_spine), + "Invalid direction type! Expect '%s' or '%s'!\n", DIRECTION_STRING[size_t(Direction::INC)], DIRECTION_STRING[size_t(Direction::DEC)]); + } + clk_ntwk.set_spine_direction(spine_id, direction_type); + } + for (pugi::xml_node xml_switch_point : xml_spine.children()) { /* Error out if the XML child has an invalid name! */ if (xml_switch_point.name() == diff --git a/libs/libclkarchopenfpga/src/io/write_xml_clock_network.cpp b/libs/libclkarchopenfpga/src/io/write_xml_clock_network.cpp index 6430bf43c..4fb6991cf 100644 --- a/libs/libclkarchopenfpga/src/io/write_xml_clock_network.cpp +++ b/libs/libclkarchopenfpga/src/io/write_xml_clock_network.cpp @@ -79,6 +79,10 @@ static int write_xml_clock_spine(std::fstream& fp, const ClockNetwork& clk_ntwk, vtr::Point end_coord = clk_ntwk.spine_end_point(spine_id); write_xml_attribute(fp, XML_CLOCK_SPINE_ATTRIBUTE_END_X, end_coord.x()); write_xml_attribute(fp, XML_CLOCK_SPINE_ATTRIBUTE_END_Y, end_coord.y()); + if (clk_ntwk.is_vague_coordinate(spine_id)) { + write_xml_attribute(fp, XML_CLOCK_SPINE_ATTRIBUTE_TYPE, rr_node_typename[clk_ntwk.spine_track_type(spine_id)]); + write_xml_attribute(fp, XML_CLOCK_SPINE_ATTRIBUTE_DIRECTION, DIRECTION_STRING[size_t(clk_ntwk.spine_direction(spine_id))]); + } fp << ">" << "\n"; diff --git a/openfpga_flow/tasks/basic_tests/clock_network/homo_1clock_2layer/config/clk_arch_1clk_2layer.xml b/openfpga_flow/tasks/basic_tests/clock_network/homo_1clock_2layer/config/clk_arch_1clk_2layer.xml index 330da638d..06f233957 100644 --- a/openfpga_flow/tasks/basic_tests/clock_network/homo_1clock_2layer/config/clk_arch_1clk_2layer.xml +++ b/openfpga_flow/tasks/basic_tests/clock_network/homo_1clock_2layer/config/clk_arch_1clk_2layer.xml @@ -6,10 +6,10 @@ - - - - + + + + From 98d8c75d86970837c679aacfd277a8096be197bb Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 2 Mar 2023 21:36:08 -0800 Subject: [PATCH 063/166] [code] format --- .../src/base/clock_network.cpp | 28 +++++++++++-------- .../src/base/clock_network.h | 8 +++--- .../src/io/read_xml_clock_network.cpp | 16 +++++------ .../src/io/write_xml_clock_network.cpp | 7 +++-- 4 files changed, 34 insertions(+), 25 deletions(-) diff --git a/libs/libclkarchopenfpga/src/base/clock_network.cpp b/libs/libclkarchopenfpga/src/base/clock_network.cpp index cfdfed633..a1dcca476 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.cpp +++ b/libs/libclkarchopenfpga/src/base/clock_network.cpp @@ -82,8 +82,8 @@ std::vector ClockNetwork::pins( ***********************************************************************/ t_rr_type ClockNetwork::spine_track_type(const ClockSpineId& spine_id) const { VTR_ASSERT(valid_spine_start_end_points(spine_id)); - if ((spine_start_point(spine_id).x() == spine_end_point(spine_id).x()) - && (spine_start_point(spine_id).y() == spine_end_point(spine_id).y())) { + if ((spine_start_point(spine_id).x() == spine_end_point(spine_id).x()) && + (spine_start_point(spine_id).y() == spine_end_point(spine_id).y())) { return spine_track_types_[spine_id]; } else if (spine_start_point(spine_id).y() == spine_end_point(spine_id).y()) { return CHANX; @@ -96,14 +96,16 @@ Direction ClockNetwork::spine_direction(const ClockSpineId& spine_id) const { if (spine_track_type(spine_id) == CHANX) { if (spine_start_point(spine_id).x() == spine_end_point(spine_id).x()) { return spine_directions_[spine_id]; - } else if (spine_start_point(spine_id).x() < spine_end_point(spine_id).x()) { + } else if (spine_start_point(spine_id).x() < + spine_end_point(spine_id).x()) { return Direction::INC; } } else { VTR_ASSERT(spine_track_type(spine_id) == CHANY); if (spine_start_point(spine_id).y() == spine_end_point(spine_id).y()) { return spine_directions_[spine_id]; - } else if (spine_start_point(spine_id).y() < spine_end_point(spine_id).y()) { + } else if (spine_start_point(spine_id).y() < + spine_end_point(spine_id).y()) { return Direction::INC; } } @@ -507,7 +509,6 @@ void ClockNetwork::set_spine_track_type(const ClockSpineId& spine_id, spine_track_types_[spine_id] = type; } - void ClockNetwork::add_spine_switch_point(const ClockSpineId& spine_id, const ClockSpineId& drive_spine_id, const vtr::Point& coord) { @@ -569,14 +570,20 @@ bool ClockNetwork::validate_tree() const { /* Ensure valid track types */ if (spine_track_type(spine_id) != spine_track_types_[spine_id]) { VTR_LOG_ERROR( - "Spine '%s' has a mismatch between inferred track type '%s' against user-defined track type '%s'\n", - spine_name(spine_id).c_str(), rr_node_typename[spine_track_type(spine_id)], rr_node_typename[spine_track_types_[spine_id]]); + "Spine '%s' has a mismatch between inferred track type '%s' against " + "user-defined track type '%s'\n", + spine_name(spine_id).c_str(), + rr_node_typename[spine_track_type(spine_id)], + rr_node_typename[spine_track_types_[spine_id]]); return false; } if (spine_direction(spine_id) != spine_directions_[spine_id]) { VTR_LOG_ERROR( - "Spine '%s' has a mismatch between inferred direction '%s' against user-defined direction '%s'\n", - spine_name(spine_id).c_str(), DIRECTION_STRING[size_t(spine_direction(spine_id))], DIRECTION_STRING[size_t(spine_directions_[spine_id])]); + "Spine '%s' has a mismatch between inferred direction '%s' against " + "user-defined direction '%s'\n", + spine_name(spine_id).c_str(), + DIRECTION_STRING[size_t(spine_direction(spine_id))], + DIRECTION_STRING[size_t(spine_directions_[spine_id])]); return false; } /* parent spine and child spine should be in different track type */ @@ -667,7 +674,6 @@ bool ClockNetwork::update_spine_attributes(const ClockTreeId& tree_id) { return true; } - /************************************************************************ * Internal invalidators/validators ***********************************************************************/ @@ -717,7 +723,7 @@ bool ClockNetwork::valid_spine_start_end_points( bool ClockNetwork::is_vague_coordinate(const ClockSpineId& spine_id) const { return ((spine_start_point(spine_id).x() == spine_end_point(spine_id).x()) && - (spine_start_point(spine_id).y() == spine_end_point(spine_id).y())); + (spine_start_point(spine_id).y() == spine_end_point(spine_id).y())); } } // End of namespace openfpga diff --git a/libs/libclkarchopenfpga/src/base/clock_network.h b/libs/libclkarchopenfpga/src/base/clock_network.h index 34ee8bf3c..e729dbef2 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.h +++ b/libs/libclkarchopenfpga/src/base/clock_network.h @@ -163,8 +163,7 @@ class ClockNetwork { const vtr::Point& coord); void set_spine_end_point(const ClockSpineId& spine_id, const vtr::Point& coord); - void set_spine_direction(const ClockSpineId& spine_id, - const Direction& dir); + void set_spine_direction(const ClockSpineId& spine_id, const Direction& dir); void set_spine_track_type(const ClockSpineId& spine_id, const t_rr_type& type); void add_spine_switch_point(const ClockSpineId& spine_id, @@ -195,8 +194,9 @@ class ClockNetwork { * X-direction spine or a Y-direction spine. Diagonal spine is not supported! */ bool valid_spine_start_end_points(const ClockSpineId& spine_id) const; - /* Definition of a vague coordinate is that start_x == end_x && start_y == end_y - * In such situation, we need specific track type and direction to be provided by user + /* Definition of a vague coordinate is that start_x == end_x && start_y == + * end_y In such situation, we need specific track type and direction to be + * provided by user */ bool is_vague_coordinate(const ClockSpineId& spine_id) const; /* Validate the internal data. Required to ensure clean data before usage. If diff --git a/libs/libclkarchopenfpga/src/io/read_xml_clock_network.cpp b/libs/libclkarchopenfpga/src/io/read_xml_clock_network.cpp index f5fd17abe..ed083f483 100644 --- a/libs/libclkarchopenfpga/src/io/read_xml_clock_network.cpp +++ b/libs/libclkarchopenfpga/src/io/read_xml_clock_network.cpp @@ -97,8 +97,7 @@ static void read_xml_clock_spine_switch_point( /******************************************************************** * Convert string to the enumerate of model type *******************************************************************/ -static t_rr_type string_to_track_type( - const std::string& type_string) { +static t_rr_type string_to_track_type(const std::string& type_string) { for (size_t itype = 0; itype < NUM_RR_TYPES; ++itype) { if (std::string(rr_node_typename[itype]) == type_string) { return static_cast(itype); @@ -112,8 +111,7 @@ static t_rr_type string_to_track_type( /******************************************************************** * Convert string to the enumerate of model type *******************************************************************/ -static Direction string_to_direction( - const std::string& type_string) { +static Direction string_to_direction(const std::string& type_string) { for (size_t itype = 0; itype < size_t(Direction::NUM_DIRECTIONS); ++itype) { if (std::string(DIRECTION_STRING[itype]) == type_string) { return static_cast(itype); @@ -124,7 +122,6 @@ static Direction string_to_direction( return Direction::NUM_DIRECTIONS; } - /******************************************************************** * Parse XML codes of a to an object of ClockNetwork *******************************************************************/ @@ -177,17 +174,20 @@ static void read_xml_clock_spine(pugi::xml_node& xml_spine, t_rr_type track_type = string_to_track_type(track_type_name); if (CHANX != track_type && CHANY != track_type) { archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_spine), - "Invalid track type! Expect '%s' or '%s'!\n", rr_node_typename[CHANX], rr_node_typename[CHANY]); + "Invalid track type! Expect '%s' or '%s'!\n", + rr_node_typename[CHANX], rr_node_typename[CHANY]); } clk_ntwk.set_spine_track_type(spine_id, track_type); - + std::string direction_name = get_attribute(xml_spine, XML_CLOCK_SPINE_ATTRIBUTE_DIRECTION, loc_data) .as_string(); Direction direction_type = string_to_direction(direction_name); if (Direction::INC != direction_type && Direction::DEC != direction_type) { archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_spine), - "Invalid direction type! Expect '%s' or '%s'!\n", DIRECTION_STRING[size_t(Direction::INC)], DIRECTION_STRING[size_t(Direction::DEC)]); + "Invalid direction type! Expect '%s' or '%s'!\n", + DIRECTION_STRING[size_t(Direction::INC)], + DIRECTION_STRING[size_t(Direction::DEC)]); } clk_ntwk.set_spine_direction(spine_id, direction_type); } diff --git a/libs/libclkarchopenfpga/src/io/write_xml_clock_network.cpp b/libs/libclkarchopenfpga/src/io/write_xml_clock_network.cpp index 4fb6991cf..720335aa4 100644 --- a/libs/libclkarchopenfpga/src/io/write_xml_clock_network.cpp +++ b/libs/libclkarchopenfpga/src/io/write_xml_clock_network.cpp @@ -80,8 +80,11 @@ static int write_xml_clock_spine(std::fstream& fp, const ClockNetwork& clk_ntwk, write_xml_attribute(fp, XML_CLOCK_SPINE_ATTRIBUTE_END_X, end_coord.x()); write_xml_attribute(fp, XML_CLOCK_SPINE_ATTRIBUTE_END_Y, end_coord.y()); if (clk_ntwk.is_vague_coordinate(spine_id)) { - write_xml_attribute(fp, XML_CLOCK_SPINE_ATTRIBUTE_TYPE, rr_node_typename[clk_ntwk.spine_track_type(spine_id)]); - write_xml_attribute(fp, XML_CLOCK_SPINE_ATTRIBUTE_DIRECTION, DIRECTION_STRING[size_t(clk_ntwk.spine_direction(spine_id))]); + write_xml_attribute(fp, XML_CLOCK_SPINE_ATTRIBUTE_TYPE, + rr_node_typename[clk_ntwk.spine_track_type(spine_id)]); + write_xml_attribute( + fp, XML_CLOCK_SPINE_ATTRIBUTE_DIRECTION, + DIRECTION_STRING[size_t(clk_ntwk.spine_direction(spine_id))]); } fp << ">" From fd1c4039d3cfab305d3e51d96fa38f4a1161da88 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 2 Mar 2023 21:37:24 -0800 Subject: [PATCH 064/166] [test] typo --- .../homo_1clock_2layer/config/clk_arch_1clk_2layer.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/openfpga_flow/tasks/basic_tests/clock_network/homo_1clock_2layer/config/clk_arch_1clk_2layer.xml b/openfpga_flow/tasks/basic_tests/clock_network/homo_1clock_2layer/config/clk_arch_1clk_2layer.xml index 06f233957..0570406fd 100644 --- a/openfpga_flow/tasks/basic_tests/clock_network/homo_1clock_2layer/config/clk_arch_1clk_2layer.xml +++ b/openfpga_flow/tasks/basic_tests/clock_network/homo_1clock_2layer/config/clk_arch_1clk_2layer.xml @@ -6,10 +6,10 @@ - - - - + + + + From c4ad21451c84c2701d91df894997b8a7cb21137d Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 2 Mar 2023 21:54:48 -0800 Subject: [PATCH 065/166] [core] debugging --- openfpga/src/annotation/append_clock_rr_graph.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openfpga/src/annotation/append_clock_rr_graph.cpp b/openfpga/src/annotation/append_clock_rr_graph.cpp index 78ff37802..508574c18 100644 --- a/openfpga/src/annotation/append_clock_rr_graph.cpp +++ b/openfpga/src/annotation/append_clock_rr_graph.cpp @@ -565,7 +565,7 @@ int append_clock_rr_graph(DeviceContext& vpr_device_ctx, "Appending programmable clock network to routing resource graph"); /* Skip if there is no clock tree */ - if (clk_ntwk.num_trees()) { + if (clk_ntwk.num_trees() == 0) { VTR_LOG( "Skip due to 0 clock trees.\nDouble check your clock architecture " "definition if this is unexpected\n"); From d3de6e3bcdd055105c590ad61741ba917f8ffb2b Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 3 Mar 2023 15:31:26 -0800 Subject: [PATCH 066/166] [lib] update vtr --- vtr-verilog-to-routing | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vtr-verilog-to-routing b/vtr-verilog-to-routing index 9e53e9a0a..52bd89f36 160000 --- a/vtr-verilog-to-routing +++ b/vtr-verilog-to-routing @@ -1 +1 @@ -Subproject commit 9e53e9a0a7c18ba9a16ea08678da726b98c669d4 +Subproject commit 52bd89f36ad5445aea3835c312ef56c2c18b2f9d From 304925b5cabe2c7d6391517efaec1943999f8992 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 3 Mar 2023 16:24:48 -0800 Subject: [PATCH 067/166] [script] update cmakelist to sync up latest compilation options in VTR --- CMakeLists.txt | 3 +-- Makefile | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 35a2296c7..885442707 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -80,10 +80,9 @@ set(ODIN_WARN OFF CACHE BOOL "Enable building odin with extra warning flags in V set(ODIN_COVERAGE OFF CACHE BOOL "Enable building odin with coverage flags in Verilog-to-Routing") set(ODIN_TIDY OFF CACHE BOOL "Enable building odin with clang tidy in Verilog-to-Routing") set(ODIN_SANITIZE OFF CACHE BOOL "Enable building odin with sanitize flags in Verilog-to-Routing") -set(WITH_YOSYS OFF CACHE BOOL "Enable building Yosys in Verilog-to-Routing") -set(ODIN_YOSYS OFF CACHE BOOL "Enable building odin with yosys in Verilog-to-Routing") set(YOSYS_SV_UHDM_PLUGIN OFF CACHE BOOL "Enable building and installing Yosys SystemVerilog and UHDM plugins in Verilog-to-Routing") set(VTR_ENABLE_VERSION ${OPENFPGA_WITH_VERSION} CACHE BOOL "Enable version always-up-to-date when building codebase. Disable only when you do not care an accurate version number") +set(WITH_PARMYS OFF CACHE BOOL "Enable Yosys as elaborator and parmys-plugin as partial mapper") # TODO: OpenFPGA and VPR has different requirements on no-warning build, e.g., on OS and compiler versions #set(VTR_ENABLE_STRICT_COMPILE ${OPENFPGA_ENABLE_STRICT_COMPILE} CACHE BOOL "Specifies whether compiler warnings should be treated as errors (e.g. -Werror)") diff --git a/Makefile b/Makefile index 9774e7863..db960eb5b 100644 --- a/Makefile +++ b/Makefile @@ -58,7 +58,7 @@ help: checkout: # Update all the submodules git submodule init - git submodule update --init --recursive + git submodule update --init --depth 1 prebuild: # Run cmake to generate Makefile under the build directory, before compilation From 5a43b451c15ed407ab421197ba34a63fc6ec8352 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 3 Mar 2023 16:56:20 -0800 Subject: [PATCH 068/166] [core] debugging --- openfpga/src/annotation/append_clock_rr_graph.cpp | 4 ++++ vtr-verilog-to-routing | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/openfpga/src/annotation/append_clock_rr_graph.cpp b/openfpga/src/annotation/append_clock_rr_graph.cpp index 508574c18..e8099c227 100644 --- a/openfpga/src/annotation/append_clock_rr_graph.cpp +++ b/openfpga/src/annotation/append_clock_rr_graph.cpp @@ -584,6 +584,7 @@ int append_clock_rr_graph(DeviceContext& vpr_device_ctx, size_t orig_num_nodes = vpr_device_ctx.rr_graph.num_nodes(); size_t num_clock_nodes = estimate_clock_rr_graph_num_nodes( vpr_device_ctx.grid, vpr_device_ctx.arch->through_channel, clk_ntwk); + vpr_device_ctx.rr_graph_builder.unlock_storage(); vpr_device_ctx.rr_graph_builder.reserve_nodes(num_clock_nodes + orig_num_nodes); @@ -603,6 +604,9 @@ int append_clock_rr_graph(DeviceContext& vpr_device_ctx, vpr_device_ctx.arch->through_channel, clk_ntwk); /* TODO: Sanity checks */ + vpr_device_ctx.rr_graph_builder.init_fan_in(); + vpr_device_ctx.rr_graph_builder.partition_edges(); + vpr_device_ctx.rr_graph_builder.build_in_edges(); /* Report number of added clock nodes and edges */ VTR_LOGV(verbose, diff --git a/vtr-verilog-to-routing b/vtr-verilog-to-routing index 52bd89f36..5795b7df7 160000 --- a/vtr-verilog-to-routing +++ b/vtr-verilog-to-routing @@ -1 +1 @@ -Subproject commit 52bd89f36ad5445aea3835c312ef56c2c18b2f9d +Subproject commit 5795b7df753903b215c1273cfe910113375f6aa8 From 59af073792f52118212f26460a980ea39cd8104a Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 3 Mar 2023 16:58:32 -0800 Subject: [PATCH 069/166] [ci] remove unnecessary checkout on submodules --- .github/workflows/build.yml | 16 +--------------- .github/workflows/cell_lib_test.yml | 2 -- 2 files changed, 1 insertion(+), 17 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e5223f0fe..18e795654 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -37,9 +37,7 @@ jobs: - name: Checkout OpenFPGA repo uses: actions/checkout@v2 - with: - fetch-depth: 0 - submodules: true + - name: Check for source code changes id: changes run: | @@ -115,8 +113,6 @@ jobs: - name: Checkout OpenFPGA repo uses: actions/checkout@v2 - with: - submodules: true - name: Install dependencies run: sudo bash ./.github/workflows/install_dependencies_build.sh @@ -201,8 +197,6 @@ jobs: - name: Checkout OpenFPGA repo uses: actions/checkout@v2 - with: - submodules: true - name: Install dependencies run: sudo bash ./.github/workflows/install_dependencies_build.sh @@ -244,8 +238,6 @@ jobs: - name: Checkout OpenFPGA repo uses: actions/checkout@v2 - with: - submodules: true - name: Install dependencies run: sudo bash ./.github/workflows/install_dependencies_build_ubuntu22p04.sh @@ -291,8 +283,6 @@ jobs: - name: Checkout OpenFPGA repo uses: actions/checkout@v2 - with: - submodules: true - name: Install dependencies run: | @@ -344,8 +334,6 @@ jobs: - name: Checkout OpenFPGA repo uses: actions/checkout@v2 - with: - submodules: true - name: Install dependencies run: | @@ -494,8 +482,6 @@ jobs: - name: Checkout OpenFPGA repo uses: actions/checkout@v2 - with: - submodules: true - name: ${{matrix.config.name}}_GCC-8_(Ubuntu 20.04) shell: bash run: | diff --git a/.github/workflows/cell_lib_test.yml b/.github/workflows/cell_lib_test.yml index 5016297d5..9825fddfc 100644 --- a/.github/workflows/cell_lib_test.yml +++ b/.github/workflows/cell_lib_test.yml @@ -22,8 +22,6 @@ jobs: - name: Checkout OpenFPGA repo uses: actions/checkout@v2 - with: - submodules: true - name: Install Dependencies run: | From 29ee6e7136afff75f54cf20f122621cda9138650 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 3 Mar 2023 17:33:53 -0800 Subject: [PATCH 070/166] [core] debugging --- .../src/base/clock_network.cpp | 19 +++++----- .../src/annotation/append_clock_rr_graph.cpp | 35 +++++++++++++++---- 2 files changed, 36 insertions(+), 18 deletions(-) diff --git a/libs/libclkarchopenfpga/src/base/clock_network.cpp b/libs/libclkarchopenfpga/src/base/clock_network.cpp index a1dcca476..aa7a09956 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.cpp +++ b/libs/libclkarchopenfpga/src/base/clock_network.cpp @@ -49,19 +49,19 @@ std::vector ClockNetwork::pins( * the same routing tracks. Therefore, we only ensure that routing tracks in * their demanding direction (INC and DEC) are satisfied */ - bool dir_flags = false; + bool dir_flag = 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) { + if (!dir_flag && 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; + dir_flag = true; } } } @@ -129,10 +129,8 @@ size_t ClockNetwork::num_tracks(const ClockTreeId& tree_id, continue; } if (spine_track_type(curr_spine) == track_type) { - if (!dir_flags[spine_direction(curr_spine)]) { - num_tracks += tree_width(spine_parent_trees_[curr_spine]); - dir_flags[spine_direction(curr_spine)] = true; - } + /* TODO: Deposit routing tracks in both INC and DEC direction, currently this is limited by the connection block build-up algorithm in fabric generator */ + return 2 * tree_width(spine_parent_trees_[curr_spine]); } } return num_tracks; @@ -148,15 +146,14 @@ size_t ClockNetwork::num_tracks(const ClockTreeId& tree_id, * 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) { - num_tracks += tree_width(spine_parent_trees_[curr_spine]); - dir_flags = true; + if (spine_direction(curr_spine) == direction) { + /* TODO: Deposit routing tracks in both INC and DEC direction, currently this is limited by the connection block build-up algorithm in fabric generator */ + return tree_width(spine_parent_trees_[curr_spine]); } } } diff --git a/openfpga/src/annotation/append_clock_rr_graph.cpp b/openfpga/src/annotation/append_clock_rr_graph.cpp index e8099c227..63d3b38c8 100644 --- a/openfpga/src/annotation/append_clock_rr_graph.cpp +++ b/openfpga/src/annotation/append_clock_rr_graph.cpp @@ -99,8 +99,22 @@ 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)) { + /* As we want to keep uni-directional wires, clock routing tracks have to be in pairs. + * Therefore, always add clock routing tracks in pair, even one of them is not required + */ + size_t num_pins = 0; + bool require_complementary_pins = false; for (auto node_dir : {Direction::INC, Direction::DEC}) { - for (auto ipin : clk_ntwk.pins(itree, ilvl, chan_type, node_dir)) { + if (0 == clk_ntwk.pins(itree, ilvl, chan_type, node_dir).size()) { + require_complementary_pins = true; + } + num_pins += clk_ntwk.pins(itree, ilvl, chan_type, node_dir).size(); + } + if (require_complementary_pins) { + num_pins = 2 * num_pins; + } + for (size_t ipin = 0; ipin < num_pins / 2; ++ipin) { + for (auto node_dir : {Direction::INC, Direction::DEC}) { 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); @@ -113,7 +127,7 @@ static void add_rr_graph_block_clock_nodes(RRGraphBuilder& rr_graph_builder, * in VTR */ /* 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); + itree, ilvl, ClockTreePinId(ipin), node_dir); /* Update ptc count and go to next */ curr_node_ptc++; } @@ -587,11 +601,19 @@ int append_clock_rr_graph(DeviceContext& vpr_device_ctx, vpr_device_ctx.rr_graph_builder.unlock_storage(); vpr_device_ctx.rr_graph_builder.reserve_nodes(num_clock_nodes + orig_num_nodes); + VTR_LOGV(verbose, + "Estimate %lu clock nodes (+%.5f%) to be added to routing " + "resource graph.\n", + num_clock_nodes, (float)(num_clock_nodes / orig_num_nodes)); /* 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_LOGV(verbose, + "Added %lu clock nodes to routing " + "resource graph.\n", + vpr_device_ctx.rr_graph.num_nodes() - orig_num_nodes); VTR_ASSERT(num_clock_nodes + orig_num_nodes == vpr_device_ctx.rr_graph.num_nodes()); @@ -609,11 +631,10 @@ int append_clock_rr_graph(DeviceContext& vpr_device_ctx, vpr_device_ctx.rr_graph_builder.build_in_edges(); /* Report number of added clock nodes and edges */ - VTR_LOGV(verbose, - "Appended %lu clock nodes (+%.2f%) and %lu clock edges to routing " - "resource graph.\n", - num_clock_nodes, (float)(num_clock_nodes / orig_num_nodes), - num_clock_edges); + VTR_LOG("Appended %lu clock nodes (+%.2f%) and %lu clock edges to routing " + "resource graph.\n", + num_clock_nodes, (float)(num_clock_nodes / orig_num_nodes), + num_clock_edges); return CMD_EXEC_SUCCESS; } From 4423d917fa8282a19f551dcac130eb9bc1a3b8dc Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 3 Mar 2023 18:00:43 -0800 Subject: [PATCH 071/166] [core] debugging --- .../src/base/rr_clock_spatial_lookup.cpp | 6 ++++ .../src/annotation/append_clock_rr_graph.cpp | 28 ++++++++++++------- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/libs/libclkarchopenfpga/src/base/rr_clock_spatial_lookup.cpp b/libs/libclkarchopenfpga/src/base/rr_clock_spatial_lookup.cpp index adbba8399..ef027a0e7 100644 --- a/libs/libclkarchopenfpga/src/base/rr_clock_spatial_lookup.cpp +++ b/libs/libclkarchopenfpga/src/base/rr_clock_spatial_lookup.cpp @@ -25,29 +25,35 @@ RRNodeId RRClockSpatialLookup::find_node(int x, int y, const ClockTreeId& tree, * - Return an invalid id if any out-of-range is detected */ if (size_t(dir) >= rr_node_indices_.size()) { + VTR_LOG("Direction out of range"); return RRNodeId::INVALID(); } if (size_t(x) >= rr_node_indices_[dir].dim_size(0)) { + VTR_LOG("X out of range"); return RRNodeId::INVALID(); } if (size_t(y) >= rr_node_indices_[dir].dim_size(1)) { + VTR_LOG("Y out of range"); return RRNodeId::INVALID(); } auto result_tree = rr_node_indices_[dir][x][y].find(tree); if (result_tree == rr_node_indices_[dir][x][y].end()) { + VTR_LOG("Tree id out of range"); return RRNodeId::INVALID(); } auto result_lvl = result_tree->second.find(lvl); if (result_lvl == result_tree->second.end()) { + VTR_LOG("Level id out of range"); return RRNodeId::INVALID(); } auto result_pin = result_lvl->second.find(pin); if (result_pin == result_lvl->second.end()) { + VTR_LOG("Pin id out of range"); return RRNodeId::INVALID(); } diff --git a/openfpga/src/annotation/append_clock_rr_graph.cpp b/openfpga/src/annotation/append_clock_rr_graph.cpp index 63d3b38c8..f9d11051d 100644 --- a/openfpga/src/annotation/append_clock_rr_graph.cpp +++ b/openfpga/src/annotation/append_clock_rr_graph.cpp @@ -90,7 +90,8 @@ static void add_rr_graph_block_clock_nodes(RRGraphBuilder& rr_graph_builder, const ClockNetwork& clk_ntwk, const vtr::Point chan_coord, const t_rr_type& chan_type, - const int& cost_index_offset) { + const int& cost_index_offset, + const bool& verbose) { size_t orig_chan_width = rr_graph_view.node_lookup() .find_channel_nodes(chan_coord.x(), chan_coord.y(), chan_type) @@ -128,6 +129,8 @@ static void add_rr_graph_block_clock_nodes(RRGraphBuilder& rr_graph_builder, /* register the node to a dedicated lookup */ clk_rr_lookup.add_node(clk_node, chan_coord.x(), chan_coord.y(), itree, ilvl, ClockTreePinId(ipin), node_dir); + VTR_LOGV(verbose, "Added node '%lu' to clock node lookup (x='%lu' y='%lu' tree='%lu' level='%lu' pin='%lu' direction='%s')\n", + size_t(clk_node), chan_coord.x(), chan_coord.y(), size_t(itree), size_t(ilvl), ipin, DIRECTION_STRING[size_t(node_dir)]); /* Update ptc count and go to next */ curr_node_ptc++; } @@ -145,7 +148,8 @@ static void add_rr_graph_clock_nodes(RRGraphBuilder& rr_graph_builder, const RRGraphView& rr_graph_view, const DeviceGrid& grids, const bool& through_channel, - const ClockNetwork& clk_ntwk) { + const ClockNetwork& clk_ntwk, + const bool& verbose) { /* Add X-direction clock nodes */ for (size_t iy = 0; iy < grids.height() - 1; ++iy) { for (size_t ix = 1; ix < grids.width() - 1; ++ix) { @@ -158,7 +162,7 @@ static void add_rr_graph_clock_nodes(RRGraphBuilder& rr_graph_builder, } add_rr_graph_block_clock_nodes(rr_graph_builder, clk_rr_lookup, rr_graph_view, clk_ntwk, chanx_coord, - CHANX, CHANX_COST_INDEX_START); + CHANX, CHANX_COST_INDEX_START, verbose); } } @@ -174,7 +178,7 @@ static void add_rr_graph_clock_nodes(RRGraphBuilder& rr_graph_builder, } add_rr_graph_block_clock_nodes( rr_graph_builder, clk_rr_lookup, rr_graph_view, clk_ntwk, chany_coord, - CHANY, CHANX_COST_INDEX_START + rr_graph_view.num_rr_segments()); + CHANY, CHANX_COST_INDEX_START + rr_graph_view.num_rr_segments(), verbose); } } } @@ -459,7 +463,8 @@ static void add_rr_graph_block_clock_edges( RRGraphBuilder& rr_graph_builder, size_t& num_edges_to_create, const RRClockSpatialLookup& clk_rr_lookup, const RRGraphView& rr_graph_view, const DeviceGrid& grids, const ClockNetwork& clk_ntwk, - const vtr::Point chan_coord, const t_rr_type& chan_type) { + const vtr::Point chan_coord, const t_rr_type& chan_type, + const bool& verbose) { size_t edge_count = 0; for (auto itree : clk_ntwk.trees()) { for (auto ilvl : clk_ntwk.levels(itree)) { @@ -468,6 +473,8 @@ static void add_rr_graph_block_clock_edges( /* find the driver clock node through lookup */ RRNodeId src_node = clk_rr_lookup.find_node( chan_coord.x(), chan_coord.y(), itree, ilvl, ipin, node_dir); + VTR_LOGV(verbose, "Try to find node '%lu' from clock node lookup (x='%lu' y='%lu' tree='%lu' level='%lu' pin='%lu' direction='%s')\n", + size_t(src_node), chan_coord.x(), chan_coord.y(), size_t(itree), size_t(ilvl), size_t(ipin), DIRECTION_STRING[size_t(node_dir)]); VTR_ASSERT(rr_graph_view.valid_node(src_node)); if (!clk_ntwk.is_last_level(itree, ilvl)) { /* find the fan-out clock node through lookup */ @@ -530,7 +537,8 @@ static void add_rr_graph_clock_edges(RRGraphBuilder& rr_graph_builder, const RRGraphView& rr_graph_view, const DeviceGrid& grids, const bool& through_channel, - const ClockNetwork& clk_ntwk) { + const ClockNetwork& clk_ntwk, + const bool& verbose) { /* Add edges which is driven by X-direction clock routing tracks */ for (size_t iy = 0; iy < grids.height() - 1; ++iy) { for (size_t ix = 1; ix < grids.width() - 1; ++ix) { @@ -543,7 +551,7 @@ static void add_rr_graph_clock_edges(RRGraphBuilder& rr_graph_builder, } add_rr_graph_block_clock_edges(rr_graph_builder, num_edges_to_create, clk_rr_lookup, rr_graph_view, grids, - clk_ntwk, chanx_coord, CHANX); + clk_ntwk, chanx_coord, CHANX, verbose); } } @@ -559,7 +567,7 @@ static void add_rr_graph_clock_edges(RRGraphBuilder& rr_graph_builder, } add_rr_graph_block_clock_edges(rr_graph_builder, num_edges_to_create, clk_rr_lookup, rr_graph_view, grids, - clk_ntwk, chany_coord, CHANY); + clk_ntwk, chany_coord, CHANY, verbose); } } } @@ -609,7 +617,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); + vpr_device_ctx.arch->through_channel, clk_ntwk, verbose); VTR_LOGV(verbose, "Added %lu clock nodes to routing " "resource graph.\n", @@ -623,7 +631,7 @@ int append_clock_rr_graph(DeviceContext& vpr_device_ctx, vpr_device_ctx.rr_graph_builder, num_clock_edges, static_cast(clk_rr_lookup), vpr_device_ctx.rr_graph, vpr_device_ctx.grid, - vpr_device_ctx.arch->through_channel, clk_ntwk); + vpr_device_ctx.arch->through_channel, clk_ntwk, verbose); /* TODO: Sanity checks */ vpr_device_ctx.rr_graph_builder.init_fan_in(); From 81e9187aac894e88e0ca270c59040f3c7be6b0ba Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 3 Mar 2023 22:55:14 -0800 Subject: [PATCH 072/166] [core] debugging --- .../src/base/rr_clock_spatial_lookup.cpp | 25 +++++++++++++------ .../src/base/rr_clock_spatial_lookup.h | 3 +-- .../src/annotation/append_clock_rr_graph.cpp | 7 +++++- 3 files changed, 24 insertions(+), 11 deletions(-) diff --git a/libs/libclkarchopenfpga/src/base/rr_clock_spatial_lookup.cpp b/libs/libclkarchopenfpga/src/base/rr_clock_spatial_lookup.cpp index ef027a0e7..32f403582 100644 --- a/libs/libclkarchopenfpga/src/base/rr_clock_spatial_lookup.cpp +++ b/libs/libclkarchopenfpga/src/base/rr_clock_spatial_lookup.cpp @@ -39,25 +39,22 @@ RRNodeId RRClockSpatialLookup::find_node(int x, int y, const ClockTreeId& tree, return RRNodeId::INVALID(); } - auto result_tree = rr_node_indices_[dir][x][y].find(tree); - if (result_tree == rr_node_indices_[dir][x][y].end()) { + if (size_t(tree) >= rr_node_indices_[dir][x][y].size()) { VTR_LOG("Tree id out of range"); return RRNodeId::INVALID(); } - auto result_lvl = result_tree->second.find(lvl); - if (result_lvl == result_tree->second.end()) { + if (size_t(lvl) == rr_node_indices_[dir][x][y][size_t(tree)].size()) { VTR_LOG("Level id out of range"); return RRNodeId::INVALID(); } - auto result_pin = result_lvl->second.find(pin); - if (result_pin == result_lvl->second.end()) { + if (size_t(pin) == rr_node_indices_[dir][x][y][size_t(tree)][size_t(lvl)].size()) { VTR_LOG("Pin id out of range"); return RRNodeId::INVALID(); } - return result_pin->second; + return rr_node_indices_[dir][x][y][size_t(tree)][size_t(lvl)][size_t(pin)]; } void RRClockSpatialLookup::add_node(RRNodeId node, int x, int y, @@ -70,9 +67,21 @@ void RRClockSpatialLookup::add_node(RRNodeId node, int x, int y, VTR_ASSERT_SAFE(2 == rr_node_indices_[dir].ndims()); resize_nodes(x, y, direction); + + if (size_t(tree) >= rr_node_indices_[dir][x][y].size()) { + rr_node_indices_[dir][x][y].resize(size_t(tree) + 1); + } + + if (size_t(lvl) >= rr_node_indices_[dir][x][y][size_t(tree)].size()) { + rr_node_indices_[dir][x][y][size_t(tree)].resize(size_t(lvl) + 1); + } + + if (size_t(pin) >= rr_node_indices_[dir][x][y][size_t(tree)][size_t(lvl)].size()) { + rr_node_indices_[dir][x][y][size_t(tree)][size_t(lvl)].resize(size_t(pin) + 1); + } /* Resize on demand finished; Register the node */ - rr_node_indices_[dir][x][y][tree][lvl][pin] = node; + rr_node_indices_[dir][x][y][size_t(tree)][size_t(lvl)][size_t(pin)] = node; } void RRClockSpatialLookup::resize_nodes(int x, int y, diff --git a/libs/libclkarchopenfpga/src/base/rr_clock_spatial_lookup.h b/libs/libclkarchopenfpga/src/base/rr_clock_spatial_lookup.h index 4e1ec0f9b..9eb48830a 100644 --- a/libs/libclkarchopenfpga/src/base/rr_clock_spatial_lookup.h +++ b/libs/libclkarchopenfpga/src/base/rr_clock_spatial_lookup.h @@ -99,8 +99,7 @@ class RRClockSpatialLookup { */ std::array< vtr::NdMatrix< - std::map>>, + std::vector>>, 2>, 2> rr_node_indices_; diff --git a/openfpga/src/annotation/append_clock_rr_graph.cpp b/openfpga/src/annotation/append_clock_rr_graph.cpp index f9d11051d..171a24bba 100644 --- a/openfpga/src/annotation/append_clock_rr_graph.cpp +++ b/openfpga/src/annotation/append_clock_rr_graph.cpp @@ -163,9 +163,12 @@ static void add_rr_graph_clock_nodes(RRGraphBuilder& rr_graph_builder, add_rr_graph_block_clock_nodes(rr_graph_builder, clk_rr_lookup, rr_graph_view, clk_ntwk, chanx_coord, CHANX, CHANX_COST_INDEX_START, verbose); + VTR_ASSERT(rr_graph_view.valid_node(clk_rr_lookup.find_node(1, 0, ClockTreeId(0), ClockLevelId(0), ClockTreePinId(0), Direction::INC))); } } + VTR_ASSERT(rr_graph_view.valid_node(clk_rr_lookup.find_node(1, 0, ClockTreeId(0), ClockLevelId(0), ClockTreePinId(0), Direction::INC))); + /* Add Y-direction clock nodes */ for (size_t ix = 0; ix < grids.width() - 1; ++ix) { for (size_t iy = 1; iy < grids.height() - 1; ++iy) { @@ -179,8 +182,10 @@ static void add_rr_graph_clock_nodes(RRGraphBuilder& rr_graph_builder, add_rr_graph_block_clock_nodes( rr_graph_builder, clk_rr_lookup, rr_graph_view, clk_ntwk, chany_coord, CHANY, CHANX_COST_INDEX_START + rr_graph_view.num_rr_segments(), verbose); + VTR_ASSERT(rr_graph_view.valid_node(clk_rr_lookup.find_node(1, 0, ClockTreeId(0), ClockLevelId(0), ClockTreePinId(0), Direction::INC))); } } + VTR_ASSERT(rr_graph_view.valid_node(clk_rr_lookup.find_node(1, 0, ClockTreeId(0), ClockLevelId(0), ClockTreePinId(0), Direction::INC))); } /******************************************************************** @@ -463,7 +468,7 @@ static void add_rr_graph_block_clock_edges( RRGraphBuilder& rr_graph_builder, size_t& num_edges_to_create, const RRClockSpatialLookup& clk_rr_lookup, const RRGraphView& rr_graph_view, const DeviceGrid& grids, const ClockNetwork& clk_ntwk, - const vtr::Point chan_coord, const t_rr_type& chan_type, + const vtr::Point& chan_coord, const t_rr_type& chan_type, const bool& verbose) { size_t edge_count = 0; for (auto itree : clk_ntwk.trees()) { From de1e300ec76f1948b0897191f856820b7e17e58d Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 5 Mar 2023 22:21:55 -0800 Subject: [PATCH 073/166] [core] now resize rr_node for clock graph is working --- .../src/base/clock_network.cpp | 17 ++++++++++++++- .../src/base/clock_network.h | 2 ++ .../src/base/rr_clock_spatial_lookup.cpp | 21 +++++++++++++++++++ .../src/base/rr_clock_spatial_lookup.h | 9 ++++++++ .../src/annotation/append_clock_rr_graph.cpp | 3 +++ 5 files changed, 51 insertions(+), 1 deletion(-) diff --git a/libs/libclkarchopenfpga/src/base/clock_network.cpp b/libs/libclkarchopenfpga/src/base/clock_network.cpp index aa7a09956..08feb206e 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.cpp +++ b/libs/libclkarchopenfpga/src/base/clock_network.cpp @@ -179,6 +179,22 @@ std::string ClockNetwork::tree_name(const ClockTreeId& tree_id) const { return tree_names_[tree_id]; } +size_t ClockNetwork::max_tree_width() const { + size_t max_size = 0; + for (auto itree : trees()) { + max_size = std::max(tree_width(itree), max_size); + } + return max_size; +} + +size_t ClockNetwork::max_tree_depth() const { + size_t max_size = 0; + for (auto itree : trees()) { + max_size = std::max(tree_depth(itree), max_size); + } + return max_size; +} + size_t ClockNetwork::tree_width(const ClockTreeId& tree_id) const { VTR_ASSERT(valid_tree_id(tree_id)); return tree_widths_[tree_id]; @@ -663,7 +679,6 @@ bool ClockNetwork::update_tree_depth(const ClockTreeId& tree_id) { } bool ClockNetwork::update_spine_attributes(const ClockTreeId& tree_id) { - size_t depth = 0; for (ClockSpineId spine_id : spines(tree_id)) { spine_track_types_[spine_id] = spine_track_type(spine_id); spine_directions_[spine_id] = spine_direction(spine_id); diff --git a/libs/libclkarchopenfpga/src/base/clock_network.h b/libs/libclkarchopenfpga/src/base/clock_network.h index e729dbef2..0b9b8a42b 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.h +++ b/libs/libclkarchopenfpga/src/base/clock_network.h @@ -78,6 +78,8 @@ class ClockNetwork { std::string tree_name(const ClockTreeId& tree_id) const; size_t tree_width(const ClockTreeId& tree_id) const; size_t tree_depth(const ClockTreeId& tree_id) const; + size_t max_tree_width() const; + size_t max_tree_depth() const; std::vector tree_top_spines(const ClockTreeId& tree_id) const; std::string spine_name(const ClockSpineId& spine_id) const; vtr::Point spine_start_point(const ClockSpineId& spine_id) const; diff --git a/libs/libclkarchopenfpga/src/base/rr_clock_spatial_lookup.cpp b/libs/libclkarchopenfpga/src/base/rr_clock_spatial_lookup.cpp index 32f403582..f77c37c1c 100644 --- a/libs/libclkarchopenfpga/src/base/rr_clock_spatial_lookup.cpp +++ b/libs/libclkarchopenfpga/src/base/rr_clock_spatial_lookup.cpp @@ -84,6 +84,27 @@ void RRClockSpatialLookup::add_node(RRNodeId node, int x, int y, rr_node_indices_[dir][x][y][size_t(tree)][size_t(lvl)][size_t(pin)] = node; } +void RRClockSpatialLookup::reserve_nodes(int x, int y, + int tree, + int lvl, + int pin) { + for (Direction dir : {Direction::INC, Direction::DEC}) { + resize_nodes(x, y, dir); + for (int ix = 0; ix < x; ++ix) { + for (int iy = 0; iy < y; ++iy) { + rr_node_indices_[size_t(dir)][ix][iy].resize(tree); + for (int itree = 0; itree < tree; ++itree) { + rr_node_indices_[size_t(dir)][ix][iy][itree].resize(lvl); + for (int ilvl = 0; ilvl < lvl; ++ilvl) { + rr_node_indices_[size_t(dir)][ix][iy][itree][ilvl].resize(pin); + } + } + } + } + } +} + + void RRClockSpatialLookup::resize_nodes(int x, int y, const Direction& direction) { /* Expand the fast look-up if the new node is out-of-range diff --git a/libs/libclkarchopenfpga/src/base/rr_clock_spatial_lookup.h b/libs/libclkarchopenfpga/src/base/rr_clock_spatial_lookup.h index 9eb48830a..25487a622 100644 --- a/libs/libclkarchopenfpga/src/base/rr_clock_spatial_lookup.h +++ b/libs/libclkarchopenfpga/src/base/rr_clock_spatial_lookup.h @@ -85,6 +85,15 @@ class RRClockSpatialLookup { const ClockLevelId& clk_lvl, const ClockTreePinId& clk_pin, const Direction& direction); + /** + * @brief Allocate memory for the lookup with maximum sizes on each dimension + * .. note:: Must run before any other API! + */ + void reserve_nodes(int x, int y, + int tree, + int lvl, + int pin); + /** @brief Clear all the data inside */ void clear(); diff --git a/openfpga/src/annotation/append_clock_rr_graph.cpp b/openfpga/src/annotation/append_clock_rr_graph.cpp index 171a24bba..23cc748f9 100644 --- a/openfpga/src/annotation/append_clock_rr_graph.cpp +++ b/openfpga/src/annotation/append_clock_rr_graph.cpp @@ -150,6 +150,9 @@ static void add_rr_graph_clock_nodes(RRGraphBuilder& rr_graph_builder, const bool& through_channel, const ClockNetwork& clk_ntwk, const bool& verbose) { + /* Pre-allocate memory: Must do otherwise data will be messed up! */ + clk_rr_lookup.reserve_nodes(grids.width(), grids.height(), clk_ntwk.num_trees(), clk_ntwk.max_tree_depth(), clk_ntwk.max_tree_width()); + /* Add X-direction clock nodes */ for (size_t iy = 0; iy < grids.height() - 1; ++iy) { for (size_t ix = 1; ix < grids.width() - 1; ++ix) { From 953625b1caeeb86f8c1c2391782ea0016212f7ba Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 5 Mar 2023 22:32:05 -0800 Subject: [PATCH 074/166] [core] format --- .../src/base/clock_network.cpp | 8 +- .../src/base/rr_clock_spatial_lookup.cpp | 16 +-- .../src/base/rr_clock_spatial_lookup.h | 12 +-- .../src/annotation/append_clock_rr_graph.cpp | 99 +++++++++++-------- 4 files changed, 77 insertions(+), 58 deletions(-) diff --git a/libs/libclkarchopenfpga/src/base/clock_network.cpp b/libs/libclkarchopenfpga/src/base/clock_network.cpp index 08feb206e..ee562bfd5 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.cpp +++ b/libs/libclkarchopenfpga/src/base/clock_network.cpp @@ -129,7 +129,9 @@ size_t ClockNetwork::num_tracks(const ClockTreeId& tree_id, continue; } if (spine_track_type(curr_spine) == track_type) { - /* TODO: Deposit routing tracks in both INC and DEC direction, currently this is limited by the connection block build-up algorithm in fabric generator */ + /* TODO: Deposit routing tracks in both INC and DEC direction, currently + * this is limited by the connection block build-up algorithm in fabric + * generator */ return 2 * tree_width(spine_parent_trees_[curr_spine]); } } @@ -152,7 +154,9 @@ size_t ClockNetwork::num_tracks(const ClockTreeId& tree_id, } if (spine_track_type(curr_spine) == track_type) { if (spine_direction(curr_spine) == direction) { - /* TODO: Deposit routing tracks in both INC and DEC direction, currently this is limited by the connection block build-up algorithm in fabric generator */ + /* TODO: Deposit routing tracks in both INC and DEC direction, currently + * this is limited by the connection block build-up algorithm in fabric + * generator */ return tree_width(spine_parent_trees_[curr_spine]); } } diff --git a/libs/libclkarchopenfpga/src/base/rr_clock_spatial_lookup.cpp b/libs/libclkarchopenfpga/src/base/rr_clock_spatial_lookup.cpp index f77c37c1c..f47284281 100644 --- a/libs/libclkarchopenfpga/src/base/rr_clock_spatial_lookup.cpp +++ b/libs/libclkarchopenfpga/src/base/rr_clock_spatial_lookup.cpp @@ -49,7 +49,8 @@ RRNodeId RRClockSpatialLookup::find_node(int x, int y, const ClockTreeId& tree, return RRNodeId::INVALID(); } - if (size_t(pin) == rr_node_indices_[dir][x][y][size_t(tree)][size_t(lvl)].size()) { + if (size_t(pin) == + rr_node_indices_[dir][x][y][size_t(tree)][size_t(lvl)].size()) { VTR_LOG("Pin id out of range"); return RRNodeId::INVALID(); } @@ -67,7 +68,7 @@ void RRClockSpatialLookup::add_node(RRNodeId node, int x, int y, VTR_ASSERT_SAFE(2 == rr_node_indices_[dir].ndims()); resize_nodes(x, y, direction); - + if (size_t(tree) >= rr_node_indices_[dir][x][y].size()) { rr_node_indices_[dir][x][y].resize(size_t(tree) + 1); } @@ -76,17 +77,17 @@ void RRClockSpatialLookup::add_node(RRNodeId node, int x, int y, rr_node_indices_[dir][x][y][size_t(tree)].resize(size_t(lvl) + 1); } - if (size_t(pin) >= rr_node_indices_[dir][x][y][size_t(tree)][size_t(lvl)].size()) { - rr_node_indices_[dir][x][y][size_t(tree)][size_t(lvl)].resize(size_t(pin) + 1); + if (size_t(pin) >= + rr_node_indices_[dir][x][y][size_t(tree)][size_t(lvl)].size()) { + rr_node_indices_[dir][x][y][size_t(tree)][size_t(lvl)].resize(size_t(pin) + + 1); } /* Resize on demand finished; Register the node */ rr_node_indices_[dir][x][y][size_t(tree)][size_t(lvl)][size_t(pin)] = node; } -void RRClockSpatialLookup::reserve_nodes(int x, int y, - int tree, - int lvl, +void RRClockSpatialLookup::reserve_nodes(int x, int y, int tree, int lvl, int pin) { for (Direction dir : {Direction::INC, Direction::DEC}) { resize_nodes(x, y, dir); @@ -104,7 +105,6 @@ void RRClockSpatialLookup::reserve_nodes(int x, int y, } } - void RRClockSpatialLookup::resize_nodes(int x, int y, const Direction& direction) { /* Expand the fast look-up if the new node is out-of-range diff --git a/libs/libclkarchopenfpga/src/base/rr_clock_spatial_lookup.h b/libs/libclkarchopenfpga/src/base/rr_clock_spatial_lookup.h index 25487a622..650c3e368 100644 --- a/libs/libclkarchopenfpga/src/base/rr_clock_spatial_lookup.h +++ b/libs/libclkarchopenfpga/src/base/rr_clock_spatial_lookup.h @@ -89,10 +89,7 @@ class RRClockSpatialLookup { * @brief Allocate memory for the lookup with maximum sizes on each dimension * .. note:: Must run before any other API! */ - void reserve_nodes(int x, int y, - int tree, - int lvl, - int pin); + void reserve_nodes(int x, int y, int tree, int lvl, int pin); /** @brief Clear all the data inside */ void clear(); @@ -106,11 +103,8 @@ class RRClockSpatialLookup { /* Fast look-up: * [INC|DEC][0..grid_width][0..grid_height][tree_id][level_id][clock_pin_id] */ - std::array< - vtr::NdMatrix< - std::vector>>, - 2>, - 2> + std::array>>, 2>, + 2> rr_node_indices_; }; diff --git a/openfpga/src/annotation/append_clock_rr_graph.cpp b/openfpga/src/annotation/append_clock_rr_graph.cpp index 23cc748f9..fdf889d2a 100644 --- a/openfpga/src/annotation/append_clock_rr_graph.cpp +++ b/openfpga/src/annotation/append_clock_rr_graph.cpp @@ -84,14 +84,11 @@ static size_t estimate_clock_rr_graph_num_nodes(const DeviceGrid& grids, * For each tree and level of the tree, add a number of clock nodes * 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 chan_coord, - const t_rr_type& chan_type, - const int& cost_index_offset, - const bool& verbose) { +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 chan_coord, const t_rr_type& chan_type, + const int& cost_index_offset, const bool& verbose) { size_t orig_chan_width = rr_graph_view.node_lookup() .find_channel_nodes(chan_coord.x(), chan_coord.y(), chan_type) @@ -100,8 +97,9 @@ 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)) { - /* As we want to keep uni-directional wires, clock routing tracks have to be in pairs. - * Therefore, always add clock routing tracks in pair, even one of them is not required + /* As we want to keep uni-directional wires, clock routing tracks have to + * be in pairs. Therefore, always add clock routing tracks in pair, even + * one of them is not required */ size_t num_pins = 0; bool require_complementary_pins = false; @@ -129,8 +127,12 @@ static void add_rr_graph_block_clock_nodes(RRGraphBuilder& rr_graph_builder, /* register the node to a dedicated lookup */ clk_rr_lookup.add_node(clk_node, chan_coord.x(), chan_coord.y(), itree, ilvl, ClockTreePinId(ipin), node_dir); - VTR_LOGV(verbose, "Added node '%lu' to clock node lookup (x='%lu' y='%lu' tree='%lu' level='%lu' pin='%lu' direction='%s')\n", - size_t(clk_node), chan_coord.x(), chan_coord.y(), size_t(itree), size_t(ilvl), ipin, DIRECTION_STRING[size_t(node_dir)]); + VTR_LOGV(verbose, + "Added node '%lu' to clock node lookup (x='%lu' y='%lu' " + "tree='%lu' level='%lu' pin='%lu' direction='%s')\n", + size_t(clk_node), chan_coord.x(), chan_coord.y(), + size_t(itree), size_t(ilvl), ipin, + DIRECTION_STRING[size_t(node_dir)]); /* Update ptc count and go to next */ curr_node_ptc++; } @@ -151,7 +153,9 @@ static void add_rr_graph_clock_nodes(RRGraphBuilder& rr_graph_builder, const ClockNetwork& clk_ntwk, const bool& verbose) { /* Pre-allocate memory: Must do otherwise data will be messed up! */ - clk_rr_lookup.reserve_nodes(grids.width(), grids.height(), clk_ntwk.num_trees(), clk_ntwk.max_tree_depth(), clk_ntwk.max_tree_width()); + clk_rr_lookup.reserve_nodes(grids.width(), grids.height(), + clk_ntwk.num_trees(), clk_ntwk.max_tree_depth(), + clk_ntwk.max_tree_width()); /* Add X-direction clock nodes */ for (size_t iy = 0; iy < grids.height() - 1; ++iy) { @@ -166,11 +170,14 @@ static void add_rr_graph_clock_nodes(RRGraphBuilder& rr_graph_builder, add_rr_graph_block_clock_nodes(rr_graph_builder, clk_rr_lookup, rr_graph_view, clk_ntwk, chanx_coord, CHANX, CHANX_COST_INDEX_START, verbose); - VTR_ASSERT(rr_graph_view.valid_node(clk_rr_lookup.find_node(1, 0, ClockTreeId(0), ClockLevelId(0), ClockTreePinId(0), Direction::INC))); + VTR_ASSERT(rr_graph_view.valid_node( + clk_rr_lookup.find_node(1, 0, ClockTreeId(0), ClockLevelId(0), + ClockTreePinId(0), Direction::INC))); } } - VTR_ASSERT(rr_graph_view.valid_node(clk_rr_lookup.find_node(1, 0, ClockTreeId(0), ClockLevelId(0), ClockTreePinId(0), Direction::INC))); + VTR_ASSERT(rr_graph_view.valid_node(clk_rr_lookup.find_node( + 1, 0, ClockTreeId(0), ClockLevelId(0), ClockTreePinId(0), Direction::INC))); /* Add Y-direction clock nodes */ for (size_t ix = 0; ix < grids.width() - 1; ++ix) { @@ -184,11 +191,15 @@ static void add_rr_graph_clock_nodes(RRGraphBuilder& rr_graph_builder, } add_rr_graph_block_clock_nodes( rr_graph_builder, clk_rr_lookup, rr_graph_view, clk_ntwk, chany_coord, - CHANY, CHANX_COST_INDEX_START + rr_graph_view.num_rr_segments(), verbose); - VTR_ASSERT(rr_graph_view.valid_node(clk_rr_lookup.find_node(1, 0, ClockTreeId(0), ClockLevelId(0), ClockTreePinId(0), Direction::INC))); + CHANY, CHANX_COST_INDEX_START + rr_graph_view.num_rr_segments(), + verbose); + VTR_ASSERT(rr_graph_view.valid_node( + clk_rr_lookup.find_node(1, 0, ClockTreeId(0), ClockLevelId(0), + ClockTreePinId(0), Direction::INC))); } } - VTR_ASSERT(rr_graph_view.valid_node(clk_rr_lookup.find_node(1, 0, ClockTreeId(0), ClockLevelId(0), ClockTreePinId(0), Direction::INC))); + VTR_ASSERT(rr_graph_view.valid_node(clk_rr_lookup.find_node( + 1, 0, ClockTreeId(0), ClockLevelId(0), ClockTreePinId(0), Direction::INC))); } /******************************************************************** @@ -481,8 +492,12 @@ static void add_rr_graph_block_clock_edges( /* find the driver clock node through lookup */ RRNodeId src_node = clk_rr_lookup.find_node( chan_coord.x(), chan_coord.y(), itree, ilvl, ipin, node_dir); - VTR_LOGV(verbose, "Try to find node '%lu' from clock node lookup (x='%lu' y='%lu' tree='%lu' level='%lu' pin='%lu' direction='%s')\n", - size_t(src_node), chan_coord.x(), chan_coord.y(), size_t(itree), size_t(ilvl), size_t(ipin), DIRECTION_STRING[size_t(node_dir)]); + VTR_LOGV(verbose, + "Try to find node '%lu' from clock node lookup (x='%lu' " + "y='%lu' tree='%lu' level='%lu' pin='%lu' direction='%s')\n", + size_t(src_node), chan_coord.x(), chan_coord.y(), + size_t(itree), size_t(ilvl), size_t(ipin), + DIRECTION_STRING[size_t(node_dir)]); VTR_ASSERT(rr_graph_view.valid_node(src_node)); if (!clk_ntwk.is_last_level(itree, ilvl)) { /* find the fan-out clock node through lookup */ @@ -539,14 +554,11 @@ static void add_rr_graph_block_clock_edges( * v * clk0_lvl1_chany[1][1] *******************************************************************/ -static void add_rr_graph_clock_edges(RRGraphBuilder& rr_graph_builder, - size_t& num_edges_to_create, - const RRClockSpatialLookup& clk_rr_lookup, - const RRGraphView& rr_graph_view, - const DeviceGrid& grids, - const bool& through_channel, - const ClockNetwork& clk_ntwk, - const bool& verbose) { +static void add_rr_graph_clock_edges( + RRGraphBuilder& rr_graph_builder, size_t& num_edges_to_create, + const RRClockSpatialLookup& clk_rr_lookup, const RRGraphView& rr_graph_view, + const DeviceGrid& grids, const bool& through_channel, + const ClockNetwork& clk_ntwk, const bool& verbose) { /* Add edges which is driven by X-direction clock routing tracks */ for (size_t iy = 0; iy < grids.height() - 1; ++iy) { for (size_t ix = 1; ix < grids.width() - 1; ++ix) { @@ -618,18 +630,19 @@ int append_clock_rr_graph(DeviceContext& vpr_device_ctx, vpr_device_ctx.rr_graph_builder.reserve_nodes(num_clock_nodes + orig_num_nodes); VTR_LOGV(verbose, - "Estimate %lu clock nodes (+%.5f%) to be added to routing " - "resource graph.\n", - num_clock_nodes, (float)(num_clock_nodes / orig_num_nodes)); + "Estimate %lu clock nodes (+%.5f%) to be added to routing " + "resource graph.\n", + num_clock_nodes, (float)(num_clock_nodes / orig_num_nodes)); /* 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, verbose); + vpr_device_ctx.arch->through_channel, clk_ntwk, + verbose); VTR_LOGV(verbose, - "Added %lu clock nodes to routing " - "resource graph.\n", - vpr_device_ctx.rr_graph.num_nodes() - orig_num_nodes); + "Added %lu clock nodes to routing " + "resource graph.\n", + vpr_device_ctx.rr_graph.num_nodes() - orig_num_nodes); VTR_ASSERT(num_clock_nodes + orig_num_nodes == vpr_device_ctx.rr_graph.num_nodes()); @@ -640,17 +653,25 @@ int append_clock_rr_graph(DeviceContext& vpr_device_ctx, static_cast(clk_rr_lookup), vpr_device_ctx.rr_graph, vpr_device_ctx.grid, vpr_device_ctx.arch->through_channel, clk_ntwk, verbose); + VTR_LOGV(verbose, + "Added %lu clock edges to routing " + "resource graph.\n", + num_clock_edges); /* TODO: Sanity checks */ + VTR_LOGV(verbose, "Initializing fan-in of nodes\n"); vpr_device_ctx.rr_graph_builder.init_fan_in(); + VTR_LOGV(verbose, "Apply edge partitioning\n"); vpr_device_ctx.rr_graph_builder.partition_edges(); + VTR_LOGV(verbose, "Building incoming edges\n"); vpr_device_ctx.rr_graph_builder.build_in_edges(); /* Report number of added clock nodes and edges */ - VTR_LOG("Appended %lu clock nodes (+%.2f%) and %lu clock edges to routing " - "resource graph.\n", - num_clock_nodes, (float)(num_clock_nodes / orig_num_nodes), - num_clock_edges); + VTR_LOG( + "Appended %lu clock nodes (+%.2f%) and %lu clock edges to routing " + "resource graph.\n", + num_clock_nodes, (float)(num_clock_nodes / orig_num_nodes), + num_clock_edges); return CMD_EXEC_SUCCESS; } From 1633279c65a5e23184daa4d2eb88d696bb53e373 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 6 Mar 2023 14:50:28 -0800 Subject: [PATCH 075/166] [core] fixed a bug in building edges for nodes --- .../src/annotation/append_clock_rr_graph.cpp | 31 +++++++++++++++---- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/openfpga/src/annotation/append_clock_rr_graph.cpp b/openfpga/src/annotation/append_clock_rr_graph.cpp index fdf889d2a..96acadd62 100644 --- a/openfpga/src/annotation/append_clock_rr_graph.cpp +++ b/openfpga/src/annotation/append_clock_rr_graph.cpp @@ -487,11 +487,26 @@ static void add_rr_graph_block_clock_edges( size_t edge_count = 0; for (auto itree : clk_ntwk.trees()) { for (auto ilvl : clk_ntwk.levels(itree)) { + /* As we want to keep uni-directional wires, clock routing tracks have to + * be in pairs. Therefore, always add clock routing tracks in pair, even + * one of them is not required + */ + size_t num_pins = 0; + bool require_complementary_pins = false; for (auto node_dir : {Direction::INC, Direction::DEC}) { - for (auto ipin : clk_ntwk.pins(itree, ilvl, chan_type, node_dir)) { + if (0 == clk_ntwk.pins(itree, ilvl, chan_type, node_dir).size()) { + require_complementary_pins = true; + } + num_pins += clk_ntwk.pins(itree, ilvl, chan_type, node_dir).size(); + } + if (require_complementary_pins) { + num_pins = 2 * num_pins; + } + for (size_t ipin = 0; ipin < num_pins / 2; ++ipin) { + for (auto node_dir : {Direction::INC, Direction::DEC}) { /* find the driver clock node through lookup */ RRNodeId src_node = clk_rr_lookup.find_node( - chan_coord.x(), chan_coord.y(), itree, ilvl, ipin, node_dir); + chan_coord.x(), chan_coord.y(), itree, ilvl, ClockTreePinId(ipin), node_dir); VTR_LOGV(verbose, "Try to find node '%lu' from clock node lookup (x='%lu' " "y='%lu' tree='%lu' level='%lu' pin='%lu' direction='%s')\n", @@ -501,28 +516,32 @@ static void add_rr_graph_block_clock_edges( VTR_ASSERT(rr_graph_view.valid_node(src_node)); if (!clk_ntwk.is_last_level(itree, ilvl)) { /* find the fan-out clock node through lookup */ + size_t curr_edge_count = edge_count; for (RRNodeId des_node : find_clock_track2track_node( rr_graph_view, clk_ntwk, clk_rr_lookup, chan_type, - chan_coord, itree, ilvl, ipin, node_dir)) { + chan_coord, itree, ilvl, ClockTreePinId(ipin), node_dir)) { /* Create edges */ VTR_ASSERT(rr_graph_view.valid_node(des_node)); rr_graph_builder.create_edge(src_node, des_node, clk_ntwk.default_switch()); edge_count++; } + VTR_LOGV(verbose, "\tWill add %lu edges to other clock nodes\n", edge_count - curr_edge_count); } /* If this is the clock node at the last level of the tree, * should drive some grid IPINs which are clocks */ if (clk_ntwk.is_last_level(itree, ilvl)) { + size_t curr_edge_count = edge_count; for (RRNodeId des_node : find_clock_track2ipin_node( grids, rr_graph_view, chan_type, chan_coord, clk_ntwk, itree, - ipin)) { + ClockTreePinId(ipin))) { /* Create edges */ VTR_ASSERT(rr_graph_view.valid_node(des_node)); rr_graph_builder.create_edge(src_node, des_node, clk_ntwk.default_switch()); edge_count++; } + VTR_LOGV(verbose, "\tWill add %lu edges to other IPIN\n", edge_count - curr_edge_count); } } } @@ -663,8 +682,8 @@ int append_clock_rr_graph(DeviceContext& vpr_device_ctx, vpr_device_ctx.rr_graph_builder.init_fan_in(); VTR_LOGV(verbose, "Apply edge partitioning\n"); vpr_device_ctx.rr_graph_builder.partition_edges(); - VTR_LOGV(verbose, "Building incoming edges\n"); - vpr_device_ctx.rr_graph_builder.build_in_edges(); + //VTR_LOGV(verbose, "Building incoming edges\n"); + //vpr_device_ctx.rr_graph_builder.build_in_edges(); /* Report number of added clock nodes and edges */ VTR_LOG( From 9823983b300855ea2814b3e03254b9adcde2cdeb Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 6 Mar 2023 15:57:37 -0800 Subject: [PATCH 076/166] [core] debuggign --- openfpga/src/annotation/append_clock_rr_graph.cpp | 4 ++-- vtr-verilog-to-routing | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/openfpga/src/annotation/append_clock_rr_graph.cpp b/openfpga/src/annotation/append_clock_rr_graph.cpp index 96acadd62..0f848ff36 100644 --- a/openfpga/src/annotation/append_clock_rr_graph.cpp +++ b/openfpga/src/annotation/append_clock_rr_graph.cpp @@ -682,8 +682,8 @@ int append_clock_rr_graph(DeviceContext& vpr_device_ctx, vpr_device_ctx.rr_graph_builder.init_fan_in(); VTR_LOGV(verbose, "Apply edge partitioning\n"); vpr_device_ctx.rr_graph_builder.partition_edges(); - //VTR_LOGV(verbose, "Building incoming edges\n"); - //vpr_device_ctx.rr_graph_builder.build_in_edges(); + VTR_LOGV(verbose, "Building incoming edges\n"); + vpr_device_ctx.rr_graph_builder.build_in_edges(); /* Report number of added clock nodes and edges */ VTR_LOG( diff --git a/vtr-verilog-to-routing b/vtr-verilog-to-routing index 5795b7df7..69d852d7e 160000 --- a/vtr-verilog-to-routing +++ b/vtr-verilog-to-routing @@ -1 +1 @@ -Subproject commit 5795b7df753903b215c1273cfe910113375f6aa8 +Subproject commit 69d852d7e968e9033c9f26541fae6e96eca72e5d From 153f1b5090abc03f83bacba1c913c4157ed6dd69 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 6 Mar 2023 16:07:11 -0800 Subject: [PATCH 077/166] [core] update vtr --- vtr-verilog-to-routing | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vtr-verilog-to-routing b/vtr-verilog-to-routing index 69d852d7e..67a84e1f1 160000 --- a/vtr-verilog-to-routing +++ b/vtr-verilog-to-routing @@ -1 +1 @@ -Subproject commit 69d852d7e968e9033c9f26541fae6e96eca72e5d +Subproject commit 67a84e1f16296e77de9642ffa1929924acb87d6c From 0fced0740a3b12f1ff5f87af97a4d2048f4699b6 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 6 Mar 2023 16:36:12 -0800 Subject: [PATCH 078/166] [core] update vtr --- vtr-verilog-to-routing | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vtr-verilog-to-routing b/vtr-verilog-to-routing index 67a84e1f1..8e623dc48 160000 --- a/vtr-verilog-to-routing +++ b/vtr-verilog-to-routing @@ -1 +1 @@ -Subproject commit 67a84e1f16296e77de9642ffa1929924acb87d6c +Subproject commit 8e623dc487f9ba671f65f5fe896daac62bda9952 From c23b8e579d618b5927cd21a3b8e0b222e7e42953 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 6 Mar 2023 17:10:14 -0800 Subject: [PATCH 079/166] [core] fixed a bug --- openfpga/src/annotation/route_clock_rr_graph.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openfpga/src/annotation/route_clock_rr_graph.cpp b/openfpga/src/annotation/route_clock_rr_graph.cpp index 1b4e8a206..93cc32bba 100644 --- a/openfpga/src/annotation/route_clock_rr_graph.cpp +++ b/openfpga/src/annotation/route_clock_rr_graph.cpp @@ -114,7 +114,7 @@ int route_clock_rr_graph(VprRoutingAnnotation& vpr_routing_annotation, "Route programmable clock network based on routing resource graph"); /* Skip if there is no clock tree */ - if (clk_ntwk.num_trees()) { + if (0 == clk_ntwk.num_trees()) { VTR_LOG( "Skip due to 0 clock trees.\nDouble check your clock architecture " "definition if this is unexpected\n"); From 45107bf14f9d4048f878837f25f80f88bea20e51 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 6 Mar 2023 21:48:19 -0800 Subject: [PATCH 080/166] [core] debugging --- openfpga/src/annotation/annotate_rr_graph.cpp | 8 +++++--- openfpga/src/annotation/annotate_rr_graph.h | 1 + openfpga/src/base/openfpga_link_arch_template.h | 1 + openfpga/src/fpga_bitstream/build_mux_bitstream.cpp | 3 +++ openfpga/src/mux_lib/mux_library_builder.cpp | 3 +++ vtr-verilog-to-routing | 2 +- 6 files changed, 14 insertions(+), 4 deletions(-) diff --git a/openfpga/src/annotation/annotate_rr_graph.cpp b/openfpga/src/annotation/annotate_rr_graph.cpp index d88f2d692..84a994577 100644 --- a/openfpga/src/annotation/annotate_rr_graph.cpp +++ b/openfpga/src/annotation/annotate_rr_graph.cpp @@ -96,7 +96,8 @@ static RRChan build_one_rr_chan(const DeviceContext& vpr_device_ctx, */ static RRGSB build_rr_gsb(const DeviceContext& vpr_device_ctx, const vtr::Point& gsb_range, - const vtr::Point& gsb_coord) { + const vtr::Point& gsb_coord, + const bool& include_clock) { /* Create an object to return */ RRGSB rr_gsb; @@ -370,7 +371,7 @@ static RRGSB build_rr_gsb(const DeviceContext& vpr_device_ctx, /* Collect IPIN rr_nodes*/ temp_ipin_rr_nodes = find_rr_graph_grid_nodes(vpr_device_ctx.rr_graph, vpr_device_ctx.grid, ix, - iy, IPIN, ipin_rr_node_grid_side); + iy, IPIN, ipin_rr_node_grid_side, include_clock); /* Fill the ipin nodes of RRGSB */ for (const RRNodeId& inode : temp_ipin_rr_nodes) { /* Skip those has no configurable outgoing, they should NOT appear in the @@ -405,6 +406,7 @@ static RRGSB build_rr_gsb(const DeviceContext& vpr_device_ctx, *******************************************************************/ void annotate_device_rr_gsb(const DeviceContext& vpr_device_ctx, DeviceRRGSB& device_rr_gsb, + const bool& include_clock, const bool& verbose_output) { vtr::ScopedStartFinishTimer timer( "Build General Switch Block(GSB) annotation on top of routing resource " @@ -431,7 +433,7 @@ void annotate_device_rr_gsb(const DeviceContext& vpr_device_ctx, build_rr_gsb(vpr_device_ctx, vtr::Point(vpr_device_ctx.grid.width() - 2, vpr_device_ctx.grid.height() - 2), - vtr::Point(ix, iy)); + vtr::Point(ix, iy), include_clock); /* Add to device_rr_gsb */ vtr::Point gsb_coordinate = rr_gsb.get_sb_coordinate(); diff --git a/openfpga/src/annotation/annotate_rr_graph.h b/openfpga/src/annotation/annotate_rr_graph.h index f2822c2a4..1e0fdd870 100644 --- a/openfpga/src/annotation/annotate_rr_graph.h +++ b/openfpga/src/annotation/annotate_rr_graph.h @@ -17,6 +17,7 @@ namespace openfpga { void annotate_device_rr_gsb(const DeviceContext& vpr_device_ctx, DeviceRRGSB& device_rr_gsb, + const bool& include_clock, const bool& verbose_output); void sort_device_rr_gsb_chan_node_in_edges(const RRGraphView& rr_graph, diff --git a/openfpga/src/base/openfpga_link_arch_template.h b/openfpga/src/base/openfpga_link_arch_template.h index 759cc0c1f..2c6fa787c 100644 --- a/openfpga/src/base/openfpga_link_arch_template.h +++ b/openfpga/src/base/openfpga_link_arch_template.h @@ -110,6 +110,7 @@ int link_arch_template(T& openfpga_ctx, const Command& cmd, VTR_ASSERT(g_vpr_ctx.device().rr_graph.validate_in_edges()); annotate_device_rr_gsb(g_vpr_ctx.device(), openfpga_ctx.mutable_device_rr_gsb(), + !openfpga_ctx.clock_arch().empty(), /* FIXME: consider to be more robust! */ cmd_context.option_enable(cmd, opt_verbose)); if (true == cmd_context.option_enable(cmd, opt_sort_edge)) { diff --git a/openfpga/src/fpga_bitstream/build_mux_bitstream.cpp b/openfpga/src/fpga_bitstream/build_mux_bitstream.cpp index fca568ea5..f3e3cf936 100644 --- a/openfpga/src/fpga_bitstream/build_mux_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/build_mux_bitstream.cpp @@ -68,6 +68,9 @@ static std::vector build_cmos_mux_bitstream( find_mux_implementation_num_inputs(circuit_lib, mux_model, mux_size); /* Note that the mux graph is indexed using datapath MUX size!!!! */ MuxId mux_graph_id = mux_lib.mux_graph(mux_model, mux_size); + if (!mux_lib.valid_mux_id(mux_graph_id)) { + VTR_ASSERT(mux_lib.valid_mux_id(mux_graph_id)); + } const MuxGraph mux_graph = mux_lib.mux_graph(mux_graph_id); size_t datapath_id = path_id; diff --git a/openfpga/src/mux_lib/mux_library_builder.cpp b/openfpga/src/mux_lib/mux_library_builder.cpp index add2acf53..9dbe78253 100644 --- a/openfpga/src/mux_lib/mux_library_builder.cpp +++ b/openfpga/src/mux_lib/mux_library_builder.cpp @@ -231,6 +231,9 @@ MuxLibrary build_device_mux_library(const DeviceContext& vpr_device_ctx, VTR_LOG("Built a multiplexer library of %lu physical multiplexers.\n", mux_lib.muxes().size()); VTR_LOG("Maximum multiplexer size is %lu.\n", mux_lib.max_mux_size()); + for (auto mux_id : mux_lib.muxes()) { + VTR_LOG("\tmodel '%s', input_size='%lu'\n", openfpga_ctx.arch().circuit_lib.model_name(mux_lib.mux_circuit_model(mux_id)).c_str(), mux_lib.mux_graph(mux_id).num_inputs()); + } return mux_lib; } diff --git a/vtr-verilog-to-routing b/vtr-verilog-to-routing index 8e623dc48..1a9b9708b 160000 --- a/vtr-verilog-to-routing +++ b/vtr-verilog-to-routing @@ -1 +1 @@ -Subproject commit 8e623dc487f9ba671f65f5fe896daac62bda9952 +Subproject commit 1a9b9708bbbf7ddd8f4786a0b5afd5db5f1404eb From aa897fdeadbe29dd80018377b935b105d950b67b Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 6 Mar 2023 21:49:06 -0800 Subject: [PATCH 081/166] [core] debugging --- vtr-verilog-to-routing | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vtr-verilog-to-routing b/vtr-verilog-to-routing index 1a9b9708b..4199c48f3 160000 --- a/vtr-verilog-to-routing +++ b/vtr-verilog-to-routing @@ -1 +1 @@ -Subproject commit 1a9b9708bbbf7ddd8f4786a0b5afd5db5f1404eb +Subproject commit 4199c48f319c2f68ec0703546fbc41c76cd20ace From 5bbd636b252e9e35023a221af447971f9ccb5df3 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 6 Mar 2023 21:49:46 -0800 Subject: [PATCH 082/166] [core] debugging --- vtr-verilog-to-routing | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vtr-verilog-to-routing b/vtr-verilog-to-routing index 4199c48f3..2796b587a 160000 --- a/vtr-verilog-to-routing +++ b/vtr-verilog-to-routing @@ -1 +1 @@ -Subproject commit 4199c48f319c2f68ec0703546fbc41c76cd20ace +Subproject commit 2796b587a6a06a5dd509464081a4c278f128a297 From cb679adf3da08346ece142fa444ca5ac741e9461 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 6 Mar 2023 21:50:30 -0800 Subject: [PATCH 083/166] [core] debugging --- vtr-verilog-to-routing | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vtr-verilog-to-routing b/vtr-verilog-to-routing index 2796b587a..ebb804ee3 160000 --- a/vtr-verilog-to-routing +++ b/vtr-verilog-to-routing @@ -1 +1 @@ -Subproject commit 2796b587a6a06a5dd509464081a4c278f128a297 +Subproject commit ebb804ee3da336b555ecf7d95c88272bb0faa14a From c1c24b6be1ca3295c0b457de6b732cd6add0bee8 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 6 Mar 2023 21:56:36 -0800 Subject: [PATCH 084/166] [core] update vtr --- vtr-verilog-to-routing | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vtr-verilog-to-routing b/vtr-verilog-to-routing index ebb804ee3..0f40ecba4 160000 --- a/vtr-verilog-to-routing +++ b/vtr-verilog-to-routing @@ -1 +1 @@ -Subproject commit ebb804ee3da336b555ecf7d95c88272bb0faa14a +Subproject commit 0f40ecba43479b0f830151adcecbf641fb2e9fe3 From 2ff3ad61cea2e4c13e30d427a60ae4b674f53abb Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 6 Mar 2023 21:57:44 -0800 Subject: [PATCH 085/166] [core] format --- openfpga/src/annotation/append_clock_rr_graph.cpp | 11 +++++++---- openfpga/src/base/openfpga_link_arch_template.h | 8 ++++---- openfpga/src/mux_lib/mux_library_builder.cpp | 6 +++++- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/openfpga/src/annotation/append_clock_rr_graph.cpp b/openfpga/src/annotation/append_clock_rr_graph.cpp index 0f848ff36..81159d5bf 100644 --- a/openfpga/src/annotation/append_clock_rr_graph.cpp +++ b/openfpga/src/annotation/append_clock_rr_graph.cpp @@ -505,8 +505,9 @@ static void add_rr_graph_block_clock_edges( for (size_t ipin = 0; ipin < num_pins / 2; ++ipin) { for (auto node_dir : {Direction::INC, Direction::DEC}) { /* find the driver clock node through lookup */ - RRNodeId src_node = clk_rr_lookup.find_node( - chan_coord.x(), chan_coord.y(), itree, ilvl, ClockTreePinId(ipin), node_dir); + RRNodeId src_node = + clk_rr_lookup.find_node(chan_coord.x(), chan_coord.y(), itree, ilvl, + ClockTreePinId(ipin), node_dir); VTR_LOGV(verbose, "Try to find node '%lu' from clock node lookup (x='%lu' " "y='%lu' tree='%lu' level='%lu' pin='%lu' direction='%s')\n", @@ -526,7 +527,8 @@ static void add_rr_graph_block_clock_edges( clk_ntwk.default_switch()); edge_count++; } - VTR_LOGV(verbose, "\tWill add %lu edges to other clock nodes\n", edge_count - curr_edge_count); + VTR_LOGV(verbose, "\tWill add %lu edges to other clock nodes\n", + edge_count - curr_edge_count); } /* If this is the clock node at the last level of the tree, * should drive some grid IPINs which are clocks */ @@ -541,7 +543,8 @@ static void add_rr_graph_block_clock_edges( clk_ntwk.default_switch()); edge_count++; } - VTR_LOGV(verbose, "\tWill add %lu edges to other IPIN\n", edge_count - curr_edge_count); + VTR_LOGV(verbose, "\tWill add %lu edges to other IPIN\n", + edge_count - curr_edge_count); } } } diff --git a/openfpga/src/base/openfpga_link_arch_template.h b/openfpga/src/base/openfpga_link_arch_template.h index 2c6fa787c..d9345780c 100644 --- a/openfpga/src/base/openfpga_link_arch_template.h +++ b/openfpga/src/base/openfpga_link_arch_template.h @@ -108,10 +108,10 @@ int link_arch_template(T& openfpga_ctx, const Command& cmd, VTR_LOG("Built %ld incoming edges for routing resource graph\n", g_vpr_ctx.device().rr_graph.in_edges_count()); VTR_ASSERT(g_vpr_ctx.device().rr_graph.validate_in_edges()); - annotate_device_rr_gsb(g_vpr_ctx.device(), - openfpga_ctx.mutable_device_rr_gsb(), - !openfpga_ctx.clock_arch().empty(), /* FIXME: consider to be more robust! */ - cmd_context.option_enable(cmd, opt_verbose)); + annotate_device_rr_gsb( + g_vpr_ctx.device(), openfpga_ctx.mutable_device_rr_gsb(), + !openfpga_ctx.clock_arch().empty(), /* FIXME: consider to be more robust! */ + cmd_context.option_enable(cmd, opt_verbose)); if (true == cmd_context.option_enable(cmd, opt_sort_edge)) { sort_device_rr_gsb_chan_node_in_edges( diff --git a/openfpga/src/mux_lib/mux_library_builder.cpp b/openfpga/src/mux_lib/mux_library_builder.cpp index 9dbe78253..4cf4b62c3 100644 --- a/openfpga/src/mux_lib/mux_library_builder.cpp +++ b/openfpga/src/mux_lib/mux_library_builder.cpp @@ -232,7 +232,11 @@ MuxLibrary build_device_mux_library(const DeviceContext& vpr_device_ctx, mux_lib.muxes().size()); VTR_LOG("Maximum multiplexer size is %lu.\n", mux_lib.max_mux_size()); for (auto mux_id : mux_lib.muxes()) { - VTR_LOG("\tmodel '%s', input_size='%lu'\n", openfpga_ctx.arch().circuit_lib.model_name(mux_lib.mux_circuit_model(mux_id)).c_str(), mux_lib.mux_graph(mux_id).num_inputs()); + VTR_LOG("\tmodel '%s', input_size='%lu'\n", + openfpga_ctx.arch() + .circuit_lib.model_name(mux_lib.mux_circuit_model(mux_id)) + .c_str(), + mux_lib.mux_graph(mux_id).num_inputs()); } return mux_lib; From 550e68c68b0a73fd2ccd8f74bf6cbb07b8f41e3f Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 6 Mar 2023 22:26:27 -0800 Subject: [PATCH 086/166] [core] fixed a bug: node_fan_in seems buggy --- .../fpga_bitstream/build_device_bitstream.cpp | 2 +- .../build_routing_bitstream.cpp | 43 ++++++++++++++----- .../fpga_bitstream/build_routing_bitstream.h | 3 +- 3 files changed, 36 insertions(+), 12 deletions(-) diff --git a/openfpga/src/fpga_bitstream/build_device_bitstream.cpp b/openfpga/src/fpga_bitstream/build_device_bitstream.cpp index 7196a6781..e4bd1b79c 100644 --- a/openfpga/src/fpga_bitstream/build_device_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/build_device_bitstream.cpp @@ -196,7 +196,7 @@ BitstreamManager build_device_bitstream(const VprContext& vpr_ctx, openfpga_ctx.arch().circuit_lib, openfpga_ctx.mux_lib(), vpr_ctx.atom(), openfpga_ctx.vpr_device_annotation(), openfpga_ctx.vpr_routing_annotation(), vpr_ctx.device().rr_graph, openfpga_ctx.device_rr_gsb(), - openfpga_ctx.flow_manager().compress_routing()); + openfpga_ctx.flow_manager().compress_routing(), verbose); VTR_LOGV(verbose, "Done\n"); VTR_LOGV(verbose, "Decoded %lu configuration bits into %lu blocks\n", diff --git a/openfpga/src/fpga_bitstream/build_routing_bitstream.cpp b/openfpga/src/fpga_bitstream/build_routing_bitstream.cpp index 7af606194..c2d2e18ae 100644 --- a/openfpga/src/fpga_bitstream/build_routing_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/build_routing_bitstream.cpp @@ -243,10 +243,9 @@ static void build_connection_block_mux_bitstream( const RRGSB& rr_gsb, const e_side& cb_ipin_side, const size_t& ipin_index) { RRNodeId src_rr_node = rr_gsb.get_ipin_node(cb_ipin_side, ipin_index); /* Find drive_rr_nodes*/ - size_t datapath_mux_size = rr_graph.node_fan_in(src_rr_node); - std::vector driver_rr_edges = rr_gsb.get_ipin_node_in_edges(rr_graph, cb_ipin_side, ipin_index); + size_t datapath_mux_size = driver_rr_edges.size(); /* Cache input and output nets */ std::vector input_nets; @@ -357,9 +356,12 @@ static void build_connection_block_interc_bitstream( const MuxLibrary& mux_lib, const AtomContext& atom_ctx, const VprDeviceAnnotation& device_annotation, const VprRoutingAnnotation& routing_annotation, const RRGraphView& rr_graph, - const RRGSB& rr_gsb, const e_side& cb_ipin_side, const size_t& ipin_index) { + const RRGSB& rr_gsb, const e_side& cb_ipin_side, const size_t& ipin_index, + const bool& verbose) { RRNodeId src_rr_node = rr_gsb.get_ipin_node(cb_ipin_side, ipin_index); + VTR_LOGV(verbose, "\tGenerating bitstream for IPIN '%lu'\n", ipin_index); + /* Consider configurable edges only */ std::vector driver_rr_edges = rr_gsb.get_ipin_node_in_edges(rr_graph, cb_ipin_side, ipin_index); @@ -405,7 +407,7 @@ static void build_connection_block_bitstream( const MuxLibrary& mux_lib, const AtomContext& atom_ctx, const VprDeviceAnnotation& device_annotation, const VprRoutingAnnotation& routing_annotation, const RRGraphView& rr_graph, - const RRGSB& rr_gsb, const t_rr_type& cb_type) { + const RRGSB& rr_gsb, const t_rr_type& cb_type, const bool& verbose) { /* Find routing multiplexers on the sides of a Connection block where IPIN * nodes locate */ std::vector cb_sides = rr_gsb.get_cb_ipin_sides(cb_type); @@ -415,10 +417,12 @@ static void build_connection_block_bitstream( SideManager side_manager(cb_ipin_side); for (size_t inode = 0; inode < rr_gsb.get_num_ipin_nodes(cb_ipin_side); ++inode) { + VTR_LOGV(verbose, "\tGenerating bitstream for IPIN at '%s' side\n", + side_manager.to_string().c_str()); build_connection_block_interc_bitstream( bitstream_manager, cb_configurable_block, module_manager, circuit_lib, mux_lib, atom_ctx, device_annotation, routing_annotation, rr_graph, - rr_gsb, cb_ipin_side, inode); + rr_gsb, cb_ipin_side, inode, verbose); } } } @@ -434,7 +438,7 @@ static void build_connection_block_bitstreams( const VprDeviceAnnotation& device_annotation, const VprRoutingAnnotation& routing_annotation, const RRGraphView& rr_graph, const DeviceRRGSB& device_rr_gsb, const bool& compact_routing_hierarchy, - const t_rr_type& cb_type) { + const t_rr_type& cb_type, const bool& verbose) { vtr::Point cb_range = device_rr_gsb.get_gsb_range(); for (size_t ix = 0; ix < cb_range.x(); ++ix) { @@ -450,9 +454,19 @@ static void build_connection_block_bitstreams( /* Skip if the cb does not contain any configuration bits! */ if (true == connection_block_contain_only_routing_tracks(rr_gsb, cb_type)) { + VTR_LOGV(verbose, + "\n\tSkipped %s Connection Block [%lu][%lu] as it contains " + "only routing tracks\n", + cb_type == CHANX ? "X-direction" : "Y-direction", + rr_gsb.get_cb_x(cb_type), rr_gsb.get_cb_y(cb_type)); continue; } + VTR_LOGV(verbose, + "\n\tGenerating bitstream for %s Connection Block [%lu][%lu]\n", + cb_type == CHANX ? "X-direction" : "Y-direction", + rr_gsb.get_cb_x(cb_type), rr_gsb.get_cb_y(cb_type)); + /* Find the cb module so that we can precisely reserve child blocks */ vtr::Point cb_coord(rr_gsb.get_cb_x(cb_type), rr_gsb.get_cb_y(cb_type)); @@ -494,7 +508,9 @@ static void build_connection_block_bitstreams( build_connection_block_bitstream( bitstream_manager, cb_configurable_block, module_manager, circuit_lib, mux_lib, atom_ctx, device_annotation, routing_annotation, rr_graph, - rr_gsb, cb_type); + rr_gsb, cb_type, verbose); + + VTR_LOGV(verbose, "\tDone\n"); } } } @@ -512,7 +528,8 @@ void build_routing_bitstream( const MuxLibrary& mux_lib, const AtomContext& atom_ctx, const VprDeviceAnnotation& device_annotation, const VprRoutingAnnotation& routing_annotation, const RRGraphView& rr_graph, - const DeviceRRGSB& device_rr_gsb, const bool& compact_routing_hierarchy) { + const DeviceRRGSB& device_rr_gsb, const bool& compact_routing_hierarchy, + const bool& verbose) { /* Generate bitstream for each switch blocks * To organize the bitstream in blocks, we create a block for each switch * block and give names which are same as they are in top-level module @@ -531,6 +548,10 @@ void build_routing_bitstream( continue; } + VTR_LOGV(verbose, + "\n\tGenerating bitstream for Switch blocks[%lu][%lu]...\n", ix, + iy); + vtr::Point sb_coord(rr_gsb.get_sb_x(), rr_gsb.get_sb_y()); /* Find the sb module so that we can precisely reserve child blocks */ @@ -570,6 +591,8 @@ void build_routing_bitstream( module_manager, circuit_lib, mux_lib, atom_ctx, device_annotation, routing_annotation, rr_graph, rr_gsb); + + VTR_LOGV(verbose, "\tDone\n"); } } VTR_LOG("Done\n"); @@ -584,7 +607,7 @@ void build_routing_bitstream( build_connection_block_bitstreams( bitstream_manager, top_configurable_block, module_manager, circuit_lib, mux_lib, atom_ctx, device_annotation, routing_annotation, rr_graph, - device_rr_gsb, compact_routing_hierarchy, CHANX); + device_rr_gsb, compact_routing_hierarchy, CHANX, verbose); VTR_LOG("Done\n"); VTR_LOG("Generating bitstream for Y-direction Connection blocks ..."); @@ -592,7 +615,7 @@ void build_routing_bitstream( build_connection_block_bitstreams( bitstream_manager, top_configurable_block, module_manager, circuit_lib, mux_lib, atom_ctx, device_annotation, routing_annotation, rr_graph, - device_rr_gsb, compact_routing_hierarchy, CHANY); + device_rr_gsb, compact_routing_hierarchy, CHANY, verbose); VTR_LOG("Done\n"); } diff --git a/openfpga/src/fpga_bitstream/build_routing_bitstream.h b/openfpga/src/fpga_bitstream/build_routing_bitstream.h index ea955dbe1..433c8dbe5 100644 --- a/openfpga/src/fpga_bitstream/build_routing_bitstream.h +++ b/openfpga/src/fpga_bitstream/build_routing_bitstream.h @@ -32,7 +32,8 @@ void build_routing_bitstream( const MuxLibrary& mux_lib, const AtomContext& atom_ctx, const VprDeviceAnnotation& device_annotation, const VprRoutingAnnotation& routing_annotation, const RRGraphView& rr_graph, - const DeviceRRGSB& device_rr_gsb, const bool& compact_routing_hierarchy); + const DeviceRRGSB& device_rr_gsb, const bool& compact_routing_hierarchy, + const bool& verbose); } /* end namespace openfpga */ From 7e3b656c514a4754e07232bfdcd0da21f6e4ebb7 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 6 Mar 2023 23:06:32 -0800 Subject: [PATCH 087/166] [test] fixed a bug in arch --- openfpga_flow/vpr_arch/k4_N4_tileable_Ntwk1clk2lvl_40nm.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openfpga_flow/vpr_arch/k4_N4_tileable_Ntwk1clk2lvl_40nm.xml b/openfpga_flow/vpr_arch/k4_N4_tileable_Ntwk1clk2lvl_40nm.xml index 24f0704d0..61960bb76 100644 --- a/openfpga_flow/vpr_arch/k4_N4_tileable_Ntwk1clk2lvl_40nm.xml +++ b/openfpga_flow/vpr_arch/k4_N4_tileable_Ntwk1clk2lvl_40nm.xml @@ -64,9 +64,9 @@ - clb.clk + clb.I[0:4] clb.O[0:1] - clb.I[5:9] clb.O[2:3] + clb.I[5:9] clb.O[2:3] clb.clk From 50e201feeba9613410d00a1d5dd936e4c5d92919 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 7 Mar 2023 13:13:25 -0800 Subject: [PATCH 088/166] [core] now clock routing for programmable clock network works for 1 clock design --- .../src/annotation/route_clock_rr_graph.cpp | 124 +++++++++++++++++- .../src/annotation/route_clock_rr_graph.h | 9 +- .../src/base/openfpga_link_arch_template.h | 14 +- .../base/openfpga_setup_command_template.h | 7 + 4 files changed, 146 insertions(+), 8 deletions(-) diff --git a/openfpga/src/annotation/route_clock_rr_graph.cpp b/openfpga/src/annotation/route_clock_rr_graph.cpp index 93cc32bba..2d4d152f6 100644 --- a/openfpga/src/annotation/route_clock_rr_graph.cpp +++ b/openfpga/src/annotation/route_clock_rr_graph.cpp @@ -1,6 +1,7 @@ #include "route_clock_rr_graph.h" #include "command_exit_codes.h" +#include "openfpga_atom_netlist_utils.h" #include "vtr_assert.h" #include "vtr_geometry.h" #include "vtr_log.h" @@ -9,6 +10,73 @@ /* begin namespace openfpga */ namespace openfpga { +/******************************************************************** + * Build the lookup between clock name and pins and clock tree pins + * This is required for routing clock nets in each clock tree + * Special: when there is only 1 clock and 1 clock tree (width = 1), the mapping + *is straight forward + * FIXME: This part works only for clock network which constains only 1 clock + *tree! + *******************************************************************/ +static int build_clock_tree_net_map( + std::map& tree2clk_pin_map, + const ClusteredNetlist& cluster_nlist, const PinConstraints& pin_constraints, + const std::vector& clk_names, const ClockNetwork& clk_ntwk, + const ClockTreeId clk_tree, const bool& verbose) { + /* Find the pin id for each clock name, error out if there is any mismatch */ + if (clk_names.size() == 1 && clk_ntwk.tree_width(clk_tree) == 1) { + /* Find cluster net id */ + ClusterNetId clk_net = cluster_nlist.find_net(clk_names[0]); + if (!cluster_nlist.valid_net_id(clk_net)) { + VTR_LOG_ERROR("Invalid clock name '%s'! Cannot found from netlists!\n", + clk_names[0].c_str()); + return CMD_EXEC_FATAL_ERROR; + } + tree2clk_pin_map[ClockTreePinId(0)] = clk_net; + } else { + for (std::string clk_name : clk_names) { + /* Find the pin information that the net should be mapped to */ + BasicPort tree_pin = pin_constraints.net_pin(clk_name); + if (!tree_pin.is_valid()) { + VTR_LOG_ERROR( + "Invalid tree pin for clock '%s'! Clock name may not be valid " + "(mismatched with netlists)!\n", + clk_name.c_str()); + return CMD_EXEC_FATAL_ERROR; + } + if (tree_pin.get_width() != 1) { + VTR_LOG_ERROR( + "Invalid tree pin %s[%lu:%lu] for clock '%s'! Clock pin must have " + "only a width of 1!\n", + tree_pin.get_name().c_str(), tree_pin.get_lsb(), tree_pin.get_msb(), + clk_name.c_str()); + return CMD_EXEC_FATAL_ERROR; + } + if (tree_pin.get_lsb() >= clk_ntwk.tree_width(clk_tree)) { + VTR_LOG_ERROR( + "Invalid tree pin %s[%lu] is out of range of clock tree size '%lu'\n", + tree_pin.get_name().c_str(), tree_pin.get_lsb(), + clk_ntwk.tree_width(clk_tree)); + return CMD_EXEC_FATAL_ERROR; + } + /* Find cluster net id */ + ClusterNetId clk_net = cluster_nlist.find_net(clk_name); + if (!cluster_nlist.valid_net_id(clk_net)) { + VTR_LOG_ERROR("Invalid clock name '%s'! Cannot found from netlists!\n", + clk_name.c_str()); + return CMD_EXEC_FATAL_ERROR; + } + /* Register the pin mapping */ + tree2clk_pin_map[ClockTreePinId(tree_pin.get_lsb())] = clk_net; + } + } + + VTR_LOGV(verbose, "Build a pin map for %lu clock nets and pins.\n", + tree2clk_pin_map.size()); + + return CMD_EXEC_SUCCESS; +} + /******************************************************************** * Route a clock tree on an existing routing resource graph * The strategy is to route spine one by one @@ -18,8 +86,10 @@ namespace openfpga { *******************************************************************/ static int route_clock_tree_rr_graph( VprRoutingAnnotation& vpr_routing_annotation, const RRGraphView& rr_graph, - const RRClockSpatialLookup& clk_rr_lookup, const ClockNetwork& clk_ntwk, - const ClockTreeId clk_tree, const bool& verbose) { + const RRClockSpatialLookup& clk_rr_lookup, + const std::map& tree2clk_pin_map, + const ClockNetwork& clk_ntwk, const ClockTreeId& clk_tree, + const bool& verbose) { for (auto ispine : clk_ntwk.spines(clk_tree)) { VTR_LOGV(verbose, "Routing spine '%s'...\n", clk_ntwk.spine_name(ispine).c_str()); @@ -71,6 +141,10 @@ static int route_clock_tree_rr_graph( VTR_ASSERT(rr_graph.valid_node(des_node)); vpr_routing_annotation.set_rr_node_prev_node(rr_graph, des_node, src_node); + vpr_routing_annotation.set_rr_node_net(src_node, + tree2clk_pin_map.at(ipin)); + vpr_routing_annotation.set_rr_node_net(des_node, + tree2clk_pin_map.at(ipin)); } /* Route the spine-to-IPIN connections (only for the last level) */ if (clk_ntwk.is_last_level(ispine)) { @@ -91,6 +165,10 @@ static int route_clock_tree_rr_graph( VTR_ASSERT(rr_graph.valid_node(des_node)); vpr_routing_annotation.set_rr_node_prev_node(rr_graph, des_node, src_node); + vpr_routing_annotation.set_rr_node_net(src_node, + tree2clk_pin_map.at(ipin)); + vpr_routing_annotation.set_rr_node_net(des_node, + tree2clk_pin_map.at(ipin)); } } } @@ -108,8 +186,13 @@ static int route_clock_tree_rr_graph( *******************************************************************/ int route_clock_rr_graph(VprRoutingAnnotation& vpr_routing_annotation, const DeviceContext& vpr_device_ctx, + const AtomContext& atom_ctx, + const ClusteredNetlist& cluster_nlist, + const VprNetlistAnnotation& netlist_annotation, const RRClockSpatialLookup& clk_rr_lookup, - const ClockNetwork& clk_ntwk, const bool& verbose) { + const ClockNetwork& clk_ntwk, + const PinConstraints& pin_constraints, + const bool& verbose) { vtr::ScopedStartFinishTimer timer( "Route programmable clock network based on routing resource graph"); @@ -129,13 +212,42 @@ int route_clock_rr_graph(VprRoutingAnnotation& vpr_routing_annotation, return CMD_EXEC_FATAL_ERROR; } + /* If there are multiple clock signals from the netlist, require pin + * constraints */ + std::vector clock_net_names = + find_atom_netlist_clock_port_names(atom_ctx.nlist, netlist_annotation); + if (clock_net_names.empty()) { + VTR_LOG( + "Skip due to 0 clocks found from netlist\nDouble check your HDL design " + "if this is unexpected\n"); + return CMD_EXEC_SUCCESS; + } + if (clock_net_names.size() > 1 && pin_constraints.empty()) { + VTR_LOG( + "There is %lu clock nets (more than 1). Require pin constraints to be " + "specified\n", + clock_net_names.size()); + return CMD_EXEC_FATAL_ERROR; + } + /* Route spines one by one */ for (auto itree : clk_ntwk.trees()) { + VTR_LOGV(verbose, "Build clock name to clock tree '%s' pin mapping...\n", + clk_ntwk.tree_name(itree).c_str()); + std::map tree2clk_pin_map; + int status = CMD_EXEC_SUCCESS; + status = + build_clock_tree_net_map(tree2clk_pin_map, cluster_nlist, pin_constraints, + clock_net_names, clk_ntwk, itree, verbose); + if (status == CMD_EXEC_FATAL_ERROR) { + return status; + } + VTR_LOGV(verbose, "Routing clock tree '%s'...\n", clk_ntwk.tree_name(itree).c_str()); - int status = - route_clock_tree_rr_graph(vpr_routing_annotation, vpr_device_ctx.rr_graph, - clk_rr_lookup, clk_ntwk, itree, verbose); + status = route_clock_tree_rr_graph( + vpr_routing_annotation, vpr_device_ctx.rr_graph, clk_rr_lookup, + tree2clk_pin_map, clk_ntwk, itree, verbose); if (status == CMD_EXEC_FATAL_ERROR) { return status; } diff --git a/openfpga/src/annotation/route_clock_rr_graph.h b/openfpga/src/annotation/route_clock_rr_graph.h index 5e5eda9e9..6a1b2cad4 100644 --- a/openfpga/src/annotation/route_clock_rr_graph.h +++ b/openfpga/src/annotation/route_clock_rr_graph.h @@ -5,8 +5,10 @@ * Include header files that are required by function declaration *******************************************************************/ #include "clock_network.h" +#include "pin_constraints.h" #include "rr_clock_spatial_lookup.h" #include "vpr_context.h" +#include "vpr_netlist_annotation.h" #include "vpr_routing_annotation.h" /******************************************************************** @@ -18,8 +20,13 @@ namespace openfpga { int route_clock_rr_graph(VprRoutingAnnotation& vpr_routing_annotation, const DeviceContext& vpr_device_ctx, + const AtomContext& atom_ctx, + const ClusteredNetlist& cluster_nlist, + const VprNetlistAnnotation& netlist_annotation, const RRClockSpatialLookup& clk_rr_lookup, - const ClockNetwork& clk_ntwk, const bool& verbose); + const ClockNetwork& clk_ntwk, + const PinConstraints& pin_constraints, + const bool& verbose); } /* end namespace openfpga */ diff --git a/openfpga/src/base/openfpga_link_arch_template.h b/openfpga/src/base/openfpga_link_arch_template.h index d9345780c..dc2e04ac4 100644 --- a/openfpga/src/base/openfpga_link_arch_template.h +++ b/openfpga/src/base/openfpga_link_arch_template.h @@ -23,6 +23,7 @@ #include "openfpga_rr_graph_support.h" #include "pb_type_utils.h" #include "read_activity.h" +#include "read_xml_pin_constraints.h" #include "route_clock_rr_graph.h" #include "vpr_device_annotation.h" #include "vtr_assert.h" @@ -214,11 +215,22 @@ int route_clock_rr_graph_template(T& openfpga_ctx, const Command& cmd, const CommandContext& cmd_context) { vtr::ScopedStartFinishTimer timer("Route clock routing resource graph"); + /* add an option '--pin_constraints_file in short '-pcf' */ + CommandOptionId opt_pcf = cmd.option("pin_constraints_file"); CommandOptionId opt_verbose = cmd.option("verbose"); + /* If pin constraints are enabled by command options, read the file */ + PinConstraints pin_constraints; + if (true == cmd_context.option_enable(cmd, opt_pcf)) { + pin_constraints = + read_xml_pin_constraints(cmd_context.option_value(cmd, opt_pcf).c_str()); + } + return route_clock_rr_graph( openfpga_ctx.mutable_vpr_routing_annotation(), g_vpr_ctx.device(), - openfpga_ctx.clock_rr_lookup(), openfpga_ctx.clock_arch(), + g_vpr_ctx.atom(), g_vpr_ctx.clustering().clb_nlist, + openfpga_ctx.vpr_netlist_annotation(), openfpga_ctx.clock_rr_lookup(), + openfpga_ctx.clock_arch(), pin_constraints, cmd_context.option_enable(cmd, opt_verbose)); } diff --git a/openfpga/src/base/openfpga_setup_command_template.h b/openfpga/src/base/openfpga_setup_command_template.h index fe8652344..abe17dfeb 100644 --- a/openfpga/src/base/openfpga_setup_command_template.h +++ b/openfpga/src/base/openfpga_setup_command_template.h @@ -667,6 +667,13 @@ ShellCommandId add_route_clock_rr_graph_command_template( const std::vector& dependent_cmds, const bool& hidden) { Command shell_cmd("route_clock_rr_graph"); + /* Add an option '--file' in short '-f'*/ + CommandOptionId opt_file = + shell_cmd.add_option("pin_constraints_file", false, + "specify the file path to the pin constraints"); + shell_cmd.set_option_short_name(opt_file, "pcf"); + shell_cmd.set_option_require_value(opt_file, openfpga::OPT_STRING); + /* Add an option '--verbose' */ shell_cmd.add_option("verbose", false, "Show verbose outputs"); From 11f09db556c13a984d8dff958f52b134004dc2d3 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 7 Mar 2023 15:05:56 -0800 Subject: [PATCH 089/166] [core] fixed a bug where clock tracks do not pass through at higher level --- openfpga/src/annotation/append_clock_rr_graph.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openfpga/src/annotation/append_clock_rr_graph.cpp b/openfpga/src/annotation/append_clock_rr_graph.cpp index 81159d5bf..e59f19398 100644 --- a/openfpga/src/annotation/append_clock_rr_graph.cpp +++ b/openfpga/src/annotation/append_clock_rr_graph.cpp @@ -515,8 +515,8 @@ static void add_rr_graph_block_clock_edges( size_t(itree), size_t(ilvl), size_t(ipin), DIRECTION_STRING[size_t(node_dir)]); VTR_ASSERT(rr_graph_view.valid_node(src_node)); - if (!clk_ntwk.is_last_level(itree, ilvl)) { - /* find the fan-out clock node through lookup */ + /* find the fan-out clock node through lookup */ + { size_t curr_edge_count = edge_count; for (RRNodeId des_node : find_clock_track2track_node( rr_graph_view, clk_ntwk, clk_rr_lookup, chan_type, From 4bd139977381748ba8385394534032069b6eec68 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 7 Mar 2023 18:41:28 -0800 Subject: [PATCH 090/166] [ci] detect code changes require all the branch and tags when checking out codes --- .github/workflows/build.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 18e795654..f370d1073 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -37,6 +37,8 @@ jobs: - name: Checkout OpenFPGA repo uses: actions/checkout@v2 + with: + fetch-depth: 0 - name: Check for source code changes id: changes From 571a01272438cef000d4a50cd5cb6aaeb1de3491 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 7 Mar 2023 18:47:55 -0800 Subject: [PATCH 091/166] [test] xml format --- openfpga_flow/vpr_arch/k4_N4_tileable_Ntwk1clk2lvl_40nm.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openfpga_flow/vpr_arch/k4_N4_tileable_Ntwk1clk2lvl_40nm.xml b/openfpga_flow/vpr_arch/k4_N4_tileable_Ntwk1clk2lvl_40nm.xml index 61960bb76..231aef08b 100644 --- a/openfpga_flow/vpr_arch/k4_N4_tileable_Ntwk1clk2lvl_40nm.xml +++ b/openfpga_flow/vpr_arch/k4_N4_tileable_Ntwk1clk2lvl_40nm.xml @@ -64,7 +64,7 @@ - + clb.I[0:4] clb.O[0:1] clb.I[5:9] clb.O[2:3] clb.clk From ddc0db490ec51bd6609dfe27b902501d7a860a80 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 7 Mar 2023 20:05:53 -0800 Subject: [PATCH 092/166] [ci] fixed a bug in build commands --- .github/workflows/build.yml | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f370d1073..613391a3b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -130,7 +130,8 @@ jobs: - name: Build shell: bash run: | - make all BUILD_TYPE=$BUILD_TYPE + make checkout + make compile BUILD_TYPE=$BUILD_TYPE # Check the cache size and see if it is over the limit - name: Check ccache size @@ -214,7 +215,8 @@ jobs: - name: Build shell: bash run: | - make all BUILD_TYPE=$BUILD_TYPE CMAKE_FLAGS="${{ matrix.config.cmake_flags }}" + make checkout + make compile BUILD_TYPE=$BUILD_TYPE CMAKE_FLAGS="${{ matrix.config.cmake_flags }}" ubuntu_support: needs: change_detect @@ -255,7 +257,8 @@ jobs: - name: Build shell: bash run: | - make all BUILD_TYPE=$BUILD_TYPE + make checkout + make compile BUILD_TYPE=$BUILD_TYPE debug_build: needs: change_detect @@ -303,7 +306,8 @@ jobs: - name: Build shell: bash run: | - make all BUILD_TYPE=${{ matrix.config.build_type }} -j ${{ matrix.config.cores }} + make checkout + make compile BUILD_TYPE=${{ matrix.config.build_type }} -j ${{ matrix.config.cores }} - name: Quick Test shell: bash @@ -354,7 +358,8 @@ jobs: - name: Build shell: bash run: | - make all BUILD_TYPE=${{ matrix.config.build_type }} -j ${{ matrix.config.cores }} CMAKE_FLAGS="-DOPENFPGA_ENABLE_STRICT_COMPILE=ON" + make checkout + make compile BUILD_TYPE=${{ matrix.config.build_type }} -j ${{ matrix.config.cores }} CMAKE_FLAGS="-DOPENFPGA_ENABLE_STRICT_COMPILE=ON" - name: Quick Test shell: bash From 71acf2905af73156759eaa0256602e0fa27661bd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Mar 2023 06:59:11 +0000 Subject: [PATCH 093/166] Bump yosys-plugins from `24755e3` to `e0a923c` Bumps [yosys-plugins](https://github.com/SymbiFlow/yosys-symbiflow-plugins) from `24755e3` to `e0a923c`. - [Release notes](https://github.com/SymbiFlow/yosys-symbiflow-plugins/releases) - [Commits](https://github.com/SymbiFlow/yosys-symbiflow-plugins/compare/24755e3b43400ad25e90fe01cc764a28a12de999...e0a923cc0bf6b2149994857ba47dc71c5791f227) --- updated-dependencies: - dependency-name: yosys-plugins dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- yosys-plugins | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yosys-plugins b/yosys-plugins index 24755e3b4..e0a923cc0 160000 --- a/yosys-plugins +++ b/yosys-plugins @@ -1 +1 @@ -Subproject commit 24755e3b43400ad25e90fe01cc764a28a12de999 +Subproject commit e0a923cc0bf6b2149994857ba47dc71c5791f227 From 4d37589e867062451f1e65d9bb2cec33bb31b002 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 16 Mar 2023 06:59:11 +0000 Subject: [PATCH 094/166] Bump yosys from `b58664d` to `ceef00c` Bumps [yosys](https://github.com/YosysHQ/yosys) from `b58664d` to `ceef00c`. - [Release notes](https://github.com/YosysHQ/yosys/releases) - [Commits](https://github.com/YosysHQ/yosys/compare/b58664d441764b4de1d01c4efcdd45094ba71535...ceef00c35e6417ba480ae40c3fe919b50e18e1be) --- updated-dependencies: - dependency-name: yosys dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- yosys | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yosys b/yosys index b58664d44..ceef00c35 160000 --- a/yosys +++ b/yosys @@ -1 +1 @@ -Subproject commit b58664d441764b4de1d01c4efcdd45094ba71535 +Subproject commit ceef00c35e6417ba480ae40c3fe919b50e18e1be From 944f782ad76c7a75d493dc2c58348649b6eae365 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 23 Mar 2023 06:58:59 +0000 Subject: [PATCH 095/166] Bump yosys-plugins from `e0a923c` to `0a91e20` Bumps [yosys-plugins](https://github.com/SymbiFlow/yosys-symbiflow-plugins) from `e0a923c` to `0a91e20`. - [Release notes](https://github.com/SymbiFlow/yosys-symbiflow-plugins/releases) - [Commits](https://github.com/SymbiFlow/yosys-symbiflow-plugins/compare/e0a923cc0bf6b2149994857ba47dc71c5791f227...0a91e20154e2e7c0d83e22e09cd570233c74b5d1) --- updated-dependencies: - dependency-name: yosys-plugins dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- yosys-plugins | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yosys-plugins b/yosys-plugins index e0a923cc0..0a91e2015 160000 --- a/yosys-plugins +++ b/yosys-plugins @@ -1 +1 @@ -Subproject commit e0a923cc0bf6b2149994857ba47dc71c5791f227 +Subproject commit 0a91e20154e2e7c0d83e22e09cd570233c74b5d1 From add165f194552191e1bac141140010ae1d7b1451 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 23 Mar 2023 06:59:04 +0000 Subject: [PATCH 096/166] Bump yosys from `ceef00c` to `23826e5` Bumps [yosys](https://github.com/YosysHQ/yosys) from `ceef00c` to `23826e5`. - [Release notes](https://github.com/YosysHQ/yosys/releases) - [Commits](https://github.com/YosysHQ/yosys/compare/ceef00c35e6417ba480ae40c3fe919b50e18e1be...23826e5152483c39a617ee1c696c3b48a0c2b756) --- updated-dependencies: - dependency-name: yosys dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- yosys | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yosys b/yosys index ceef00c35..23826e515 160000 --- a/yosys +++ b/yosys @@ -1 +1 @@ -Subproject commit ceef00c35e6417ba480ae40c3fe919b50e18e1be +Subproject commit 23826e5152483c39a617ee1c696c3b48a0c2b756 From d374ee3614d729c3aedb0675176bbc120e865949 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 24 Mar 2023 00:02:44 +0000 Subject: [PATCH 097/166] Updated Patch Count --- VERSION.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION.md b/VERSION.md index f033f8ae0..7a25b15b9 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -1.2.759 +1.2.773 From 0da0542a3d33fcad88cdbd7384667ca67a01675e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 24 Mar 2023 06:59:09 +0000 Subject: [PATCH 098/166] Bump yosys from `23826e5` to `53c0a6b` Bumps [yosys](https://github.com/YosysHQ/yosys) from `23826e5` to `53c0a6b`. - [Release notes](https://github.com/YosysHQ/yosys/releases) - [Commits](https://github.com/YosysHQ/yosys/compare/23826e5152483c39a617ee1c696c3b48a0c2b756...53c0a6b780199dc56348916acf7c00e30f65e1ec) --- updated-dependencies: - dependency-name: yosys dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- yosys | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yosys b/yosys index 23826e515..53c0a6b78 160000 --- a/yosys +++ b/yosys @@ -1 +1 @@ -Subproject commit 23826e5152483c39a617ee1c696c3b48a0c2b756 +Subproject commit 53c0a6b780199dc56348916acf7c00e30f65e1ec From 4775afa7cca528d35b4f5a24e0ab13699f9bb446 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 29 Mar 2023 00:02:28 +0000 Subject: [PATCH 099/166] Updated Patch Count --- VERSION.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION.md b/VERSION.md index 7a25b15b9..6e0add544 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -1.2.773 +1.2.777 From 13a7b6500079cff011797a10272d7f121a2f00d4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 31 Mar 2023 06:59:08 +0000 Subject: [PATCH 100/166] Bump yosys-plugins from `0a91e20` to `652f82d` Bumps [yosys-plugins](https://github.com/SymbiFlow/yosys-symbiflow-plugins) from `0a91e20` to `652f82d`. - [Release notes](https://github.com/SymbiFlow/yosys-symbiflow-plugins/releases) - [Commits](https://github.com/SymbiFlow/yosys-symbiflow-plugins/compare/0a91e20154e2e7c0d83e22e09cd570233c74b5d1...652f82d692b6353ecd4357b27426400eda37c7a8) --- updated-dependencies: - dependency-name: yosys-plugins dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- yosys-plugins | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yosys-plugins b/yosys-plugins index 0a91e2015..652f82d69 160000 --- a/yosys-plugins +++ b/yosys-plugins @@ -1 +1 @@ -Subproject commit 0a91e20154e2e7c0d83e22e09cd570233c74b5d1 +Subproject commit 652f82d692b6353ecd4357b27426400eda37c7a8 From 3659d5485010f3ec981bee882f7b50e5be38a1d3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 4 Apr 2023 00:02:40 +0000 Subject: [PATCH 101/166] Updated Patch Count --- VERSION.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION.md b/VERSION.md index 6e0add544..d27f691ba 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -1.2.777 +1.2.781 From 89704f074f9f1ce32f52da4ba1f485c9e5e4cd69 Mon Sep 17 00:00:00 2001 From: Yunus Emre ERYILMAZ <30428379+yunuseryilmaz18@users.noreply.github.com> Date: Tue, 4 Apr 2023 14:11:26 +0300 Subject: [PATCH 102/166] Update openfpga.sh The default template for create-task was not updated, I've changed it to ```template_tasks/fabric_netlist_gen_template```. --- openfpga.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openfpga.sh b/openfpga.sh index 8773c3b30..6d2900a11 100755 --- a/openfpga.sh +++ b/openfpga.sh @@ -40,7 +40,7 @@ create-task () { echo "Task $1 already exists" return fi - template="template_tasks/yosys_vpr_template" + template="template_tasks/fabric_netlist_gen_template" if [ ${#2} -ge 1 ]; then if [[ "$2" == "fabric_netlist_gen" ]]; then template="template_tasks/${2}_template/"; elif [[ "$2" == "fabric_verification" ]]; then template="template_tasks/${2}_template/"; From 412743b3029e86dea8996e96d08a42908ff74ad8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 5 Apr 2023 06:59:07 +0000 Subject: [PATCH 103/166] Bump yosys-plugins from `652f82d` to `3bfd401` Bumps [yosys-plugins](https://github.com/SymbiFlow/yosys-symbiflow-plugins) from `652f82d` to `3bfd401`. - [Release notes](https://github.com/SymbiFlow/yosys-symbiflow-plugins/releases) - [Commits](https://github.com/SymbiFlow/yosys-symbiflow-plugins/compare/652f82d692b6353ecd4357b27426400eda37c7a8...3bfd4016e2a4bf32a37dac31ecae40e14e92474c) --- updated-dependencies: - dependency-name: yosys-plugins dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- yosys-plugins | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yosys-plugins b/yosys-plugins index 652f82d69..3bfd4016e 160000 --- a/yosys-plugins +++ b/yosys-plugins @@ -1 +1 @@ -Subproject commit 652f82d692b6353ecd4357b27426400eda37c7a8 +Subproject commit 3bfd4016e2a4bf32a37dac31ecae40e14e92474c From 8218ac160df581f8128bcb9e8a50a570579515fb Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 6 Apr 2023 00:02:33 +0000 Subject: [PATCH 104/166] Updated Patch Count --- VERSION.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION.md b/VERSION.md index d27f691ba..ec65128be 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -1.2.781 +1.2.785 From 2a31b2fa1ac6e076b74f0c0ae1e0a741c7fc5fbc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 7 Apr 2023 06:58:59 +0000 Subject: [PATCH 105/166] Bump yosys from `53c0a6b` to `1010756` Bumps [yosys](https://github.com/YosysHQ/yosys) from `53c0a6b` to `1010756`. - [Release notes](https://github.com/YosysHQ/yosys/releases) - [Commits](https://github.com/YosysHQ/yosys/compare/53c0a6b780199dc56348916acf7c00e30f65e1ec...101075611fc5698739180017bf96b1abf140c8e7) --- updated-dependencies: - dependency-name: yosys dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- yosys | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yosys b/yosys index 53c0a6b78..101075611 160000 --- a/yosys +++ b/yosys @@ -1 +1 @@ -Subproject commit 53c0a6b780199dc56348916acf7c00e30f65e1ec +Subproject commit 101075611fc5698739180017bf96b1abf140c8e7 From f89c29efee0f7da7287c7e2034c5ddf7ac401524 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Apr 2023 07:00:27 +0000 Subject: [PATCH 106/166] Bump yosys-plugins from `3bfd401` to `794ff73` Bumps [yosys-plugins](https://github.com/SymbiFlow/yosys-symbiflow-plugins) from `3bfd401` to `794ff73`. - [Release notes](https://github.com/SymbiFlow/yosys-symbiflow-plugins/releases) - [Commits](https://github.com/SymbiFlow/yosys-symbiflow-plugins/compare/3bfd4016e2a4bf32a37dac31ecae40e14e92474c...794ff73e432515eabe95a73e127f45cf7db0a04c) --- updated-dependencies: - dependency-name: yosys-plugins dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- yosys-plugins | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yosys-plugins b/yosys-plugins index 3bfd4016e..794ff73e4 160000 --- a/yosys-plugins +++ b/yosys-plugins @@ -1 +1 @@ -Subproject commit 3bfd4016e2a4bf32a37dac31ecae40e14e92474c +Subproject commit 794ff73e432515eabe95a73e127f45cf7db0a04c From da8d01a22b9ea822469d3cf39005a81102c03356 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 11 Apr 2023 00:02:59 +0000 Subject: [PATCH 107/166] Updated Patch Count --- VERSION.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION.md b/VERSION.md index ec65128be..f0e03a21f 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -1.2.785 +1.2.793 From 76e497607f517b14c9bc94fa909f05752f78c833 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Apr 2023 07:00:11 +0000 Subject: [PATCH 108/166] Bump yosys from `1010756` to `a9c792d` Bumps [yosys](https://github.com/YosysHQ/yosys) from `1010756` to `a9c792d`. - [Release notes](https://github.com/YosysHQ/yosys/releases) - [Commits](https://github.com/YosysHQ/yosys/compare/101075611fc5698739180017bf96b1abf140c8e7...a9c792dceef4be21059ff4732d1aff62e67d96bc) --- updated-dependencies: - dependency-name: yosys dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- yosys | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yosys b/yosys index 101075611..a9c792dce 160000 --- a/yosys +++ b/yosys @@ -1 +1 @@ -Subproject commit 101075611fc5698739180017bf96b1abf140c8e7 +Subproject commit a9c792dceef4be21059ff4732d1aff62e67d96bc From a4dc8cd98f6cca8228ed8ef923fab5546a166c0e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 18 Apr 2023 06:58:49 +0000 Subject: [PATCH 109/166] Bump yosys-plugins from `794ff73` to `96a0853` Bumps [yosys-plugins](https://github.com/SymbiFlow/yosys-symbiflow-plugins) from `794ff73` to `96a0853`. - [Release notes](https://github.com/SymbiFlow/yosys-symbiflow-plugins/releases) - [Commits](https://github.com/SymbiFlow/yosys-symbiflow-plugins/compare/794ff73e432515eabe95a73e127f45cf7db0a04c...96a0853eba5691f54a5e0bfc044d847743e09cef) --- updated-dependencies: - dependency-name: yosys-plugins dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- yosys-plugins | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yosys-plugins b/yosys-plugins index 794ff73e4..96a0853eb 160000 --- a/yosys-plugins +++ b/yosys-plugins @@ -1 +1 @@ -Subproject commit 794ff73e432515eabe95a73e127f45cf7db0a04c +Subproject commit 96a0853eba5691f54a5e0bfc044d847743e09cef From 817015f7b6ff6aab3094c9c6dccb76b6b8b85cd5 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 18 Apr 2023 16:46:43 +0800 Subject: [PATCH 110/166] [core] update vtr --- vtr-verilog-to-routing | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vtr-verilog-to-routing b/vtr-verilog-to-routing index 9e53e9a0a..d70659f42 160000 --- a/vtr-verilog-to-routing +++ b/vtr-verilog-to-routing @@ -1 +1 @@ -Subproject commit 9e53e9a0a7c18ba9a16ea08678da726b98c669d4 +Subproject commit d70659f424425dbaa6ecdb6dea40bf1841f02dac From 7f96d98083e6ccc747f366dca0d5d22de65585e5 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 18 Apr 2023 16:49:31 +0800 Subject: [PATCH 111/166] [ci] now git checkout does not download submodule; It is done by make checkout --- .github/workflows/build.yml | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e5223f0fe..505dd7fa2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -37,9 +37,7 @@ jobs: - name: Checkout OpenFPGA repo uses: actions/checkout@v2 - with: - fetch-depth: 0 - submodules: true + - name: Check for source code changes id: changes run: | @@ -115,8 +113,6 @@ jobs: - name: Checkout OpenFPGA repo uses: actions/checkout@v2 - with: - submodules: true - name: Install dependencies run: sudo bash ./.github/workflows/install_dependencies_build.sh @@ -201,8 +197,6 @@ jobs: - name: Checkout OpenFPGA repo uses: actions/checkout@v2 - with: - submodules: true - name: Install dependencies run: sudo bash ./.github/workflows/install_dependencies_build.sh @@ -244,8 +238,6 @@ jobs: - name: Checkout OpenFPGA repo uses: actions/checkout@v2 - with: - submodules: true - name: Install dependencies run: sudo bash ./.github/workflows/install_dependencies_build_ubuntu22p04.sh @@ -291,8 +283,6 @@ jobs: - name: Checkout OpenFPGA repo uses: actions/checkout@v2 - with: - submodules: true - name: Install dependencies run: | @@ -344,8 +334,6 @@ jobs: - name: Checkout OpenFPGA repo uses: actions/checkout@v2 - with: - submodules: true - name: Install dependencies run: | @@ -494,8 +482,7 @@ jobs: - name: Checkout OpenFPGA repo uses: actions/checkout@v2 - with: - submodules: true + - name: ${{matrix.config.name}}_GCC-8_(Ubuntu 20.04) shell: bash run: | From ae46442e8c8901946cdad5ff6aa012c19e1379c2 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 18 Apr 2023 16:52:20 +0800 Subject: [PATCH 112/166] [script] now make checkout only checkout submodule by 1 depth --- Makefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 9774e7863..49f6a0a73 100644 --- a/Makefile +++ b/Makefile @@ -58,7 +58,7 @@ help: checkout: # Update all the submodules git submodule init - git submodule update --init --recursive + git submodule update --init --depth 1 prebuild: # Run cmake to generate Makefile under the build directory, before compilation @@ -79,8 +79,9 @@ list_cmake_targets: prebuild # Show the targets available to be built, which can be specified through ``CMAKE_GOALS`` when compile cd ${BUILD_DIR} && make help && cd - -all: checkout compile +all: checkout # A shortcut command to run checkout and compile in serial + make compile CMAKE_GOALS=${CMAKE_GOALS} format-cpp: # Format all the C/C++ files under this project, excluding submodules From 9e50b2d923d5f1812e891a2715fb1a30d13d96fd Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 18 Apr 2023 17:13:21 +0800 Subject: [PATCH 113/166] [ci] disable checkout submodules for cell library tests --- .github/workflows/cell_lib_test.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/cell_lib_test.yml b/.github/workflows/cell_lib_test.yml index 5016297d5..9825fddfc 100644 --- a/.github/workflows/cell_lib_test.yml +++ b/.github/workflows/cell_lib_test.yml @@ -22,8 +22,6 @@ jobs: - name: Checkout OpenFPGA repo uses: actions/checkout@v2 - with: - submodules: true - name: Install Dependencies run: | From 691a6b2b734e5ff7d2327cda3926ea6dac8693fe Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 18 Apr 2023 17:19:07 +0800 Subject: [PATCH 114/166] [ci] now checkout all the branches and tags when detecting code changes --- .github/workflows/build.yml | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 505dd7fa2..e0cd7bc71 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -36,7 +36,9 @@ jobs: access_token: ${{ github.token }} - name: Checkout OpenFPGA repo - uses: actions/checkout@v2 + uses: actions/checkout@v3 + with: + fetch-depth: 0 - name: Check for source code changes id: changes @@ -112,7 +114,7 @@ jobs: access_token: ${{ github.token }} - name: Checkout OpenFPGA repo - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Install dependencies run: sudo bash ./.github/workflows/install_dependencies_build.sh @@ -196,7 +198,7 @@ jobs: access_token: ${{ github.token }} - name: Checkout OpenFPGA repo - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Install dependencies run: sudo bash ./.github/workflows/install_dependencies_build.sh @@ -237,7 +239,7 @@ jobs: access_token: ${{ github.token }} - name: Checkout OpenFPGA repo - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Install dependencies run: sudo bash ./.github/workflows/install_dependencies_build_ubuntu22p04.sh @@ -282,7 +284,7 @@ jobs: access_token: ${{ github.token }} - name: Checkout OpenFPGA repo - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Install dependencies run: | @@ -333,7 +335,7 @@ jobs: access_token: ${{ github.token }} - name: Checkout OpenFPGA repo - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Install dependencies run: | @@ -370,7 +372,7 @@ jobs: access_token: ${{ github.token }} - name: Checkout OpenFPGA repo - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Download a built artifacts uses: actions/download-artifact@v2 with: @@ -423,7 +425,7 @@ jobs: access_token: ${{ github.token }} - name: Checkout OpenFPGA repo - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Download a built artifacts uses: actions/download-artifact@v2 with: @@ -481,7 +483,7 @@ jobs: access_token: ${{ github.token }} - name: Checkout OpenFPGA repo - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: ${{matrix.config.name}}_GCC-8_(Ubuntu 20.04) shell: bash From 3780ca5150ed932d13cd24aaaa5a3c688cfb3b09 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 18 Apr 2023 17:20:39 +0800 Subject: [PATCH 115/166] [ci] now all use checkout v3 --- .github/workflows/cell_lib_test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cell_lib_test.yml b/.github/workflows/cell_lib_test.yml index 9825fddfc..619dc5251 100644 --- a/.github/workflows/cell_lib_test.yml +++ b/.github/workflows/cell_lib_test.yml @@ -21,7 +21,7 @@ jobs: access_token: ${{ github.token }} - name: Checkout OpenFPGA repo - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Install Dependencies run: | From ffca43266fe6350fdcc221e33332732e4783f7c6 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 18 Apr 2023 17:35:59 +0800 Subject: [PATCH 116/166] [script] now disable yosys and parmys in vtr --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 35a2296c7..c3fc2cce6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,8 +81,10 @@ set(ODIN_COVERAGE OFF CACHE BOOL "Enable building odin with coverage flags in Ve set(ODIN_TIDY OFF CACHE BOOL "Enable building odin with clang tidy in Verilog-to-Routing") set(ODIN_SANITIZE OFF CACHE BOOL "Enable building odin with sanitize flags in Verilog-to-Routing") set(WITH_YOSYS OFF CACHE BOOL "Enable building Yosys in Verilog-to-Routing") +set(WITH_PARMYS OFF CACHE BOOL "Enable Yosys as elaborator and parmys-plugin as partial mapper") set(ODIN_YOSYS OFF CACHE BOOL "Enable building odin with yosys in Verilog-to-Routing") set(YOSYS_SV_UHDM_PLUGIN OFF CACHE BOOL "Enable building and installing Yosys SystemVerilog and UHDM plugins in Verilog-to-Routing") +set(YOSYS_F4PGA_PLUGINS OFF CACHE BOOL "Enable building and installing Yosys SystemVerilog and UHDM plugins") set(VTR_ENABLE_VERSION ${OPENFPGA_WITH_VERSION} CACHE BOOL "Enable version always-up-to-date when building codebase. Disable only when you do not care an accurate version number") # TODO: OpenFPGA and VPR has different requirements on no-warning build, e.g., on OS and compiler versions #set(VTR_ENABLE_STRICT_COMPILE ${OPENFPGA_ENABLE_STRICT_COMPILE} CACHE BOOL "Specifies whether compiler warnings should be treated as errors (e.g. -Werror)") From 929b296ad3c1ac366831840c13a28b3ba025cf4b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 19 Apr 2023 00:02:18 +0000 Subject: [PATCH 117/166] Updated Patch Count --- VERSION.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION.md b/VERSION.md index f0e03a21f..48688bac6 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -1.2.793 +1.2.799 From a84cc52d7c7d7a7ee9072c62ff76b8c86e5c3ae8 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 19 Apr 2023 11:08:18 +0800 Subject: [PATCH 118/166] [core] fixed a few bugs due to the changes in vtr regarding flat router --- .../annotation/annotate_simulation_setting.cpp | 8 ++++---- .../annotation/openfpga_annotate_routing.cpp | 6 +++--- openfpga/src/vpr_wrapper/vpr_main.cpp | 18 +++++++++++------- 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/openfpga/src/annotation/annotate_simulation_setting.cpp b/openfpga/src/annotation/annotate_simulation_setting.cpp index a3d489efe..08a06c2be 100644 --- a/openfpga/src/annotation/annotate_simulation_setting.cpp +++ b/openfpga/src/annotation/annotate_simulation_setting.cpp @@ -208,14 +208,14 @@ int annotate_simulation_setting( * - MUST mention in documentation that VPR should be run in timing * enabled mode */ - ClbNetPinsMatrix net_delay = - make_net_pins_matrix(cluster_ctx.clb_nlist); + NetPinsMatrix net_delay = + make_net_pins_matrix((const Netlist<>&)cluster_ctx.clb_nlist); /* Load the net delays */ - load_net_delay_from_routing(net_delay); + load_net_delay_from_routing((const Netlist<>&)cluster_ctx.clb_nlist, net_delay, false); /* Do final timing analysis */ auto analysis_delay_calc = std::make_shared( - atom_ctx.nlist, atom_ctx.lookup, net_delay); + atom_ctx.nlist, atom_ctx.lookup, net_delay, false); auto timing_info = make_setup_hold_timing_info(analysis_delay_calc, e_timing_update_type::FULL); timing_info->update(); diff --git a/openfpga/src/annotation/openfpga_annotate_routing.cpp b/openfpga/src/annotation/openfpga_annotate_routing.cpp index 577106359..f5389f324 100644 --- a/openfpga/src/annotation/openfpga_annotate_routing.cpp +++ b/openfpga/src/annotation/openfpga_annotate_routing.cpp @@ -22,12 +22,12 @@ void annotate_vpr_rr_node_nets(const DeviceContext& device_ctx, const RoutingContext& routing_ctx, VprRoutingAnnotation& vpr_routing_annotation, const bool& verbose) { - vtr::vector node2net = annotate_rr_node_nets( - device_ctx, clustering_ctx, routing_ctx, verbose, false); + vtr::vector node2net = annotate_rr_node_nets( + (const Netlist<>&)clustering_ctx.clb_nlist, device_ctx, routing_ctx, verbose, false); for (size_t node_id = 0; node_id < device_ctx.rr_graph.num_nodes(); ++node_id) { vpr_routing_annotation.set_rr_node_net(RRNodeId(node_id), - node2net[RRNodeId(node_id)]); + convert_to_cluster_net_id(node2net[RRNodeId(node_id)])); } VTR_LOG("Loaded node-to-net mapping\n"); } diff --git a/openfpga/src/vpr_wrapper/vpr_main.cpp b/openfpga/src/vpr_wrapper/vpr_main.cpp index cc6924b49..10b7a9ccd 100644 --- a/openfpga/src/vpr_wrapper/vpr_main.cpp +++ b/openfpga/src/vpr_wrapper/vpr_main.cpp @@ -118,16 +118,17 @@ static int vpr_standalone(int argc, char** argv) { /* Read options, architecture, and circuit netlist */ vpr_init(argc, const_cast(argv), &Options, &vpr_setup, &Arch); + const Netlist<>& net_list = vpr_setup.RouterOpts.flat_routing ? (const Netlist<>&)g_vpr_ctx.atom().nlist : (const Netlist<>&)g_vpr_ctx.clustering().clb_nlist; if (Options.show_version) { - vpr_free_all(Arch, vpr_setup); + vpr_free_all(net_list, Arch, vpr_setup); return SUCCESS_EXIT_CODE; } bool flow_succeeded = vpr_flow(vpr_setup, Arch); if (!flow_succeeded) { VTR_LOG("VPR failed to implement circuit\n"); - vpr_free_all(Arch, vpr_setup); + vpr_free_all(net_list, Arch, vpr_setup); return UNIMPLEMENTABLE_EXIT_CODE; } @@ -135,31 +136,34 @@ static int vpr_standalone(int argc, char** argv) { print_timing_stats("Flow", timing_ctx.stats); /* free data structures */ - vpr_free_all(Arch, vpr_setup); + vpr_free_all(net_list, Arch, vpr_setup); VTR_LOG("VPR succeeded\n"); } catch (const tatum::Error& tatum_error) { VTR_LOG_ERROR("%s\n", format_tatum_error(tatum_error).c_str()); - vpr_free_all(Arch, vpr_setup); + const Netlist<>& net_list = vpr_setup.RouterOpts.flat_routing ? (const Netlist<>&)g_vpr_ctx.atom().nlist : (const Netlist<>&)g_vpr_ctx.clustering().clb_nlist; + vpr_free_all(net_list, Arch, vpr_setup); return ERROR_EXIT_CODE; } catch (const VprError& vpr_error) { vpr_print_error(vpr_error); + const Netlist<>& net_list = vpr_setup.RouterOpts.flat_routing ? (const Netlist<>&)g_vpr_ctx.atom().nlist : (const Netlist<>&)g_vpr_ctx.clustering().clb_nlist; if (vpr_error.type() == VPR_ERROR_INTERRUPTED) { - vpr_free_all(Arch, vpr_setup); + vpr_free_all(net_list, Arch, vpr_setup); return INTERRUPTED_EXIT_CODE; } else { - vpr_free_all(Arch, vpr_setup); + vpr_free_all(net_list, Arch, vpr_setup); return ERROR_EXIT_CODE; } } catch (const vtr::VtrError& vtr_error) { VTR_LOG_ERROR("%s:%d %s\n", vtr_error.filename_c_str(), vtr_error.line(), vtr_error.what()); - vpr_free_all(Arch, vpr_setup); + const Netlist<>& net_list = vpr_setup.RouterOpts.flat_routing ? (const Netlist<>&)g_vpr_ctx.atom().nlist : (const Netlist<>&)g_vpr_ctx.clustering().clb_nlist; + vpr_free_all(net_list, Arch, vpr_setup); return ERROR_EXIT_CODE; } From cb4512b9255962dd0cd1c0c7b3956de00a6a89e4 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 19 Apr 2023 11:10:42 +0800 Subject: [PATCH 119/166] [core] code format --- .../annotate_simulation_setting.cpp | 3 ++- .../annotation/openfpga_annotate_routing.cpp | 10 ++++++---- openfpga/src/vpr_wrapper/vpr_main.cpp | 20 +++++++++++++++---- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/openfpga/src/annotation/annotate_simulation_setting.cpp b/openfpga/src/annotation/annotate_simulation_setting.cpp index 08a06c2be..3c3c7b3ee 100644 --- a/openfpga/src/annotation/annotate_simulation_setting.cpp +++ b/openfpga/src/annotation/annotate_simulation_setting.cpp @@ -211,7 +211,8 @@ int annotate_simulation_setting( NetPinsMatrix net_delay = make_net_pins_matrix((const Netlist<>&)cluster_ctx.clb_nlist); /* Load the net delays */ - load_net_delay_from_routing((const Netlist<>&)cluster_ctx.clb_nlist, net_delay, false); + load_net_delay_from_routing((const Netlist<>&)cluster_ctx.clb_nlist, + net_delay, false); /* Do final timing analysis */ auto analysis_delay_calc = std::make_shared( diff --git a/openfpga/src/annotation/openfpga_annotate_routing.cpp b/openfpga/src/annotation/openfpga_annotate_routing.cpp index f5389f324..6c5327e04 100644 --- a/openfpga/src/annotation/openfpga_annotate_routing.cpp +++ b/openfpga/src/annotation/openfpga_annotate_routing.cpp @@ -22,12 +22,14 @@ void annotate_vpr_rr_node_nets(const DeviceContext& device_ctx, const RoutingContext& routing_ctx, VprRoutingAnnotation& vpr_routing_annotation, const bool& verbose) { - vtr::vector node2net = annotate_rr_node_nets( - (const Netlist<>&)clustering_ctx.clb_nlist, device_ctx, routing_ctx, verbose, false); + vtr::vector node2net = + annotate_rr_node_nets((const Netlist<>&)clustering_ctx.clb_nlist, + device_ctx, routing_ctx, verbose, false); for (size_t node_id = 0; node_id < device_ctx.rr_graph.num_nodes(); ++node_id) { - vpr_routing_annotation.set_rr_node_net(RRNodeId(node_id), - convert_to_cluster_net_id(node2net[RRNodeId(node_id)])); + vpr_routing_annotation.set_rr_node_net( + RRNodeId(node_id), + convert_to_cluster_net_id(node2net[RRNodeId(node_id)])); } VTR_LOG("Loaded node-to-net mapping\n"); } diff --git a/openfpga/src/vpr_wrapper/vpr_main.cpp b/openfpga/src/vpr_wrapper/vpr_main.cpp index 10b7a9ccd..e9b5d563a 100644 --- a/openfpga/src/vpr_wrapper/vpr_main.cpp +++ b/openfpga/src/vpr_wrapper/vpr_main.cpp @@ -118,7 +118,10 @@ static int vpr_standalone(int argc, char** argv) { /* Read options, architecture, and circuit netlist */ vpr_init(argc, const_cast(argv), &Options, &vpr_setup, &Arch); - const Netlist<>& net_list = vpr_setup.RouterOpts.flat_routing ? (const Netlist<>&)g_vpr_ctx.atom().nlist : (const Netlist<>&)g_vpr_ctx.clustering().clb_nlist; + const Netlist<>& net_list = + vpr_setup.RouterOpts.flat_routing + ? (const Netlist<>&)g_vpr_ctx.atom().nlist + : (const Netlist<>&)g_vpr_ctx.clustering().clb_nlist; if (Options.show_version) { vpr_free_all(net_list, Arch, vpr_setup); @@ -142,14 +145,20 @@ static int vpr_standalone(int argc, char** argv) { } catch (const tatum::Error& tatum_error) { VTR_LOG_ERROR("%s\n", format_tatum_error(tatum_error).c_str()); - const Netlist<>& net_list = vpr_setup.RouterOpts.flat_routing ? (const Netlist<>&)g_vpr_ctx.atom().nlist : (const Netlist<>&)g_vpr_ctx.clustering().clb_nlist; + const Netlist<>& net_list = + vpr_setup.RouterOpts.flat_routing + ? (const Netlist<>&)g_vpr_ctx.atom().nlist + : (const Netlist<>&)g_vpr_ctx.clustering().clb_nlist; vpr_free_all(net_list, Arch, vpr_setup); return ERROR_EXIT_CODE; } catch (const VprError& vpr_error) { vpr_print_error(vpr_error); - const Netlist<>& net_list = vpr_setup.RouterOpts.flat_routing ? (const Netlist<>&)g_vpr_ctx.atom().nlist : (const Netlist<>&)g_vpr_ctx.clustering().clb_nlist; + const Netlist<>& net_list = + vpr_setup.RouterOpts.flat_routing + ? (const Netlist<>&)g_vpr_ctx.atom().nlist + : (const Netlist<>&)g_vpr_ctx.clustering().clb_nlist; if (vpr_error.type() == VPR_ERROR_INTERRUPTED) { vpr_free_all(net_list, Arch, vpr_setup); @@ -162,7 +171,10 @@ static int vpr_standalone(int argc, char** argv) { } catch (const vtr::VtrError& vtr_error) { VTR_LOG_ERROR("%s:%d %s\n", vtr_error.filename_c_str(), vtr_error.line(), vtr_error.what()); - const Netlist<>& net_list = vpr_setup.RouterOpts.flat_routing ? (const Netlist<>&)g_vpr_ctx.atom().nlist : (const Netlist<>&)g_vpr_ctx.clustering().clb_nlist; + const Netlist<>& net_list = + vpr_setup.RouterOpts.flat_routing + ? (const Netlist<>&)g_vpr_ctx.atom().nlist + : (const Netlist<>&)g_vpr_ctx.clustering().clb_nlist; vpr_free_all(net_list, Arch, vpr_setup); return ERROR_EXIT_CODE; From c7203cd6e6d6f7ae88a7b43e141cdee538d81ebe Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 19 Apr 2023 11:11:24 +0800 Subject: [PATCH 120/166] [script] revert back the old make all recipe --- Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 49f6a0a73..db960eb5b 100644 --- a/Makefile +++ b/Makefile @@ -79,9 +79,8 @@ list_cmake_targets: prebuild # Show the targets available to be built, which can be specified through ``CMAKE_GOALS`` when compile cd ${BUILD_DIR} && make help && cd - -all: checkout +all: checkout compile # A shortcut command to run checkout and compile in serial - make compile CMAKE_GOALS=${CMAKE_GOALS} format-cpp: # Format all the C/C++ files under this project, excluding submodules From 7d13faffe9e82653cb38560c804f2eca1f0b25ab Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 19 Apr 2023 11:19:27 +0800 Subject: [PATCH 121/166] [script] now split make checkout and make compile --- .github/workflows/build.yml | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e0cd7bc71..4017fcaf5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -127,10 +127,15 @@ jobs: - uses: hendrikmuhs/ccache-action@v1 + - name: checkout submodules + shell: bash + run: | + make checkout + - name: Build shell: bash run: | - make all BUILD_TYPE=$BUILD_TYPE + make compile BUILD_TYPE=$BUILD_TYPE # Check the cache size and see if it is over the limit - name: Check ccache size @@ -211,10 +216,15 @@ jobs: - uses: hendrikmuhs/ccache-action@v1 + - name: checkout submodules + shell: bash + run: | + make checkout + - name: Build shell: bash run: | - make all BUILD_TYPE=$BUILD_TYPE CMAKE_FLAGS="${{ matrix.config.cmake_flags }}" + make compile BUILD_TYPE=$BUILD_TYPE CMAKE_FLAGS="${{ matrix.config.cmake_flags }}" ubuntu_support: needs: change_detect @@ -252,10 +262,15 @@ jobs: - uses: hendrikmuhs/ccache-action@v1 + - name: checkout submodules + shell: bash + run: | + make checkout + - name: Build shell: bash run: | - make all BUILD_TYPE=$BUILD_TYPE + make compile BUILD_TYPE=$BUILD_TYPE debug_build: needs: change_detect @@ -300,10 +315,15 @@ jobs: - uses: hendrikmuhs/ccache-action@v1 + - name: checkout submodules + shell: bash + run: | + make checkout + - name: Build shell: bash run: | - make all BUILD_TYPE=${{ matrix.config.build_type }} -j ${{ matrix.config.cores }} + make compile BUILD_TYPE=${{ matrix.config.build_type }} -j ${{ matrix.config.cores }} - name: Quick Test shell: bash @@ -351,10 +371,15 @@ jobs: - uses: hendrikmuhs/ccache-action@v1 + - name: checkout submodules + shell: bash + run: | + make checkout + - name: Build shell: bash run: | - make all BUILD_TYPE=${{ matrix.config.build_type }} -j ${{ matrix.config.cores }} CMAKE_FLAGS="-DOPENFPGA_ENABLE_STRICT_COMPILE=ON" + make compile BUILD_TYPE=${{ matrix.config.build_type }} -j ${{ matrix.config.cores }} CMAKE_FLAGS="-DOPENFPGA_ENABLE_STRICT_COMPILE=ON" - name: Quick Test shell: bash From 9690cea1154417c0c7d905d9cebe968828229aaf Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 19 Apr 2023 15:46:42 +0800 Subject: [PATCH 122/166] [core] fix clang syntax --- openfpga/src/mux_lib/mux_library_builder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openfpga/src/mux_lib/mux_library_builder.cpp b/openfpga/src/mux_lib/mux_library_builder.cpp index add2acf53..9ef612784 100644 --- a/openfpga/src/mux_lib/mux_library_builder.cpp +++ b/openfpga/src/mux_lib/mux_library_builder.cpp @@ -56,7 +56,7 @@ static void build_routing_arch_mux_library( if (CircuitModelId::INVALID() == rr_switch_circuit_model) { VTR_LOG_ERROR( "Unable to find the circuit model for rr_switch '%s'!\n", - rr_graph.rr_switch_inf(driver_switches[0]).name); + rr_graph.rr_switch_inf(driver_switches[0]).name.c_str()); VTR_LOG("Node type: %s\n", rr_graph.node_type_string(node)); VTR_LOG("Node coordinate: %s\n", rr_graph.node_coordinate_to_string(node).c_str()); From 87b3f9d828436a259eaf36c293029c6d6deb253d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 20 Apr 2023 00:02:33 +0000 Subject: [PATCH 123/166] Updated Patch Count --- VERSION.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION.md b/VERSION.md index 48688bac6..ff8e40899 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -1.2.799 +1.2.815 From 1f9c1fe7e1f508e7d2c7fbed54958ee90f31b8b9 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 20 Apr 2023 10:31:22 +0800 Subject: [PATCH 124/166] [test] clean up clock network task config --- .../homo_1clock_2layer/config/task.conf | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/openfpga_flow/tasks/basic_tests/clock_network/homo_1clock_2layer/config/task.conf b/openfpga_flow/tasks/basic_tests/clock_network/homo_1clock_2layer/config/task.conf index d88210133..a92fa5fef 100644 --- a/openfpga_flow/tasks/basic_tests/clock_network/homo_1clock_2layer/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/clock_network/homo_1clock_2layer/config/task.conf @@ -27,20 +27,11 @@ openfpga_vpr_route_chan_width=24 arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_Ntwk1clk2lvl_40nm.xml [BENCHMARKS] -#bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v -#bench1=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/or2/or2.v -bench2=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2_latch/and2_latch.v +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2_latch/and2_latch.v [SYNTHESIS_PARAM] bench_read_verilog_options_common = -nolatches -bench0_top = and2 -bench0_chan_width = 300 - -bench1_top = or2 -bench1_chan_width = 300 - -bench2_top = and2_latch -bench2_chan_width = 300 +bench0_top = and2_latch [SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] end_flow_with_test= From 7d333b36693aad6f8ef2285acef65da201c37d34 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 20 Apr 2023 10:36:08 +0800 Subject: [PATCH 125/166] [test] add a new test for clock network: validate full testbench is working --- .../example_clkntwk_full_tb_script.openfpga | 73 +++++++++++++++++++ .../regression_test_scripts/basic_reg_test.sh | 1 + .../config/clk_arch_1clk_2layer.xml | 17 +++++ .../config/task.conf | 37 ++++++++++ 4 files changed, 128 insertions(+) create mode 100644 openfpga_flow/openfpga_shell_scripts/example_clkntwk_full_tb_script.openfpga create mode 100644 openfpga_flow/tasks/basic_tests/clock_network/homo_1clock_2layer_full_tb/config/clk_arch_1clk_2layer.xml create mode 100644 openfpga_flow/tasks/basic_tests/clock_network/homo_1clock_2layer_full_tb/config/task.conf diff --git a/openfpga_flow/openfpga_shell_scripts/example_clkntwk_full_tb_script.openfpga b/openfpga_flow/openfpga_shell_scripts/example_clkntwk_full_tb_script.openfpga new file mode 100644 index 000000000..92cd639ca --- /dev/null +++ b/openfpga_flow/openfpga_shell_scripts/example_clkntwk_full_tb_script.openfpga @@ -0,0 +1,73 @@ +# Run VPR for the 'and' design +#--write_rr_graph example_rr_graph.xml +vpr ${VPR_ARCH_FILE} ${VPR_TESTBENCH_BLIF} \ + --clock_modeling ideal \ + --device ${OPENFPGA_VPR_DEVICE_LAYOUT} \ + --route_chan_width ${OPENFPGA_VPR_ROUTE_CHAN_WIDTH} + +# Read OpenFPGA architecture definition +read_openfpga_arch -f ${OPENFPGA_ARCH_FILE} + +# Read OpenFPGA simulation settings +read_openfpga_simulation_setting -f ${OPENFPGA_SIM_SETTING_FILE} + +# Read OpenFPGA clock architecture +read_openfpga_clock_arch -f ${OPENFPGA_CLOCK_ARCH_FILE} + +# Append clock network to vpr's routing resource graph +append_clock_rr_graph + +# Annotate the OpenFPGA architecture to VPR data base +# to debug use --verbose options +link_openfpga_arch --activity_file ${ACTIVITY_FILE} --sort_gsb_chan_node_in_edges + +# Route clock based on clock network definition +route_clock_rr_graph + +# Check and correct any naming conflicts in the BLIF netlist +check_netlist_naming_conflict --fix --report ./netlist_renaming.xml + +# Apply fix-up to Look-Up Table truth tables based on packing results +lut_truth_table_fixup + +# Build the module graph +# - Enabled compression on routing architecture modules +# - Enable pin duplication on grid modules +build_fabric --compress_routing #--verbose + +# Write the fabric hierarchy of module graph to a file +# This is used by hierarchical PnR flows +write_fabric_hierarchy --file ./fabric_hierarchy.txt + +# Repack the netlist to physical pbs +# This must be done before bitstream generator and testbench generation +# Strongly recommend it is done after all the fix-up have been applied +repack #--verbose + +# Build the bitstream +# - Output the fabric-independent bitstream to a file +build_architecture_bitstream --verbose --write_file fabric_independent_bitstream.xml + +# Build fabric-dependent bitstream +build_fabric_bitstream --verbose + +# Write fabric-dependent bitstream +write_fabric_bitstream --file fabric_bitstream.bit --format plain_text + +# Write the Verilog netlist for FPGA fabric +# - Enable the use of explicit port mapping in Verilog netlist +write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --print_user_defined_template --verbose + +# Write the Verilog testbench for FPGA fabric +# - We suggest the use of same output directory as fabric Verilog netlists +# - Must specify the reference benchmark file if you want to output any testbenches +# - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA +# - Enable pre-configured top-level testbench which is a fast verification skipping programming phase +# - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init --bitstream fabric_bitstream.bit + +# Finish and exit OpenFPGA +exit + +# Note : +# To run verification at the end of the flow maintain source in ./SRC directory diff --git a/openfpga_flow/regression_test_scripts/basic_reg_test.sh b/openfpga_flow/regression_test_scripts/basic_reg_test.sh index 848941b69..248f779f5 100755 --- a/openfpga_flow/regression_test_scripts/basic_reg_test.sh +++ b/openfpga_flow/regression_test_scripts/basic_reg_test.sh @@ -165,6 +165,7 @@ run-task basic_tests/global_tile_ports/global_tile_4clock_pin $@ echo -e "Testing programmable clock architecture"; run-task basic_tests/clock_network/homo_1clock_2layer $@ +run-task basic_tests/clock_network/homo_1clock_2layer_full_tb $@ echo -e "Testing configuration chain of a K4N4 FPGA using .blif generated by yosys+verific"; run-task basic_tests/verific_test $@ diff --git a/openfpga_flow/tasks/basic_tests/clock_network/homo_1clock_2layer_full_tb/config/clk_arch_1clk_2layer.xml b/openfpga_flow/tasks/basic_tests/clock_network/homo_1clock_2layer_full_tb/config/clk_arch_1clk_2layer.xml new file mode 100644 index 000000000..0570406fd --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/clock_network/homo_1clock_2layer_full_tb/config/clk_arch_1clk_2layer.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/openfpga_flow/tasks/basic_tests/clock_network/homo_1clock_2layer_full_tb/config/task.conf b/openfpga_flow/tasks/basic_tests/clock_network/homo_1clock_2layer_full_tb/config/task.conf new file mode 100644 index 000000000..ef0ce93fd --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/clock_network/homo_1clock_2layer_full_tb/config/task.conf @@ -0,0 +1,37 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = true +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=yosys_vpr + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/example_clkntwk_full_tb_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_Ntwk1clk2lvl_cc_openfpga.xml +openfpga_clock_arch_file=${PATH:TASK_DIR}/config/clk_arch_1clk_2layer.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout=2x2 +openfpga_vpr_route_chan_width=24 + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_Ntwk1clk2lvl_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2_latch/and2_latch.v + +[SYNTHESIS_PARAM] +bench_read_verilog_options_common = -nolatches +bench0_top = and2_latch + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= From 03cb664049476ed2369b583cdd4b38a07d4eac5e Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 20 Apr 2023 10:56:36 +0800 Subject: [PATCH 126/166] [test] now clock network example script supports multiple clocks --- .../openfpga_shell_scripts/example_clkntwk_script.openfpga | 4 ++-- .../homo_1clock_2layer/config/dummy_pin_constraints.xml | 3 +++ .../homo_1clock_2layer/config/dummy_repack_constraints.xml | 4 ++++ .../clock_network/homo_1clock_2layer/config/task.conf | 2 ++ 4 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 openfpga_flow/tasks/basic_tests/clock_network/homo_1clock_2layer/config/dummy_pin_constraints.xml create mode 100644 openfpga_flow/tasks/basic_tests/clock_network/homo_1clock_2layer/config/dummy_repack_constraints.xml diff --git a/openfpga_flow/openfpga_shell_scripts/example_clkntwk_script.openfpga b/openfpga_flow/openfpga_shell_scripts/example_clkntwk_script.openfpga index 112f758fd..9187178f9 100644 --- a/openfpga_flow/openfpga_shell_scripts/example_clkntwk_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/example_clkntwk_script.openfpga @@ -42,7 +42,7 @@ write_fabric_hierarchy --file ./fabric_hierarchy.txt # Repack the netlist to physical pbs # This must be done before bitstream generator and testbench generation # Strongly recommend it is done after all the fix-up have been applied -repack #--verbose +repack --design_constraints ${OPENFPGA_REPACK_CONSTRAINTS_FILE} #--verbose # Build the bitstream # - Output the fabric-independent bitstream to a file @@ -66,7 +66,7 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init --bitstream fabric_bitstream.bit write_preconfigured_fabric_wrapper --embed_bitstream iverilog --file ./SRC --explicit_port_mapping -write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --pin_constraints_file ${OPENFPGA_PIN_CONSTRAINTS_FILE} # Finish and exit OpenFPGA exit diff --git a/openfpga_flow/tasks/basic_tests/clock_network/homo_1clock_2layer/config/dummy_pin_constraints.xml b/openfpga_flow/tasks/basic_tests/clock_network/homo_1clock_2layer/config/dummy_pin_constraints.xml new file mode 100644 index 000000000..219672931 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/clock_network/homo_1clock_2layer/config/dummy_pin_constraints.xml @@ -0,0 +1,3 @@ + + + diff --git a/openfpga_flow/tasks/basic_tests/clock_network/homo_1clock_2layer/config/dummy_repack_constraints.xml b/openfpga_flow/tasks/basic_tests/clock_network/homo_1clock_2layer/config/dummy_repack_constraints.xml new file mode 100644 index 000000000..fd33eba91 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/clock_network/homo_1clock_2layer/config/dummy_repack_constraints.xml @@ -0,0 +1,4 @@ + + + + diff --git a/openfpga_flow/tasks/basic_tests/clock_network/homo_1clock_2layer/config/task.conf b/openfpga_flow/tasks/basic_tests/clock_network/homo_1clock_2layer/config/task.conf index a92fa5fef..b05af260f 100644 --- a/openfpga_flow/tasks/basic_tests/clock_network/homo_1clock_2layer/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/clock_network/homo_1clock_2layer/config/task.conf @@ -22,6 +22,8 @@ openfpga_clock_arch_file=${PATH:TASK_DIR}/config/clk_arch_1clk_2layer.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml openfpga_vpr_device_layout=2x2 openfpga_vpr_route_chan_width=24 +openfpga_repack_constraints_file=${PATH:TASK_DIR}/config/dummy_repack_constraints.xml +openfpga_pin_constraints_file=${PATH:TASK_DIR}/config/dummy_pin_constraints.xml [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_Ntwk1clk2lvl_40nm.xml From b242fd97d6896fc6948696e2931df83009615cf6 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 20 Apr 2023 11:31:49 +0800 Subject: [PATCH 127/166] [test] adding new arch and testcase for 2-clock network --- .../k4_N4_40nm_Ntwk2clk2lvl_cc_openfpga.xml | 197 ++++++++++ .../config/clk_arch_2clk_2layer.xml | 17 + .../config/pin_constraints.xml | 4 + .../config/repack_constraints.xml | 5 + .../homo_2clock_2layer/config/task.conf | 40 +++ .../k4_N4_tileable_Ntwk2clk2lvl_40nm.xml | 338 ++++++++++++++++++ 6 files changed, 601 insertions(+) create mode 100644 openfpga_flow/openfpga_arch/k4_N4_40nm_Ntwk2clk2lvl_cc_openfpga.xml create mode 100644 openfpga_flow/tasks/basic_tests/clock_network/homo_2clock_2layer/config/clk_arch_2clk_2layer.xml create mode 100644 openfpga_flow/tasks/basic_tests/clock_network/homo_2clock_2layer/config/pin_constraints.xml create mode 100644 openfpga_flow/tasks/basic_tests/clock_network/homo_2clock_2layer/config/repack_constraints.xml create mode 100644 openfpga_flow/tasks/basic_tests/clock_network/homo_2clock_2layer/config/task.conf create mode 100644 openfpga_flow/vpr_arch/k4_N4_tileable_Ntwk2clk2lvl_40nm.xml diff --git a/openfpga_flow/openfpga_arch/k4_N4_40nm_Ntwk2clk2lvl_cc_openfpga.xml b/openfpga_flow/openfpga_arch/k4_N4_40nm_Ntwk2clk2lvl_cc_openfpga.xml new file mode 100644 index 000000000..90109d00b --- /dev/null +++ b/openfpga_flow/openfpga_arch/k4_N4_40nm_Ntwk2clk2lvl_cc_openfpga.xml @@ -0,0 +1,197 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + + + + + 10e-12 5e-12 5e-12 + + + 10e-12 5e-12 5e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/openfpga_flow/tasks/basic_tests/clock_network/homo_2clock_2layer/config/clk_arch_2clk_2layer.xml b/openfpga_flow/tasks/basic_tests/clock_network/homo_2clock_2layer/config/clk_arch_2clk_2layer.xml new file mode 100644 index 000000000..0570406fd --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/clock_network/homo_2clock_2layer/config/clk_arch_2clk_2layer.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/openfpga_flow/tasks/basic_tests/clock_network/homo_2clock_2layer/config/pin_constraints.xml b/openfpga_flow/tasks/basic_tests/clock_network/homo_2clock_2layer/config/pin_constraints.xml new file mode 100644 index 000000000..20738476d --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/clock_network/homo_2clock_2layer/config/pin_constraints.xml @@ -0,0 +1,4 @@ + + + + diff --git a/openfpga_flow/tasks/basic_tests/clock_network/homo_2clock_2layer/config/repack_constraints.xml b/openfpga_flow/tasks/basic_tests/clock_network/homo_2clock_2layer/config/repack_constraints.xml new file mode 100644 index 000000000..eb0c4435a --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/clock_network/homo_2clock_2layer/config/repack_constraints.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/openfpga_flow/tasks/basic_tests/clock_network/homo_2clock_2layer/config/task.conf b/openfpga_flow/tasks/basic_tests/clock_network/homo_2clock_2layer/config/task.conf new file mode 100644 index 000000000..190ff11e0 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/clock_network/homo_2clock_2layer/config/task.conf @@ -0,0 +1,40 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = true +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=yosys_vpr + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/example_clkntwk_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_Ntwk2clk2lvl_cc_openfpga.xml +openfpga_clock_arch_file=${PATH:TASK_DIR}/config/clk_arch_2clk_2layer.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout=2x2 +openfpga_vpr_route_chan_width=24 +openfpga_repack_constraints_file=${PATH:TASK_DIR}/config/repack_constraints.xml +openfpga_pin_constraints_file=${PATH:TASK_DIR}/config/pin_constraints.xml + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_Ntwk2clk2lvl_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2_latch/and2_latch.v + +[SYNTHESIS_PARAM] +bench_read_verilog_options_common = -nolatches +bench0_top = and2_latch + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= +vpr_fpga_verilog_formal_verification_top_netlist= diff --git a/openfpga_flow/vpr_arch/k4_N4_tileable_Ntwk2clk2lvl_40nm.xml b/openfpga_flow/vpr_arch/k4_N4_tileable_Ntwk2clk2lvl_40nm.xml new file mode 100644 index 000000000..fe6a8a7e3 --- /dev/null +++ b/openfpga_flow/vpr_arch/k4_N4_tileable_Ntwk2clk2lvl_40nm.xml @@ -0,0 +1,338 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + io.outpad io.inpad + io.outpad io.inpad + io.outpad io.inpad + io.outpad io.inpad + + + + + + + + + + + + + + + + + clb.I[0:4] clb.O[0:1] + clb.I[5:9] clb.O[2:3] clb.clk + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 1 + 1 + + + + 1 1 1 1 1 + 1 1 1 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 261e-12 + 261e-12 + 261e-12 + 261e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 02b02d18a5b5bd96918f93e316e7d876fa1648dd Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 20 Apr 2023 11:35:36 +0800 Subject: [PATCH 128/166] [test] fixed a bug in clock arch --- .../homo_2clock_2layer/config/clk_arch_2clk_2layer.xml | 2 +- openfpga_flow/vpr_arch/k4_N4_tileable_Ntwk2clk2lvl_40nm.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openfpga_flow/tasks/basic_tests/clock_network/homo_2clock_2layer/config/clk_arch_2clk_2layer.xml b/openfpga_flow/tasks/basic_tests/clock_network/homo_2clock_2layer/config/clk_arch_2clk_2layer.xml index 0570406fd..d39c48e9b 100644 --- a/openfpga_flow/tasks/basic_tests/clock_network/homo_2clock_2layer/config/clk_arch_2clk_2layer.xml +++ b/openfpga_flow/tasks/basic_tests/clock_network/homo_2clock_2layer/config/clk_arch_2clk_2layer.xml @@ -11,7 +11,7 @@ - + diff --git a/openfpga_flow/vpr_arch/k4_N4_tileable_Ntwk2clk2lvl_40nm.xml b/openfpga_flow/vpr_arch/k4_N4_tileable_Ntwk2clk2lvl_40nm.xml index fe6a8a7e3..f4e40b275 100644 --- a/openfpga_flow/vpr_arch/k4_N4_tileable_Ntwk2clk2lvl_40nm.xml +++ b/openfpga_flow/vpr_arch/k4_N4_tileable_Ntwk2clk2lvl_40nm.xml @@ -250,7 +250,7 @@ - + From fba0a83679a18ac56a130bf61ef3398fff353562 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 20 Apr 2023 14:44:01 +0800 Subject: [PATCH 129/166] [test] debugging 2-clock network --- .../openfpga_shell_scripts/example_clkntwk_script.openfpga | 2 +- .../homo_2clock_2layer/config/clk_arch_2clk_2layer.xml | 5 +++-- .../homo_2clock_2layer/config/pin_constraints.xml | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/openfpga_flow/openfpga_shell_scripts/example_clkntwk_script.openfpga b/openfpga_flow/openfpga_shell_scripts/example_clkntwk_script.openfpga index 9187178f9..cc74022f6 100644 --- a/openfpga_flow/openfpga_shell_scripts/example_clkntwk_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/example_clkntwk_script.openfpga @@ -22,7 +22,7 @@ append_clock_rr_graph link_openfpga_arch --activity_file ${ACTIVITY_FILE} --sort_gsb_chan_node_in_edges # Route clock based on clock network definition -route_clock_rr_graph +route_clock_rr_graph --pin_constraints_file ${OPENFPGA_PIN_CONSTRAINTS_FILE} # Check and correct any naming conflicts in the BLIF netlist check_netlist_naming_conflict --fix --report ./netlist_renaming.xml diff --git a/openfpga_flow/tasks/basic_tests/clock_network/homo_2clock_2layer/config/clk_arch_2clk_2layer.xml b/openfpga_flow/tasks/basic_tests/clock_network/homo_2clock_2layer/config/clk_arch_2clk_2layer.xml index d39c48e9b..46fec8fd5 100644 --- a/openfpga_flow/tasks/basic_tests/clock_network/homo_2clock_2layer/config/clk_arch_2clk_2layer.xml +++ b/openfpga_flow/tasks/basic_tests/clock_network/homo_2clock_2layer/config/clk_arch_2clk_2layer.xml @@ -1,5 +1,5 @@ - + @@ -11,7 +11,8 @@ - + + diff --git a/openfpga_flow/tasks/basic_tests/clock_network/homo_2clock_2layer/config/pin_constraints.xml b/openfpga_flow/tasks/basic_tests/clock_network/homo_2clock_2layer/config/pin_constraints.xml index 20738476d..1989d1eea 100644 --- a/openfpga_flow/tasks/basic_tests/clock_network/homo_2clock_2layer/config/pin_constraints.xml +++ b/openfpga_flow/tasks/basic_tests/clock_network/homo_2clock_2layer/config/pin_constraints.xml @@ -1,4 +1,4 @@ - - + + From 40598d25a3c08b5764f672c040d4b0030ca62982 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 20 Apr 2023 15:05:45 +0800 Subject: [PATCH 130/166] [core] fixed a bug which causes multi-clock programmable network failed in routing --- .../src/annotation/route_clock_rr_graph.cpp | 21 ++++++++++++------- .../example_clkntwk_script.openfpga | 4 ++-- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/openfpga/src/annotation/route_clock_rr_graph.cpp b/openfpga/src/annotation/route_clock_rr_graph.cpp index 2d4d152f6..03d083172 100644 --- a/openfpga/src/annotation/route_clock_rr_graph.cpp +++ b/openfpga/src/annotation/route_clock_rr_graph.cpp @@ -141,10 +141,13 @@ static int route_clock_tree_rr_graph( VTR_ASSERT(rr_graph.valid_node(des_node)); vpr_routing_annotation.set_rr_node_prev_node(rr_graph, des_node, src_node); - vpr_routing_annotation.set_rr_node_net(src_node, - tree2clk_pin_map.at(ipin)); - vpr_routing_annotation.set_rr_node_net(des_node, - tree2clk_pin_map.at(ipin)); + /* It could happen that there is no net mapped some clock pin, skip the net mapping */ + if (tree2clk_pin_map.find(ipin) != tree2clk_pin_map.end()) { + vpr_routing_annotation.set_rr_node_net(src_node, + tree2clk_pin_map.at(ipin)); + vpr_routing_annotation.set_rr_node_net(des_node, + tree2clk_pin_map.at(ipin)); + } } /* Route the spine-to-IPIN connections (only for the last level) */ if (clk_ntwk.is_last_level(ispine)) { @@ -165,10 +168,12 @@ static int route_clock_tree_rr_graph( VTR_ASSERT(rr_graph.valid_node(des_node)); vpr_routing_annotation.set_rr_node_prev_node(rr_graph, des_node, src_node); - vpr_routing_annotation.set_rr_node_net(src_node, - tree2clk_pin_map.at(ipin)); - vpr_routing_annotation.set_rr_node_net(des_node, - tree2clk_pin_map.at(ipin)); + if (tree2clk_pin_map.find(ipin) != tree2clk_pin_map.end()) { + vpr_routing_annotation.set_rr_node_net(src_node, + tree2clk_pin_map.at(ipin)); + vpr_routing_annotation.set_rr_node_net(des_node, + tree2clk_pin_map.at(ipin)); + } } } } diff --git a/openfpga_flow/openfpga_shell_scripts/example_clkntwk_script.openfpga b/openfpga_flow/openfpga_shell_scripts/example_clkntwk_script.openfpga index cc74022f6..83cc44860 100644 --- a/openfpga_flow/openfpga_shell_scripts/example_clkntwk_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/example_clkntwk_script.openfpga @@ -64,8 +64,8 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init --bitstream fabric_bitstream.bit -write_preconfigured_fabric_wrapper --embed_bitstream iverilog --file ./SRC --explicit_port_mapping +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init --bitstream fabric_bitstream.bit --pin_constraints_file ${OPENFPGA_PIN_CONSTRAINTS_FILE} +write_preconfigured_fabric_wrapper --embed_bitstream iverilog --file ./SRC --explicit_port_mapping --pin_constraints_file ${OPENFPGA_PIN_CONSTRAINTS_FILE} write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --pin_constraints_file ${OPENFPGA_PIN_CONSTRAINTS_FILE} # Finish and exit OpenFPGA From 087636cefab6d9f140bc281d4bdb3cc9533d5c93 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 20 Apr 2023 15:06:47 +0800 Subject: [PATCH 131/166] [test] deploy new test to regression tests --- openfpga_flow/regression_test_scripts/basic_reg_test.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/openfpga_flow/regression_test_scripts/basic_reg_test.sh b/openfpga_flow/regression_test_scripts/basic_reg_test.sh index 248f779f5..490cab089 100755 --- a/openfpga_flow/regression_test_scripts/basic_reg_test.sh +++ b/openfpga_flow/regression_test_scripts/basic_reg_test.sh @@ -166,6 +166,7 @@ run-task basic_tests/global_tile_ports/global_tile_4clock_pin $@ echo -e "Testing programmable clock architecture"; run-task basic_tests/clock_network/homo_1clock_2layer $@ run-task basic_tests/clock_network/homo_1clock_2layer_full_tb $@ +run-task basic_tests/clock_network/homo_2clock_2layer $@ echo -e "Testing configuration chain of a K4N4 FPGA using .blif generated by yosys+verific"; run-task basic_tests/verific_test $@ From aeeee6d8bd4fc37448325d61b2d3f004f08a0410 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 20 Apr 2023 15:07:54 +0800 Subject: [PATCH 132/166] [core] code format --- openfpga/src/annotation/route_clock_rr_graph.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/openfpga/src/annotation/route_clock_rr_graph.cpp b/openfpga/src/annotation/route_clock_rr_graph.cpp index 03d083172..bafc8215f 100644 --- a/openfpga/src/annotation/route_clock_rr_graph.cpp +++ b/openfpga/src/annotation/route_clock_rr_graph.cpp @@ -141,7 +141,8 @@ static int route_clock_tree_rr_graph( VTR_ASSERT(rr_graph.valid_node(des_node)); vpr_routing_annotation.set_rr_node_prev_node(rr_graph, des_node, src_node); - /* It could happen that there is no net mapped some clock pin, skip the net mapping */ + /* It could happen that there is no net mapped some clock pin, skip the + * net mapping */ if (tree2clk_pin_map.find(ipin) != tree2clk_pin_map.end()) { vpr_routing_annotation.set_rr_node_net(src_node, tree2clk_pin_map.at(ipin)); @@ -169,10 +170,10 @@ static int route_clock_tree_rr_graph( vpr_routing_annotation.set_rr_node_prev_node(rr_graph, des_node, src_node); if (tree2clk_pin_map.find(ipin) != tree2clk_pin_map.end()) { - vpr_routing_annotation.set_rr_node_net(src_node, - tree2clk_pin_map.at(ipin)); - vpr_routing_annotation.set_rr_node_net(des_node, - tree2clk_pin_map.at(ipin)); + vpr_routing_annotation.set_rr_node_net( + src_node, tree2clk_pin_map.at(ipin)); + vpr_routing_annotation.set_rr_node_net( + des_node, tree2clk_pin_map.at(ipin)); } } } From 9756bfe0ca8b34cb395cd8bc483c7cb91c404189 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 20 Apr 2023 15:27:28 +0800 Subject: [PATCH 133/166] [doc] document newly added commands for programmable clock arch support --- .../openfpga_commands/setup_commands.rst | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/docs/source/manual/openfpga_shell/openfpga_commands/setup_commands.rst b/docs/source/manual/openfpga_shell/openfpga_commands/setup_commands.rst index 9c05ee00c..5971f75f2 100644 --- a/docs/source/manual/openfpga_shell/openfpga_commands/setup_commands.rst +++ b/docs/source/manual/openfpga_shell/openfpga_commands/setup_commands.rst @@ -83,6 +83,60 @@ write_openfpga_bitstream_setting Show verbose log +.. _openfpga_setup_command_read_openfpga_clock_arch: + +read_openfpga_clock_arch +~~~~~~~~~~~~~~~~~~~~~~~~ + + Read the XML file about programmable clock network (see details in :ref:`file_formats_clock_network`) + + .. option:: --file or -f + + Specify the file name. For example, ``--file clock_network.xml`` + + .. option:: --verbose + + Show verbose log + +write_openfpga_clock_arch +~~~~~~~~~~~~~~~~~~~~~~~~~ + + Write the OpenFPGA programmable clock network to an XML file + + .. option:: --file or -f + + Specify the file name. For example, ``--file clock_network_echo.xml``. + See details about file format at :ref:`file_formats_clock_network`. + + .. option:: --verbose + + Show verbose log + +append_clock_rr_graph +~~~~~~~~~~~~~~~~~~~~~ + +Build the routing resource graph based on an defined programmable clock network, and append it to the existing routing resource graph built by VPR. +Use command :ref:`openfpga_setup_command_read_openfpga_clock_arch`` to load the clock network. + + .. option:: --verbose + + Show verbose log + +route_clock_rr_graph +~~~~~~~~~~~~~~~~~~~~ + +Route clock signals on the built routing resource graph which contains a programmable clock network. +Clock signals will be auto-detected and routed based on pin constraints which are provided by users. + + .. option:: --pin_constraints_file or -pcf + + Specify the *Pin Constraints File* (PCF) when the clock network contains multiple clock pins. For example, ``-pin_constraints_file pin_constraints.xml`` + Strongly recommend for multi-clock network. See detailed file format about :ref:`file_format_pin_constraints_file`. + + .. option:: --verbose + + Show verbose log + link_openfpga_arch ~~~~~~~~~~~~~~~~~~ From 509f5eb6dc3c464c811c95e21177d2e714cedb18 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 20 Apr 2023 17:06:53 +0800 Subject: [PATCH 134/166] [doc] add documentation about clock network description file --- .../manual/arch_lang/annotate_vpr_arch.rst | 4 +- .../manual/file_formats/clock_network.rst | 207 ++++++++++++++++++ docs/source/manual/file_formats/index.rst | 2 + 3 files changed, 212 insertions(+), 1 deletion(-) create mode 100644 docs/source/manual/file_formats/clock_network.rst diff --git a/docs/source/manual/arch_lang/annotate_vpr_arch.rst b/docs/source/manual/arch_lang/annotate_vpr_arch.rst index a9e423f7c..a23b4f0c6 100644 --- a/docs/source/manual/arch_lang/annotate_vpr_arch.rst +++ b/docs/source/manual/arch_lang/annotate_vpr_arch.rst @@ -62,7 +62,7 @@ Here is an example: .. code-block:: xml - + ... @@ -72,6 +72,8 @@ Here is an example: - ``is_clock=""`` define if the global port is a clock port at the top-level FPGA fabric. An operating clock port will be driven by proper signals in auto-generated testbenches. +- ``clock_arch_tree_name=""`` defines the name of the programmable clock network, which the global port will drive. The name of the programmable clock network must be a valid name (See details in :ref:`file_formats_clock_network`) + - ``is_reset=""`` define if the global port is a reset port at the top-level FPGA fabric. An operating reset port will be driven by proper signals in testbenches. - ``is_set=""`` define if the global port is a set port at the top-level FPGA fabric. An operating set port will be driven by proper signals in testbenches. diff --git a/docs/source/manual/file_formats/clock_network.rst b/docs/source/manual/file_formats/clock_network.rst new file mode 100644 index 000000000..24b7aec38 --- /dev/null +++ b/docs/source/manual/file_formats/clock_network.rst @@ -0,0 +1,207 @@ +.. _file_formats_clock_network: + +Clock Network (.xml) +-------------------- + +The XML-based clock network description language is used to describe + +- One or more programmable clock networks constaining programmable switches for routing clock signals +- The routing for clock signals on the programmable clock network + +Using the clock network description language, users can define multiple clock networks, each of which consists: + +- A number of clock spines which can propagate clock signals from one point to another. See details in :ref:`_file_formats_clock_network_clock_spine`. +- A number of switch points which interconnects clock spines using programmable routing switches. See details in :ref:`_file_formats_clock_network_switch_point`. +- A number of tap points which connect the clock spines to programmable blocks, e.g., CLBs. See details in :ref:`_file_formats_clock_network_tap_point`. + +.. note:: Please note that the levels of a clock network will be automatically inferred from the clock spines and switch points. Clock network will be **only** built based on the width and the number of levels, as well as the tap points. + +.. note:: The switch points and clock spines will be used to route a clock network. The switch points will not impact the physical clock network but only impact the configuration of the programmable routing switches in the physical clock network. + +.. warning:: Clock network is a feature for power-users. It requires additional EDA support to leverage the best performance of the clock network, as timing analysis and convergence is more challenging. + +.. code-block:: xml + + + + + + + + + + + + +General Settings +^^^^^^^^^^^^^^^^ + +The following syntax are applicable to the XML definition under the root node ``clock_networks`` + +.. option:: default_segment="" + + Define the default routing segment to be used when building the routing tracks for the clock network. Must be a valid routing segment defined in the VPR architecture file. For example, + + .. code-block:: xml + + default_segment="L1" + +where the segment is defined in the VPR architecture file: + +.. code-block:: xml + + + + + +.. note:: Currently, clock network requires only length-1 wire segment to be used! + +.. option:: default_switch="" + + Define the default routing switch to be used when interconnects the routing tracks in the clock network. Must be a valid routing switch defined in the VPR architecture file. For example, + + .. code-block:: xml + + default_switch="clk_mux" + +where the switch is defined in the VPR architecture file: + +.. code-block:: xml + + + + + +.. note:: Currently, clock network only supports one type of routing switch, which means all the programmable routing switch in the clock network will be in the same type and circuit design topology. + +Clock Network Settings +^^^^^^^^^^^^^^^^^^^^^^ + +The following syntax are applicable to the XML definition tagged by ``clock_network``. +Note that a number of clock networks can be defined under the root node ``clock_networks``. + +.. option:: name="" + + The unique name of the clock network. It will be used to link the clock network to a specific global port in :ref:`annotate_vpr_arch_physical_tile_annotation`. For example, + + .. code-block:: xml + + name="clk_tree_0" + +where the clock network is used to drive the global clock pin ``clk0`` in OpenFPGA's architecture description file: + +.. code-block:: xml + + + + + + +.. option:: width="" + + The maximum number of clock pins that a clock network can drive. + +.. _file_formats_clock_network_clock_spine: + +Clock Spine Settings +^^^^^^^^^^^^^^^^^^^^ + +The following syntax are applicable to the XML definition tagged by ``spine``. +Note that a number of clock spines can be defined under the node ``clock_network``. + +.. option:: name="" + + The unique name of the clock spine. It will be used to build switch points between other clock spines. + +.. option:: start_x="" + + The coordinate X of the starting point of the clock spine. + +.. option:: start_y="" + + The coordinate Y of the starting point of the clock spine. + +.. option:: end_x="" + + The coordinate X of the ending point of the clock spine. + +.. option:: end_y="" + + The coordinate Y of the ending point of the clock spine. + +For example, + +.. code-block:: xml + + + +where a horizental clock spine ``spine0`` is defined which spans from (1, 1) to (2, 1) + +.. note:: We only support clock spines in horizental and vertical directions. Diagonal clock spine is not supported! + +.. _file_formats_clock_network_switch_point: + +Switch Point Settings +^^^^^^^^^^^^^^^^^^^^^ + +The following syntax are applicable to the XML definition tagged by ``switch_point``. +Note that a number of switch points can be defined under each clock spine ``spine``. + +.. option:: tap="" + + Define which clock spine will be tapped from the current clock spine. + +.. option:: x="" + + The coordinate X of the switch point. Must be a valid coordinate within the range of the current clock spine and the clock spine to be tapped. + +.. option:: y="" + + The coordinate Y of the switch point. Must be a valid coordinate within the range of the current clock spine and the clock spine to be tapped. + +For example, + +.. code-block:: xml + + + + + +where clock spine ``spine0`` will drive another clock spine ``spine1`` at (1, 1). + +.. _file_formats_clock_network_tap_point: + +Tap Point Settings +^^^^^^^^^^^^^^^^^^ + +The following syntax are applicable to the XML definition tagged by ``tap``. +Note that a number of tap points can be defined under the node ``taps``. + +.. option:: tile_pin="" + + Define the pin of a programmable block to be tapped by a clock network. The pin must be a valid pin defined in the VPR architecture description file. + +.. note:: Only the leaf clock spine (not switch points to drive other clock spine) can tap pins of programmable blocks. + +For example, + +.. code-block:: xml + + + + + + + + +where all the clock spines of the clock network ``clk_tree_0`` tap the clock pins ``clk`` of tile ``clb`` in a VPR architecture description file: + +.. code-block:: xml + + + + + + + diff --git a/docs/source/manual/file_formats/index.rst b/docs/source/manual/file_formats/index.rst index 49332c134..45c91d0ce 100644 --- a/docs/source/manual/file_formats/index.rst +++ b/docs/source/manual/file_formats/index.rst @@ -33,3 +33,5 @@ OpenFPGA widely uses XML format for interchangable files pcf_file pin_table_file + + clock_network From 074e8f5150e83d79865f41a426125175d2b65c35 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 21 Apr 2023 00:02:29 +0000 Subject: [PATCH 135/166] Updated Patch Count --- VERSION.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION.md b/VERSION.md index ff8e40899..21d8cb3bc 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -1.2.815 +1.2.929 From 081620055b81859020d695d77075f205f5124c22 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 21 Apr 2023 13:58:13 +0800 Subject: [PATCH 136/166] [doc] fix broken links in the Clock Network file format --- docs/source/manual/file_formats/clock_network.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/source/manual/file_formats/clock_network.rst b/docs/source/manual/file_formats/clock_network.rst index 24b7aec38..9d6baad98 100644 --- a/docs/source/manual/file_formats/clock_network.rst +++ b/docs/source/manual/file_formats/clock_network.rst @@ -10,9 +10,9 @@ The XML-based clock network description language is used to describe Using the clock network description language, users can define multiple clock networks, each of which consists: -- A number of clock spines which can propagate clock signals from one point to another. See details in :ref:`_file_formats_clock_network_clock_spine`. -- A number of switch points which interconnects clock spines using programmable routing switches. See details in :ref:`_file_formats_clock_network_switch_point`. -- A number of tap points which connect the clock spines to programmable blocks, e.g., CLBs. See details in :ref:`_file_formats_clock_network_tap_point`. +- A number of clock spines which can propagate clock signals from one point to another. See details in :ref:`file_formats_clock_network_clock_spine`. +- A number of switch points which interconnects clock spines using programmable routing switches. See details in :ref:`file_formats_clock_network_switch_point`. +- A number of tap points which connect the clock spines to programmable blocks, e.g., CLBs. See details in :ref:`file_formats_clock_network_tap_point`. .. note:: Please note that the levels of a clock network will be automatically inferred from the clock spines and switch points. Clock network will be **only** built based on the width and the number of levels, as well as the tap points. From 82f526fc61c5a5b8fd785d7458d691d4ae2fbf3f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 21 Apr 2023 06:58:52 +0000 Subject: [PATCH 137/166] Bump yosys-plugins from `96a0853` to `137606e` Bumps [yosys-plugins](https://github.com/SymbiFlow/yosys-symbiflow-plugins) from `96a0853` to `137606e`. - [Release notes](https://github.com/SymbiFlow/yosys-symbiflow-plugins/releases) - [Commits](https://github.com/SymbiFlow/yosys-symbiflow-plugins/compare/96a0853eba5691f54a5e0bfc044d847743e09cef...137606ebfad8de60aa44d37c11a20c540bbdba98) --- updated-dependencies: - dependency-name: yosys-plugins dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- yosys-plugins | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yosys-plugins b/yosys-plugins index 96a0853eb..137606ebf 160000 --- a/yosys-plugins +++ b/yosys-plugins @@ -1 +1 @@ -Subproject commit 96a0853eba5691f54a5e0bfc044d847743e09cef +Subproject commit 137606ebfad8de60aa44d37c11a20c540bbdba98 From 7694f7105501471cbee03e1a74ad98cc2460aca9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 21 Apr 2023 06:58:57 +0000 Subject: [PATCH 138/166] Bump vtr-verilog-to-routing from `d70659f` to `90ee6e6` Bumps [vtr-verilog-to-routing](https://github.com/verilog-to-routing/vtr-verilog-to-routing) from `d70659f` to `90ee6e6`. - [Release notes](https://github.com/verilog-to-routing/vtr-verilog-to-routing/releases) - [Commits](https://github.com/verilog-to-routing/vtr-verilog-to-routing/compare/d70659f424425dbaa6ecdb6dea40bf1841f02dac...90ee6e663a0e021604dff4552f5b7f9744cedd74) --- updated-dependencies: - dependency-name: vtr-verilog-to-routing dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- vtr-verilog-to-routing | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vtr-verilog-to-routing b/vtr-verilog-to-routing index d70659f42..90ee6e663 160000 --- a/vtr-verilog-to-routing +++ b/vtr-verilog-to-routing @@ -1 +1 @@ -Subproject commit d70659f424425dbaa6ecdb6dea40bf1841f02dac +Subproject commit 90ee6e663a0e021604dff4552f5b7f9744cedd74 From c220438c42077fb8e845f91273da8e968ce1efa8 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 21 Apr 2023 15:21:34 +0800 Subject: [PATCH 139/166] [doc] adding new syntax that supports separated clocks for multi-head configuration chains --- .../manual/arch_lang/config_protocol.rst | 34 ++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/docs/source/manual/arch_lang/config_protocol.rst b/docs/source/manual/arch_lang/config_protocol.rst index 9d21a78b6..e4cb11078 100644 --- a/docs/source/manual/arch_lang/config_protocol.rst +++ b/docs/source/manual/arch_lang/config_protocol.rst @@ -63,7 +63,9 @@ It will use the circuit model defined in :numref:`fig_ccff_config_chain`. .. code-block:: xml - + + + .. _fig_ccff_fpga: @@ -81,6 +83,36 @@ It will use the circuit model defined in :numref:`fig_ccff_config_chain`. Examples of single- and multiple- region configuration chains +Note that for each configuration chain, its programming clock can be separated or grouped by using the syntax ``programming_clock``. + +.. note:: Only applicable to multi-head configuration chains (number of regions is greater than 1). If not specified, all the chains share the same clock. + +.. option:: port="" + + Define the port name of a programming clock. This should be a valid global clock port defined in the circuit models whose type is ``ccff``. See details in :ref:`circuit_model_ccff_example`. + +.. option:: ccff_head_indices="" + + Define the indices of the configuration chains which will be controlled by the programming clock defined using XML syntax ``port``. The indices should consist of valid indices within the range of number of regions. + +In the following example, a 6-head configuration protocol is defined where the first three chains share a common clock ``CK[0]``, where the forth chain is driven by an individual clock ``CK[1]`` and the other two chains are driven by a common clock ``CK[2]``. + +.. code-block:: xml + + + + + + + + + + + + + + + Frame-based Example ~~~~~~~~~~~~~~~~~~~ From 76a553e7bce02d928325162957ae1a688322467c Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 21 Apr 2023 15:23:51 +0800 Subject: [PATCH 140/166] [doc] supplementary description --- docs/source/manual/arch_lang/config_protocol.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/source/manual/arch_lang/config_protocol.rst b/docs/source/manual/arch_lang/config_protocol.rst index e4cb11078..d4d4d052e 100644 --- a/docs/source/manual/arch_lang/config_protocol.rst +++ b/docs/source/manual/arch_lang/config_protocol.rst @@ -77,6 +77,8 @@ It will use the circuit model defined in :numref:`fig_ccff_config_chain`. Example of a configuration chain to program core logic of a FPGA +.. _fig_multi_region_config_chains: + .. figure:: figures/multi_region_config_chains.png :width: 100% :alt: map to buried treasure @@ -95,7 +97,7 @@ Note that for each configuration chain, its programming clock can be separated o Define the indices of the configuration chains which will be controlled by the programming clock defined using XML syntax ``port``. The indices should consist of valid indices within the range of number of regions. -In the following example, a 6-head configuration protocol is defined where the first three chains share a common clock ``CK[0]``, where the forth chain is driven by an individual clock ``CK[1]`` and the other two chains are driven by a common clock ``CK[2]``. +In the following example, a 6-head configuration protocol (corresponding to :numref:`fig_multi_region_config_chains`) is defined where the first three chains share a common clock ``CK[0]``, where the forth chain is driven by an individual clock ``CK[1]`` and the other two chains are driven by a common clock ``CK[2]``. .. code-block:: xml From 6e44f3f5fc9eaca44f50fba3489997dc38642b6f Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 21 Apr 2023 17:01:51 +0800 Subject: [PATCH 141/166] [core] developing ccff_v2 parsers --- libs/libarchopenfpga/src/config_protocol.cpp | 40 ++++++++++++++++++- libs/libarchopenfpga/src/config_protocol.h | 13 ++++++ .../src/read_xml_config_protocol.cpp | 23 +++++++++++ 3 files changed, 75 insertions(+), 1 deletion(-) diff --git a/libs/libarchopenfpga/src/config_protocol.cpp b/libs/libarchopenfpga/src/config_protocol.cpp index 2a617830e..51fbecea6 100644 --- a/libs/libarchopenfpga/src/config_protocol.cpp +++ b/libs/libarchopenfpga/src/config_protocol.cpp @@ -10,7 +10,9 @@ /************************************************************************ * Constructors ***********************************************************************/ -ConfigProtocol::ConfigProtocol() { return; } +ConfigProtocol::ConfigProtocol() { + INDICE_STRING_DELIM_ = ','; +} /************************************************************************ * Public Accessors @@ -25,6 +27,28 @@ CircuitModelId ConfigProtocol::memory_model() const { return memory_model_; } int ConfigProtocol::num_regions() const { return num_regions_; } +std::vector ConfigProtocol::prog_clock_ports() const { + std::vector keys; + for (const auto& [k, v] : prog_clk_ccff_head_indices_) { + keys.push_back(k); + } + return keys; +} + +std::string ConfigProtocol::prog_clock_port_ccff_head_indices(const BasicPort& port) const { + std::string ret(""); + auto result = prog_clk_ccff_head_indices.find(port); + if (result != prog_clk_ccff_head_indices.end()) { + for (size_t idx : result->second) { + /* TODO: We need a join function */ + ret += std::to_string(idx) + std::string(INDICE_STRING_DELIM); + } + /* Remove the last comma */ + ret.pop(); + } + return ret; +} + e_blwl_protocol_type ConfigProtocol::bl_protocol_type() const { return bl_protocol_type_; } @@ -73,6 +97,20 @@ void ConfigProtocol::set_num_regions(const int& num_regions) { num_regions_ = num_regions; } +void ConfigProtocol::set_prog_clock_port_ccff_head_indices_pair(const BasicPort& port, const std::string& indices_str) { + openfpga::StringToken tokenizer(indices_str); + std::vector token_int; + token_int.reserve(tokenizer.split(INDICE_STRING_DELIM_).size()); + for (std::string token : tokenizer.split(INDICE_STRING_DELIM_)) { + token_int.push_back(std::atoi(token)); + } + auto result = prog_clk_ccff_head_indices.find(port); + if (result != prog_clk_ccff_head_indices.end()) { + VTR_LOG_WARN("Overwrite the pair between programming clock port '%s[%d:%d]' and ccff head indices (previous: '%s', current: '%s')!\n", port.get_name().c_str(), port.get_lsb(), port.get_msb(), prog_clock_port_ccff_head_indices(port).c_str(), indices_str.c_str()); + } + prog_clk_ccff_head_indices_[port] = token_int; +} + void ConfigProtocol::set_bl_protocol_type(const e_blwl_protocol_type& type) { if (CONFIG_MEM_QL_MEMORY_BANK != type_) { VTR_LOG_ERROR( diff --git a/libs/libarchopenfpga/src/config_protocol.h b/libs/libarchopenfpga/src/config_protocol.h index 3ef7f59d4..960a25f06 100644 --- a/libs/libarchopenfpga/src/config_protocol.h +++ b/libs/libarchopenfpga/src/config_protocol.h @@ -5,6 +5,7 @@ #include "circuit_library_fwd.h" #include "circuit_types.h" +#include "openfpga_port.h" /* Data type to define the protocol through which BL/WL can be manipulated */ enum e_blwl_protocol_type { @@ -28,6 +29,11 @@ class ConfigProtocol { std::string memory_model_name() const; CircuitModelId memory_model() const; int num_regions() const; + + /* Get a list of programming clock ports */ + std::vector prog_clock_ports() const; + /* Get a list of programming clock ports */ + std::string prog_clock_port_ccff_head_indices(const BasicPort& port) const; e_blwl_protocol_type bl_protocol_type() const; std::string bl_memory_model_name() const; @@ -44,6 +50,9 @@ class ConfigProtocol { void set_memory_model(const CircuitModelId& memory_model); void set_num_regions(const int& num_regions); + /* Add a pair of programming clock port and ccff head indices. This API will parse the index list, e.g., "0,1" to a vector of integers [0 1] */ + void set_prog_clock_port_ccff_head_indices_pair(const BasicPort& port, const std::string& indices_str); + void set_bl_protocol_type(const e_blwl_protocol_type& type); void set_bl_memory_model_name(const std::string& memory_model_name); void set_bl_memory_model(const CircuitModelId& memory_model); @@ -67,6 +76,10 @@ class ConfigProtocol { /* Number of configurable regions */ int num_regions_; + /* Programming clock managment: This is only applicable to configuration chain protocols */ + std::map> prog_clk_ccff_head_indices_; + char INDICE_STRING_DELIM_; + /* BL & WL protocol: This is only applicable to memory-bank configuration * protocols * - type: defines which protocol to be used. By default, we diff --git a/libs/libarchopenfpga/src/read_xml_config_protocol.cpp b/libs/libarchopenfpga/src/read_xml_config_protocol.cpp index 74572de54..9b52c88fb 100644 --- a/libs/libarchopenfpga/src/read_xml_config_protocol.cpp +++ b/libs/libarchopenfpga/src/read_xml_config_protocol.cpp @@ -45,6 +45,18 @@ static e_blwl_protocol_type string_to_blwl_protocol_type( return NUM_BLWL_PROTOCOL_TYPES; } +/******************************************************************** + * Parse XML codes of a to an object of configuration protocol + *******************************************************************/ +static void read_xml_ccff_prog_clock(pugi::xml_node& xml_progclk, + const pugiutil::loc_data& loc_data, + ConfigProtocol& config_protocol) { + /* Find the type of configuration protocol */ + const char* port_attr = + get_attribute(xml_progclk, "port", loc_data).value(); + +} + /******************************************************************** * Parse XML codes of a to an object of configuration protocol *******************************************************************/ @@ -153,6 +165,17 @@ static void read_xml_config_organization(pugi::xml_node& xml_config_orgz, config_protocol.num_regions()); } + /* Parse Configuration chain protocols */ + if (config_protocol.type() == CONFIG_MEM_SCAN_CHAIN) { + for (pugi::xml_node xml_progclk : xml_config_orgz.children()) { + /* Error out if the XML child has an invalid name! */ + if (xml_progclk.name() != std::string("programming_clock")) { + bad_tag(xml_progclk, loc_data, xml_config_orgz, {"programming_clock"}); + } + read_xml_ccff_prog_clock(xml_progclk, loc_data, config_protocol); + } + } + /* Parse BL & WL protocols */ if (config_protocol.type() == CONFIG_MEM_QL_MEMORY_BANK) { pugi::xml_node xml_bl_protocol = get_single_child( From dba449f42a0882d9bb5e415656092c83d3d21ae4 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 21 Apr 2023 23:45:35 +0800 Subject: [PATCH 142/166] [core] code complete for parsers --- .../src/config_protocol_xml_constants.h | 10 +++ .../src/read_xml_config_protocol.cpp | 16 +++-- .../src/write_xml_config_protocol.cpp | 68 ++++++++++++------- libs/libopenfpgautil/src/openfpga_port.cpp | 4 ++ libs/libopenfpgautil/src/openfpga_port.h | 1 + 5 files changed, 72 insertions(+), 27 deletions(-) create mode 100644 libs/libarchopenfpga/src/config_protocol_xml_constants.h diff --git a/libs/libarchopenfpga/src/config_protocol_xml_constants.h b/libs/libarchopenfpga/src/config_protocol_xml_constants.h new file mode 100644 index 000000000..6647ea8ee --- /dev/null +++ b/libs/libarchopenfpga/src/config_protocol_xml_constants.h @@ -0,0 +1,10 @@ +#ifndef CONFIG_PROTOCOL_XML_CONSTANTS_H +#define CONFIG_PROTOCOL_XML_CONSTANTS_H + +/* Constants for XML parsers, including readers and writers */ +constexpr const char* XML_CONFIG_PROTOCOL_NUM_REGIONS_ATTR = "num_regions"; +constexpr const char* XML_CONFIG_PROTOCOL_CCFF_PROG_CLOCK_NODE_NAME = "programming_clock"; +constexpr const char* XML_CONFIG_PROTOCOL_CCFF_PROG_CLOCK_PORT_ATTR = "port"; +constexpr const char* XML_CONFIG_PROTOCOL_CCFF_PROG_CLOCK_INDICES_ATTR = "ccff_head_indices"; + +#endif diff --git a/libs/libarchopenfpga/src/read_xml_config_protocol.cpp b/libs/libarchopenfpga/src/read_xml_config_protocol.cpp index 9b52c88fb..8dcada58e 100644 --- a/libs/libarchopenfpga/src/read_xml_config_protocol.cpp +++ b/libs/libarchopenfpga/src/read_xml_config_protocol.cpp @@ -14,7 +14,9 @@ /* Headers from libarchfpga */ #include "arch_error.h" +#include "config_protocol_xml_constants.h" #include "read_xml_config_protocol.h" +#include "openfpga_port_parser.h" #include "read_xml_util.h" /******************************************************************** @@ -52,9 +54,15 @@ static void read_xml_ccff_prog_clock(pugi::xml_node& xml_progclk, const pugiutil::loc_data& loc_data, ConfigProtocol& config_protocol) { /* Find the type of configuration protocol */ - const char* port_attr = - get_attribute(xml_progclk, "port", loc_data).value(); + std::string port_attr = + get_attribute(xml_progclk, XML_CONFIG_PROTOCOL_CCFF_PROG_CLOCK_PORT_ATTR, loc_data).as_string(); + std::string indices_attr = + get_attribute(xml_progclk, XML_CONFIG_PROTOCOL_CCFF_PROG_CLOCK_INDICES_ATTR, loc_data).as_string(); + + BasicPort port = openfpga::PortParser(port_attr).port(); + + config_protocol.set_prog_clock_port_ccff_head_indices_pair(port, indices_attr); } /******************************************************************** @@ -154,7 +162,7 @@ static void read_xml_config_organization(pugi::xml_node& xml_config_orgz, /* Parse the number of configurable regions * At least 1 region should be defined, otherwise error out */ - config_protocol.set_num_regions(get_attribute(xml_config_orgz, "num_regions", + config_protocol.set_num_regions(get_attribute(xml_config_orgz, XML_CONFIG_PROTOCOL_NUM_REGIONS_ATTR, loc_data, pugiutil::ReqOpt::OPTIONAL) .as_int(1)); @@ -169,7 +177,7 @@ static void read_xml_config_organization(pugi::xml_node& xml_config_orgz, if (config_protocol.type() == CONFIG_MEM_SCAN_CHAIN) { for (pugi::xml_node xml_progclk : xml_config_orgz.children()) { /* Error out if the XML child has an invalid name! */ - if (xml_progclk.name() != std::string("programming_clock")) { + if (xml_progclk.name() != std::string(XML_CONFIG_PROTOCOL_CCFF_PROG_CLOCK_NODE_NAME)) { bad_tag(xml_progclk, loc_data, xml_config_orgz, {"programming_clock"}); } read_xml_ccff_prog_clock(xml_progclk, loc_data, config_protocol); diff --git a/libs/libarchopenfpga/src/write_xml_config_protocol.cpp b/libs/libarchopenfpga/src/write_xml_config_protocol.cpp index d215ee8c9..5f5eb6dcb 100644 --- a/libs/libarchopenfpga/src/write_xml_config_protocol.cpp +++ b/libs/libarchopenfpga/src/write_xml_config_protocol.cpp @@ -12,6 +12,7 @@ #include "vtr_log.h" /* Headers from readarchopenfpga library */ +#include "config_protocol_xml_constants.h" #include "write_xml_config_protocol.h" #include "write_xml_utils.h" @@ -31,33 +32,54 @@ static void write_xml_config_organization(std::fstream& fp, const char* fname, write_xml_attribute( fp, "circuit_model_name", circuit_lib.model_name(config_protocol.memory_model()).c_str()); + write_xml_attribute( + fp, XML_CONFIG_PROTOCOL_NUM_REGIONS_ATTR, + config_protocol.num_regions()); fp << "/>" << "\n"; - /* Output BL/WL protocols */ - fp << "\t\t\t" - << "" - << "\n"; + /* CCFF protocol details */ + if (config_protocol.type() == CONFIG_MEM_SCAN_CHAIN) { + for (openfpga::BasicPort port : config_protocol.prog_clock_ports()) { + fp << "\t\t\t" + << "<" << XML_CONFIG_PROTOCOL_CCFF_PROG_CLOCK_NODE_NAME; + write_xml_attribute( + fp, XML_CONFIG_PROTOCOL_CCFF_PROG_CLOCK_PORT_ATTR, + port.to_verilog_string().c_str()); + write_xml_attribute( + fp, XML_CONFIG_PROTOCOL_CCFF_PROG_CLOCK_INDICES_ATTR, + config_protocol.prog_clock_port_ccff_head_indices(port).c_str()); + fp << "/>" + << "\n"; + } + } - fp << "\t\t\t" - << "" - << "\n"; + /* BL/WL protocol details */ + if (config_protocol.type() == CONFIG_MEM_QL_MEMORY_BANK) { + fp << "\t\t\t" + << "" + << "\n"; + + fp << "\t\t\t" + << "" + << "\n"; + } fp << "\t" << "" diff --git a/libs/libopenfpgautil/src/openfpga_port.cpp b/libs/libopenfpgautil/src/openfpga_port.cpp index 5d583bc6b..61bf32bf5 100644 --- a/libs/libopenfpgautil/src/openfpga_port.cpp +++ b/libs/libopenfpgautil/src/openfpga_port.cpp @@ -106,6 +106,10 @@ bool BasicPort::contained(const BasicPort& portA) const { /* Set original port width */ size_t BasicPort::get_origin_port_width() const { return origin_port_width_; } +std::string BasicPort::to_verilog_string() const { + return get_name() + "[" + std::to_string(get_lsb()) + ":" + std::to_string(get_msb()) + "]"; +} + /************************************************************************ * Overloaded operators ***********************************************************************/ diff --git a/libs/libopenfpgautil/src/openfpga_port.h b/libs/libopenfpgautil/src/openfpga_port.h index b2759f273..40b0a3fe4 100644 --- a/libs/libopenfpgautil/src/openfpga_port.h +++ b/libs/libopenfpgautil/src/openfpga_port.h @@ -35,6 +35,7 @@ class BasicPort { bool contained(const BasicPort& portA) const; /* Check if a port is contained by this port */ size_t get_origin_port_width() const; + std::string to_verilog_string() const; /* Generate verilog-style string, e.g., a[0:1] */ public: /* Mutators */ void set(const BasicPort& basic_port); /* copy */ From 14892a6146fe87737535e6507eb6350bca21aeaa Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 22 Apr 2023 00:02:24 +0000 Subject: [PATCH 143/166] Updated Patch Count --- VERSION.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION.md b/VERSION.md index 21d8cb3bc..2b92ea739 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -1.2.929 +1.2.935 From f70cc3282488ae25ccecab699893e9a6188d1540 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 22 Apr 2023 08:46:36 +0800 Subject: [PATCH 144/166] [core] developing checkers for configuration protocol w.r.t. the programming clocks --- .../src/base/openfpga_read_arch_template.h | 2 +- openfpga/src/utils/check_config_protocol.cpp | 83 +++++++++++++++++++ openfpga/src/utils/check_config_protocol.h | 22 +++++ 3 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 openfpga/src/utils/check_config_protocol.cpp create mode 100644 openfpga/src/utils/check_config_protocol.h diff --git a/openfpga/src/base/openfpga_read_arch_template.h b/openfpga/src/base/openfpga_read_arch_template.h index 9d7f32b0a..b7c626755 100644 --- a/openfpga/src/base/openfpga_read_arch_template.h +++ b/openfpga/src/base/openfpga_read_arch_template.h @@ -55,7 +55,7 @@ int read_openfpga_arch_template(T& openfpga_context, const Command& cmd, return CMD_EXEC_FATAL_ERROR; } - if (false == check_configurable_memory_circuit_model( + if (false == check_config_protocol( openfpga_context.arch().config_protocol, openfpga_context.arch().circuit_lib)) { return CMD_EXEC_FATAL_ERROR; diff --git a/openfpga/src/utils/check_config_protocol.cpp b/openfpga/src/utils/check_config_protocol.cpp new file mode 100644 index 000000000..194f73436 --- /dev/null +++ b/openfpga/src/utils/check_config_protocol.cpp @@ -0,0 +1,83 @@ +/************************************************************************ + * Check functions for the content of config protocol to avoid conflicts with + * other data structures + * These functions are not universal methods for the ConfigProtocol class + * They are made to ease the development in some specific purposes + * Please classify such functions in this file + ***********************************************************************/ +#include "circuit_library_utils.h" +#include "check_config_protocol.h" +#include "vtr_assert.h" +#include "vtr_log.h" + +/* begin namespace openfpga */ +namespace openfpga { + +/******************************************************************** + * Check if the programming clock port defined in configuration protocol is a valid global programming clock of a ccff model + *******************************************************************/ +int check_config_protocol_programming_clock( + const ConfigProtocol& config_protocol, const CircuitLibrary& circuit_lib) { + int num_err = 0; + /* Programming clock is only available for CCFF */ + if (config_protocol.type() == CONFIG_MEM_SCAN_CHAIN) { + return num_err; + } + /* Must find a CCFF model */ + std::vector ccff_models = circuit_lib.models_by_type(CIRCUIT_MODEL_CCFF); + if (ccff_models.empty()) { + VTR_LOG_ERROR("Expect at least one CCFF model to be defined in circuit library!\n"); + num_err++; + } + /* Try to match the programming clock port name with the CCFF port name */ + for (BasicPort prog_clk_port : config_protocol.prog_clock_ports()) { + bool port_match = false; + for (CircuitModelId ccff_model : ccff_models) { + CircuitPortId circuit_port = circuit_lib.model_port(ccff_model, prog_clk_port.get_name()); + if (circuit_port) { + port_match = true; + /* Ensure this is a programming clock and a global port */ + if (!circuit_lib.port_is_global(circuit_port)) { + VTR_LOG_ERROR("Expect the programming clock '%s' to be a global port but not!\n", prog_clk_port.get_name().c_str()); + num_err++; + } + if (circuit_lib.port_type(circuit_port) != CIRCUIT_MODEL_PORT_CLOCK) { + VTR_LOG_ERROR("Expect the programming clock '%s' to be a clock port but not!\n", prog_clk_port.get_name().c_str()); + num_err++; + } + if (!circuit_lib.port_is_prog(circuit_port)) { + VTR_LOG_ERROR("Expect the programming clock '%s' to be a programming port but not!\n", prog_clk_port.get_name().c_str()); + num_err++; + } + } + } + if (!port_match) { + VTR_LOG_ERROR("Fail to find a port of any CCFF model that matches the programming clock definition (Expect port name: '%s')!\n", prog_clk_port.get_name().c_str()); + num_err++; + } + } + + return num_err; +} + +/******************************************************************** + * Check if the configuration protocol is valid without any conflict with + * circuit library content. + *******************************************************************/ +bool check_config_protocol( + const ConfigProtocol& config_protocol, const CircuitLibrary& circuit_lib) { + int num_err = 0; + if (false == check_configurable_memory_circuit_model( + config_protocol, + circuit_lib)) { + num_err++; + } + + num_err += check_config_protocol_programming_clock( + config_protocol, circuit_lib); + + VTR_LOG("Found %ld errors when checking configuration protocol!\n", num_err); + return (0 == num_err); +} + +} /* end namespace openfpga */ diff --git a/openfpga/src/utils/check_config_protocol.h b/openfpga/src/utils/check_config_protocol.h new file mode 100644 index 000000000..8b4b47ba1 --- /dev/null +++ b/openfpga/src/utils/check_config_protocol.h @@ -0,0 +1,22 @@ +#ifndef CHECK_CONFIG_PROTOCOL_H +#define CHECK_CONFIG_PROTOCOL_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +#include "config_protocol.h" +#include "circuit_library.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ + +/* begin namespace openfpga */ +namespace openfpga { + +bool check_config_protocol( + const ConfigProtocol& config_protocol, const CircuitLibrary& circuit_lib); + +} /* end namespace openfpga */ + +#endif From 5e8e9823340607106167d19406751c0365516e92 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 22 Apr 2023 12:44:34 +0800 Subject: [PATCH 145/166] [core] finished developing checkers --- libs/libarchopenfpga/src/config_protocol.cpp | 71 +++++++++++++++++++- libs/libarchopenfpga/src/config_protocol.h | 15 ++++- openfpga/src/utils/check_config_protocol.cpp | 7 +- 3 files changed, 88 insertions(+), 5 deletions(-) diff --git a/libs/libarchopenfpga/src/config_protocol.cpp b/libs/libarchopenfpga/src/config_protocol.cpp index 51fbecea6..57a780134 100644 --- a/libs/libarchopenfpga/src/config_protocol.cpp +++ b/libs/libarchopenfpga/src/config_protocol.cpp @@ -37,9 +37,9 @@ std::vector ConfigProtocol::prog_clock_ports() const { std::string ConfigProtocol::prog_clock_port_ccff_head_indices(const BasicPort& port) const { std::string ret(""); - auto result = prog_clk_ccff_head_indices.find(port); - if (result != prog_clk_ccff_head_indices.end()) { - for (size_t idx : result->second) { + std::vector raw = prog_clock_port_ccff_head_indices(port); + if (!raw.empty()) { + for (size_t idx : raw) { /* TODO: We need a join function */ ret += std::to_string(idx) + std::string(INDICE_STRING_DELIM); } @@ -49,6 +49,15 @@ std::string ConfigProtocol::prog_clock_port_ccff_head_indices(const BasicPort& p return ret; } +std::vector ConfigProtocol::prog_clock_port_ccff_head_indices(const BasicPort& port) const { + std::vector ret; + auto result = prog_clk_ccff_head_indices.find(port); + if (result != prog_clk_ccff_head_indices.end()) { + return result->second; + } + return ret; +} + e_blwl_protocol_type ConfigProtocol::bl_protocol_type() const { return bl_protocol_type_; } @@ -192,3 +201,59 @@ void ConfigProtocol::set_wl_num_banks(const size_t& num_banks) { } wl_num_banks_ = num_banks; } + +/************************************************************************ + * Private Validators + ***********************************************************************/ +int ConfigProtocol::validate_ccff_prog_clocks() { + int num_err = 0; + /* Initialize scoreboard */ + std::vector ccff_head_scoreboard(num_regions(), 0); + for (BasicPort port : prog_clock_ports()) { + /* Must be valid first */ + if (port.is_valid()) { + VTR_LOG_ERROR("Programming clock '%s[%d:%d]' is not a valid port!\n", port.get_name().c_str(), port.get_lsb(), port.get_msb()); + num_err++; + } + /* Each port should have a width of 1 */ + if (port.get_width() != 1) { + VTR_LOG_ERROR("Expect each programming clock has a size of 1 in the definition. '%s[%d:%d]' violates the rule!\n", port.get_name().c_str(), port.get_lsb(), port.get_msb()); + num_err++; + } + /* Fill scoreboard */ + for (size_t ccff_head_idx : prog_clock_port_ccff_head_indices(port)) { + if (ccff_head_idx => ccff_head_scoreboard.size()) { + VTR_LOG_ERROR("Programming clock '%s[%d:%d]' controlls an invalid ccff head '%ld' (Expect [0, '%ld'])!\n", port.get_name().c_str(), port.get_lsb(), port.get_msb(), ccff_head_idx, ccff_head_scoreboard.size() - 1); + num_err++; + } + ccff_head_scoreboard[ccff_head_idx]++; + } + } + if (prog_clock_ports().size() != num_regions()) { + VTR_LOG_ERROR("Number of programming clocks '%ld' does not match the number of configuration regions '%ld'!\n", prog_clock_ports().size(), num_regions()); + num_err++; + } + for (size_t iregion = 0; iregion < ccff_head_scoreboard.size(); iregion++) { + if (ccff_head_scoreboard[iregion] == 0) { + VTR_LOG_ERROR("Configuration chain '%ld' is not driven by any programming clock!\n", iregion); + num_err++; + } + if (ccff_head_scoreboard[iregion] > 1) { + VTR_LOG_ERROR("Configuration chain '%ld' is driven by %ld programming clock!\n", iregion, ccff_head_scoreboard[iregion]); + num_err++; + } + } + return num_err; +} + +/************************************************************************ + * Public Validators + ***********************************************************************/ +int ConfigProtocol::validate() { + int num_err = 0; + if (type() == CONFIG_MEM_SCAN_CHAIN) { + num_err += validate_ccff_prog_clocks(); + } + return num_err; +} + diff --git a/libs/libarchopenfpga/src/config_protocol.h b/libs/libarchopenfpga/src/config_protocol.h index 960a25f06..740b43574 100644 --- a/libs/libarchopenfpga/src/config_protocol.h +++ b/libs/libarchopenfpga/src/config_protocol.h @@ -34,6 +34,7 @@ class ConfigProtocol { std::vector prog_clock_ports() const; /* Get a list of programming clock ports */ std::string prog_clock_port_ccff_head_indices(const BasicPort& port) const; + std::vector prog_clock_port_ccff_head_indices(const BasicPort& port) const; e_blwl_protocol_type bl_protocol_type() const; std::string bl_memory_model_name() const; @@ -43,7 +44,6 @@ class ConfigProtocol { std::string wl_memory_model_name() const; CircuitModelId wl_memory_model() const; size_t wl_num_banks() const; - public: /* Public Mutators */ void set_type(const e_config_protocol_type& type); void set_memory_model_name(const std::string& memory_model_name); @@ -62,6 +62,19 @@ class ConfigProtocol { void set_wl_memory_model(const CircuitModelId& memory_model); void set_wl_num_banks(const size_t& num_banks); + public: /* Public validators */ + /* Check if internal data has any conflicts to each other. Return number of errors detected */ + int validate() const; + + private: /* Private validators */ + /* For configuration chains, to validate if + * - programming clocks is smaller than the number of regions + * - programming clocks does not have any conflicts in controlling regions (no overlaps) + * - each region has been assigned to a programming clock + * Return number of errors detected + */ + int validate_ccff_prog_clocks() const; + private: /* Internal data */ /* The type of configuration protocol. * In other words, it is about how to organize and access each configurable diff --git a/openfpga/src/utils/check_config_protocol.cpp b/openfpga/src/utils/check_config_protocol.cpp index 194f73436..c2c2c3dbd 100644 --- a/openfpga/src/utils/check_config_protocol.cpp +++ b/openfpga/src/utils/check_config_protocol.cpp @@ -67,7 +67,12 @@ int check_config_protocol_programming_clock( bool check_config_protocol( const ConfigProtocol& config_protocol, const CircuitLibrary& circuit_lib) { int num_err = 0; - if (false == check_configurable_memory_circuit_model( + + if (!config_protocol.validate()) { + num_err++; + } + + if (!check_configurable_memory_circuit_model( config_protocol, circuit_lib)) { num_err++; From 297a23dee7bf1c1cec3fdddc89b31b9554ee949d Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 22 Apr 2023 15:09:39 +0800 Subject: [PATCH 146/166] [core] fixed syntax errors --- libs/libarchopenfpga/src/config_protocol.cpp | 39 ++++++++++--------- libs/libarchopenfpga/src/config_protocol.h | 11 +++--- .../src/read_xml_config_protocol.cpp | 2 +- .../src/write_xml_config_protocol.cpp | 2 +- .../src/base/openfpga_read_arch_template.h | 1 + openfpga/src/utils/check_config_protocol.cpp | 2 +- 6 files changed, 30 insertions(+), 27 deletions(-) diff --git a/libs/libarchopenfpga/src/config_protocol.cpp b/libs/libarchopenfpga/src/config_protocol.cpp index 57a780134..22e194ed8 100644 --- a/libs/libarchopenfpga/src/config_protocol.cpp +++ b/libs/libarchopenfpga/src/config_protocol.cpp @@ -1,3 +1,4 @@ +#include "openfpga_tokenizer.h" #include "config_protocol.h" #include "vtr_assert.h" @@ -27,32 +28,32 @@ CircuitModelId ConfigProtocol::memory_model() const { return memory_model_; } int ConfigProtocol::num_regions() const { return num_regions_; } -std::vector ConfigProtocol::prog_clock_ports() const { - std::vector keys; +std::vector ConfigProtocol::prog_clock_ports() const { + std::vector keys; for (const auto& [k, v] : prog_clk_ccff_head_indices_) { keys.push_back(k); } return keys; } -std::string ConfigProtocol::prog_clock_port_ccff_head_indices(const BasicPort& port) const { +std::string ConfigProtocol::prog_clock_port_ccff_head_indices_str(const openfpga::BasicPort& port) const { std::string ret(""); std::vector raw = prog_clock_port_ccff_head_indices(port); if (!raw.empty()) { for (size_t idx : raw) { /* TODO: We need a join function */ - ret += std::to_string(idx) + std::string(INDICE_STRING_DELIM); + ret += std::to_string(idx) + std::to_string(INDICE_STRING_DELIM_); } /* Remove the last comma */ - ret.pop(); + ret.pop_back(); } return ret; } -std::vector ConfigProtocol::prog_clock_port_ccff_head_indices(const BasicPort& port) const { +std::vector ConfigProtocol::prog_clock_port_ccff_head_indices(const openfpga::BasicPort& port) const { std::vector ret; - auto result = prog_clk_ccff_head_indices.find(port); - if (result != prog_clk_ccff_head_indices.end()) { + auto result = prog_clk_ccff_head_indices_.find(port); + if (result != prog_clk_ccff_head_indices_.end()) { return result->second; } return ret; @@ -106,16 +107,16 @@ void ConfigProtocol::set_num_regions(const int& num_regions) { num_regions_ = num_regions; } -void ConfigProtocol::set_prog_clock_port_ccff_head_indices_pair(const BasicPort& port, const std::string& indices_str) { +void ConfigProtocol::set_prog_clock_port_ccff_head_indices_pair(const openfpga::BasicPort& port, const std::string& indices_str) { openfpga::StringToken tokenizer(indices_str); - std::vector token_int; + std::vector token_int; token_int.reserve(tokenizer.split(INDICE_STRING_DELIM_).size()); for (std::string token : tokenizer.split(INDICE_STRING_DELIM_)) { - token_int.push_back(std::atoi(token)); + token_int.push_back(std::stoi(token)); } - auto result = prog_clk_ccff_head_indices.find(port); - if (result != prog_clk_ccff_head_indices.end()) { - VTR_LOG_WARN("Overwrite the pair between programming clock port '%s[%d:%d]' and ccff head indices (previous: '%s', current: '%s')!\n", port.get_name().c_str(), port.get_lsb(), port.get_msb(), prog_clock_port_ccff_head_indices(port).c_str(), indices_str.c_str()); + auto result = prog_clk_ccff_head_indices_.find(port); + if (result != prog_clk_ccff_head_indices_.end()) { + VTR_LOG_WARN("Overwrite the pair between programming clock port '%s[%d:%d]' and ccff head indices (previous: '%s', current: '%s')!\n", port.get_name().c_str(), port.get_lsb(), port.get_msb(), prog_clock_port_ccff_head_indices_str(port).c_str(), indices_str.c_str()); } prog_clk_ccff_head_indices_[port] = token_int; } @@ -205,11 +206,11 @@ void ConfigProtocol::set_wl_num_banks(const size_t& num_banks) { /************************************************************************ * Private Validators ***********************************************************************/ -int ConfigProtocol::validate_ccff_prog_clocks() { +int ConfigProtocol::validate_ccff_prog_clocks() const { int num_err = 0; /* Initialize scoreboard */ std::vector ccff_head_scoreboard(num_regions(), 0); - for (BasicPort port : prog_clock_ports()) { + for (openfpga::BasicPort port : prog_clock_ports()) { /* Must be valid first */ if (port.is_valid()) { VTR_LOG_ERROR("Programming clock '%s[%d:%d]' is not a valid port!\n", port.get_name().c_str(), port.get_lsb(), port.get_msb()); @@ -222,14 +223,14 @@ int ConfigProtocol::validate_ccff_prog_clocks() { } /* Fill scoreboard */ for (size_t ccff_head_idx : prog_clock_port_ccff_head_indices(port)) { - if (ccff_head_idx => ccff_head_scoreboard.size()) { + if (ccff_head_idx >= ccff_head_scoreboard.size()) { VTR_LOG_ERROR("Programming clock '%s[%d:%d]' controlls an invalid ccff head '%ld' (Expect [0, '%ld'])!\n", port.get_name().c_str(), port.get_lsb(), port.get_msb(), ccff_head_idx, ccff_head_scoreboard.size() - 1); num_err++; } ccff_head_scoreboard[ccff_head_idx]++; } } - if (prog_clock_ports().size() != num_regions()) { + if (prog_clock_ports().size() != (size_t)num_regions()) { VTR_LOG_ERROR("Number of programming clocks '%ld' does not match the number of configuration regions '%ld'!\n", prog_clock_ports().size(), num_regions()); num_err++; } @@ -249,7 +250,7 @@ int ConfigProtocol::validate_ccff_prog_clocks() { /************************************************************************ * Public Validators ***********************************************************************/ -int ConfigProtocol::validate() { +int ConfigProtocol::validate() const { int num_err = 0; if (type() == CONFIG_MEM_SCAN_CHAIN) { num_err += validate_ccff_prog_clocks(); diff --git a/libs/libarchopenfpga/src/config_protocol.h b/libs/libarchopenfpga/src/config_protocol.h index 740b43574..93d0d2c6c 100644 --- a/libs/libarchopenfpga/src/config_protocol.h +++ b/libs/libarchopenfpga/src/config_protocol.h @@ -2,6 +2,7 @@ #define CONFIG_PROTOCOL_H #include +#include #include "circuit_library_fwd.h" #include "circuit_types.h" @@ -31,10 +32,10 @@ class ConfigProtocol { int num_regions() const; /* Get a list of programming clock ports */ - std::vector prog_clock_ports() const; + std::vector prog_clock_ports() const; /* Get a list of programming clock ports */ - std::string prog_clock_port_ccff_head_indices(const BasicPort& port) const; - std::vector prog_clock_port_ccff_head_indices(const BasicPort& port) const; + std::string prog_clock_port_ccff_head_indices_str(const openfpga::BasicPort& port) const; + std::vector prog_clock_port_ccff_head_indices(const openfpga::BasicPort& port) const; e_blwl_protocol_type bl_protocol_type() const; std::string bl_memory_model_name() const; @@ -51,7 +52,7 @@ class ConfigProtocol { void set_num_regions(const int& num_regions); /* Add a pair of programming clock port and ccff head indices. This API will parse the index list, e.g., "0,1" to a vector of integers [0 1] */ - void set_prog_clock_port_ccff_head_indices_pair(const BasicPort& port, const std::string& indices_str); + void set_prog_clock_port_ccff_head_indices_pair(const openfpga::BasicPort& port, const std::string& indices_str); void set_bl_protocol_type(const e_blwl_protocol_type& type); void set_bl_memory_model_name(const std::string& memory_model_name); @@ -90,7 +91,7 @@ class ConfigProtocol { int num_regions_; /* Programming clock managment: This is only applicable to configuration chain protocols */ - std::map> prog_clk_ccff_head_indices_; + std::map> prog_clk_ccff_head_indices_; char INDICE_STRING_DELIM_; /* BL & WL protocol: This is only applicable to memory-bank configuration diff --git a/libs/libarchopenfpga/src/read_xml_config_protocol.cpp b/libs/libarchopenfpga/src/read_xml_config_protocol.cpp index 8dcada58e..7dc47c1ee 100644 --- a/libs/libarchopenfpga/src/read_xml_config_protocol.cpp +++ b/libs/libarchopenfpga/src/read_xml_config_protocol.cpp @@ -60,7 +60,7 @@ static void read_xml_ccff_prog_clock(pugi::xml_node& xml_progclk, std::string indices_attr = get_attribute(xml_progclk, XML_CONFIG_PROTOCOL_CCFF_PROG_CLOCK_INDICES_ATTR, loc_data).as_string(); - BasicPort port = openfpga::PortParser(port_attr).port(); + openfpga::BasicPort port = openfpga::PortParser(port_attr).port(); config_protocol.set_prog_clock_port_ccff_head_indices_pair(port, indices_attr); } diff --git a/libs/libarchopenfpga/src/write_xml_config_protocol.cpp b/libs/libarchopenfpga/src/write_xml_config_protocol.cpp index 5f5eb6dcb..212614ff6 100644 --- a/libs/libarchopenfpga/src/write_xml_config_protocol.cpp +++ b/libs/libarchopenfpga/src/write_xml_config_protocol.cpp @@ -48,7 +48,7 @@ static void write_xml_config_organization(std::fstream& fp, const char* fname, port.to_verilog_string().c_str()); write_xml_attribute( fp, XML_CONFIG_PROTOCOL_CCFF_PROG_CLOCK_INDICES_ATTR, - config_protocol.prog_clock_port_ccff_head_indices(port).c_str()); + config_protocol.prog_clock_port_ccff_head_indices_str(port).c_str()); fp << "/>" << "\n"; } diff --git a/openfpga/src/base/openfpga_read_arch_template.h b/openfpga/src/base/openfpga_read_arch_template.h index b7c626755..b99d48e95 100644 --- a/openfpga/src/base/openfpga_read_arch_template.h +++ b/openfpga/src/base/openfpga_read_arch_template.h @@ -4,6 +4,7 @@ * This file includes functions to read an OpenFPGA architecture file * which are built on the libarchopenfpga library *******************************************************************/ +#include "check_config_protocol.h" #include "check_circuit_library.h" #include "check_tile_annotation.h" #include "circuit_library_utils.h" diff --git a/openfpga/src/utils/check_config_protocol.cpp b/openfpga/src/utils/check_config_protocol.cpp index c2c2c3dbd..518adb69a 100644 --- a/openfpga/src/utils/check_config_protocol.cpp +++ b/openfpga/src/utils/check_config_protocol.cpp @@ -16,7 +16,7 @@ namespace openfpga { /******************************************************************** * Check if the programming clock port defined in configuration protocol is a valid global programming clock of a ccff model *******************************************************************/ -int check_config_protocol_programming_clock( +static int check_config_protocol_programming_clock( const ConfigProtocol& config_protocol, const CircuitLibrary& circuit_lib) { int num_err = 0; /* Programming clock is only available for CCFF */ From ea8ae29b5308e68b60db4281c87ce154c3acf0af Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 22 Apr 2023 15:12:38 +0800 Subject: [PATCH 147/166] [core] code format --- libs/libarchopenfpga/src/config_protocol.cpp | 57 ++++++++++++------- libs/libarchopenfpga/src/config_protocol.h | 31 ++++++---- .../src/config_protocol_xml_constants.h | 8 ++- .../src/read_xml_config_protocol.cpp | 29 ++++++---- .../src/write_xml_config_protocol.cpp | 16 +++--- libs/libopenfpgautil/src/openfpga_port.cpp | 3 +- libs/libopenfpgautil/src/openfpga_port.h | 3 +- .../src/base/openfpga_read_arch_template.h | 7 +-- openfpga/src/utils/check_config_protocol.cpp | 47 +++++++++------ openfpga/src/utils/check_config_protocol.h | 6 +- 10 files changed, 128 insertions(+), 79 deletions(-) diff --git a/libs/libarchopenfpga/src/config_protocol.cpp b/libs/libarchopenfpga/src/config_protocol.cpp index 22e194ed8..7a3d59cf4 100644 --- a/libs/libarchopenfpga/src/config_protocol.cpp +++ b/libs/libarchopenfpga/src/config_protocol.cpp @@ -1,6 +1,6 @@ -#include "openfpga_tokenizer.h" #include "config_protocol.h" +#include "openfpga_tokenizer.h" #include "vtr_assert.h" #include "vtr_log.h" @@ -11,9 +11,7 @@ /************************************************************************ * Constructors ***********************************************************************/ -ConfigProtocol::ConfigProtocol() { - INDICE_STRING_DELIM_ = ','; -} +ConfigProtocol::ConfigProtocol() { INDICE_STRING_DELIM_ = ','; } /************************************************************************ * Public Accessors @@ -36,7 +34,8 @@ std::vector ConfigProtocol::prog_clock_ports() const { return keys; } -std::string ConfigProtocol::prog_clock_port_ccff_head_indices_str(const openfpga::BasicPort& port) const { +std::string ConfigProtocol::prog_clock_port_ccff_head_indices_str( + const openfpga::BasicPort& port) const { std::string ret(""); std::vector raw = prog_clock_port_ccff_head_indices(port); if (!raw.empty()) { @@ -50,7 +49,8 @@ std::string ConfigProtocol::prog_clock_port_ccff_head_indices_str(const openfpga return ret; } -std::vector ConfigProtocol::prog_clock_port_ccff_head_indices(const openfpga::BasicPort& port) const { +std::vector ConfigProtocol::prog_clock_port_ccff_head_indices( + const openfpga::BasicPort& port) const { std::vector ret; auto result = prog_clk_ccff_head_indices_.find(port); if (result != prog_clk_ccff_head_indices_.end()) { @@ -107,7 +107,8 @@ void ConfigProtocol::set_num_regions(const int& num_regions) { num_regions_ = num_regions; } -void ConfigProtocol::set_prog_clock_port_ccff_head_indices_pair(const openfpga::BasicPort& port, const std::string& indices_str) { +void ConfigProtocol::set_prog_clock_port_ccff_head_indices_pair( + const openfpga::BasicPort& port, const std::string& indices_str) { openfpga::StringToken tokenizer(indices_str); std::vector token_int; token_int.reserve(tokenizer.split(INDICE_STRING_DELIM_).size()); @@ -116,7 +117,11 @@ void ConfigProtocol::set_prog_clock_port_ccff_head_indices_pair(const openfpga:: } auto result = prog_clk_ccff_head_indices_.find(port); if (result != prog_clk_ccff_head_indices_.end()) { - VTR_LOG_WARN("Overwrite the pair between programming clock port '%s[%d:%d]' and ccff head indices (previous: '%s', current: '%s')!\n", port.get_name().c_str(), port.get_lsb(), port.get_msb(), prog_clock_port_ccff_head_indices_str(port).c_str(), indices_str.c_str()); + VTR_LOG_WARN( + "Overwrite the pair between programming clock port '%s[%d:%d]' and ccff " + "head indices (previous: '%s', current: '%s')!\n", + port.get_name().c_str(), port.get_lsb(), port.get_msb(), + prog_clock_port_ccff_head_indices_str(port).c_str(), indices_str.c_str()); } prog_clk_ccff_head_indices_[port] = token_int; } @@ -211,40 +216,55 @@ int ConfigProtocol::validate_ccff_prog_clocks() const { /* Initialize scoreboard */ std::vector ccff_head_scoreboard(num_regions(), 0); for (openfpga::BasicPort port : prog_clock_ports()) { - /* Must be valid first */ + /* Must be valid first */ if (port.is_valid()) { - VTR_LOG_ERROR("Programming clock '%s[%d:%d]' is not a valid port!\n", port.get_name().c_str(), port.get_lsb(), port.get_msb()); + VTR_LOG_ERROR("Programming clock '%s[%d:%d]' is not a valid port!\n", + port.get_name().c_str(), port.get_lsb(), port.get_msb()); num_err++; } - /* Each port should have a width of 1 */ + /* Each port should have a width of 1 */ if (port.get_width() != 1) { - VTR_LOG_ERROR("Expect each programming clock has a size of 1 in the definition. '%s[%d:%d]' violates the rule!\n", port.get_name().c_str(), port.get_lsb(), port.get_msb()); + VTR_LOG_ERROR( + "Expect each programming clock has a size of 1 in the definition. " + "'%s[%d:%d]' violates the rule!\n", + port.get_name().c_str(), port.get_lsb(), port.get_msb()); num_err++; } /* Fill scoreboard */ for (size_t ccff_head_idx : prog_clock_port_ccff_head_indices(port)) { if (ccff_head_idx >= ccff_head_scoreboard.size()) { - VTR_LOG_ERROR("Programming clock '%s[%d:%d]' controlls an invalid ccff head '%ld' (Expect [0, '%ld'])!\n", port.get_name().c_str(), port.get_lsb(), port.get_msb(), ccff_head_idx, ccff_head_scoreboard.size() - 1); + VTR_LOG_ERROR( + "Programming clock '%s[%d:%d]' controlls an invalid ccff head '%ld' " + "(Expect [0, '%ld'])!\n", + port.get_name().c_str(), port.get_lsb(), port.get_msb(), + ccff_head_idx, ccff_head_scoreboard.size() - 1); num_err++; } ccff_head_scoreboard[ccff_head_idx]++; } } if (prog_clock_ports().size() != (size_t)num_regions()) { - VTR_LOG_ERROR("Number of programming clocks '%ld' does not match the number of configuration regions '%ld'!\n", prog_clock_ports().size(), num_regions()); + VTR_LOG_ERROR( + "Number of programming clocks '%ld' does not match the number of " + "configuration regions '%ld'!\n", + prog_clock_ports().size(), num_regions()); num_err++; } for (size_t iregion = 0; iregion < ccff_head_scoreboard.size(); iregion++) { if (ccff_head_scoreboard[iregion] == 0) { - VTR_LOG_ERROR("Configuration chain '%ld' is not driven by any programming clock!\n", iregion); + VTR_LOG_ERROR( + "Configuration chain '%ld' is not driven by any programming clock!\n", + iregion); num_err++; } if (ccff_head_scoreboard[iregion] > 1) { - VTR_LOG_ERROR("Configuration chain '%ld' is driven by %ld programming clock!\n", iregion, ccff_head_scoreboard[iregion]); + VTR_LOG_ERROR( + "Configuration chain '%ld' is driven by %ld programming clock!\n", + iregion, ccff_head_scoreboard[iregion]); num_err++; } } - return num_err; + return num_err; } /************************************************************************ @@ -255,6 +275,5 @@ int ConfigProtocol::validate() const { if (type() == CONFIG_MEM_SCAN_CHAIN) { num_err += validate_ccff_prog_clocks(); } - return num_err; + return num_err; } - diff --git a/libs/libarchopenfpga/src/config_protocol.h b/libs/libarchopenfpga/src/config_protocol.h index 93d0d2c6c..954600f65 100644 --- a/libs/libarchopenfpga/src/config_protocol.h +++ b/libs/libarchopenfpga/src/config_protocol.h @@ -1,8 +1,8 @@ #ifndef CONFIG_PROTOCOL_H #define CONFIG_PROTOCOL_H -#include #include +#include #include "circuit_library_fwd.h" #include "circuit_types.h" @@ -30,12 +30,14 @@ class ConfigProtocol { std::string memory_model_name() const; CircuitModelId memory_model() const; int num_regions() const; - + /* Get a list of programming clock ports */ std::vector prog_clock_ports() const; /* Get a list of programming clock ports */ - std::string prog_clock_port_ccff_head_indices_str(const openfpga::BasicPort& port) const; - std::vector prog_clock_port_ccff_head_indices(const openfpga::BasicPort& port) const; + std::string prog_clock_port_ccff_head_indices_str( + const openfpga::BasicPort& port) const; + std::vector prog_clock_port_ccff_head_indices( + const openfpga::BasicPort& port) const; e_blwl_protocol_type bl_protocol_type() const; std::string bl_memory_model_name() const; @@ -45,14 +47,17 @@ class ConfigProtocol { std::string wl_memory_model_name() const; CircuitModelId wl_memory_model() const; size_t wl_num_banks() const; + public: /* Public Mutators */ void set_type(const e_config_protocol_type& type); void set_memory_model_name(const std::string& memory_model_name); void set_memory_model(const CircuitModelId& memory_model); void set_num_regions(const int& num_regions); - /* Add a pair of programming clock port and ccff head indices. This API will parse the index list, e.g., "0,1" to a vector of integers [0 1] */ - void set_prog_clock_port_ccff_head_indices_pair(const openfpga::BasicPort& port, const std::string& indices_str); + /* Add a pair of programming clock port and ccff head indices. This API will + * parse the index list, e.g., "0,1" to a vector of integers [0 1] */ + void set_prog_clock_port_ccff_head_indices_pair( + const openfpga::BasicPort& port, const std::string& indices_str); void set_bl_protocol_type(const e_blwl_protocol_type& type); void set_bl_memory_model_name(const std::string& memory_model_name); @@ -64,13 +69,15 @@ class ConfigProtocol { void set_wl_num_banks(const size_t& num_banks); public: /* Public validators */ - /* Check if internal data has any conflicts to each other. Return number of errors detected */ + /* Check if internal data has any conflicts to each other. Return number of + * errors detected */ int validate() const; private: /* Private validators */ - /* For configuration chains, to validate if + /* For configuration chains, to validate if * - programming clocks is smaller than the number of regions - * - programming clocks does not have any conflicts in controlling regions (no overlaps) + * - programming clocks does not have any conflicts in controlling regions (no + * overlaps) * - each region has been assigned to a programming clock * Return number of errors detected */ @@ -90,8 +97,10 @@ class ConfigProtocol { /* Number of configurable regions */ int num_regions_; - /* Programming clock managment: This is only applicable to configuration chain protocols */ - std::map> prog_clk_ccff_head_indices_; + /* Programming clock managment: This is only applicable to configuration chain + * protocols */ + std::map> + prog_clk_ccff_head_indices_; char INDICE_STRING_DELIM_; /* BL & WL protocol: This is only applicable to memory-bank configuration diff --git a/libs/libarchopenfpga/src/config_protocol_xml_constants.h b/libs/libarchopenfpga/src/config_protocol_xml_constants.h index 6647ea8ee..6978984b5 100644 --- a/libs/libarchopenfpga/src/config_protocol_xml_constants.h +++ b/libs/libarchopenfpga/src/config_protocol_xml_constants.h @@ -2,9 +2,11 @@ #define CONFIG_PROTOCOL_XML_CONSTANTS_H /* Constants for XML parsers, including readers and writers */ -constexpr const char* XML_CONFIG_PROTOCOL_NUM_REGIONS_ATTR = "num_regions"; -constexpr const char* XML_CONFIG_PROTOCOL_CCFF_PROG_CLOCK_NODE_NAME = "programming_clock"; +constexpr const char* XML_CONFIG_PROTOCOL_NUM_REGIONS_ATTR = "num_regions"; +constexpr const char* XML_CONFIG_PROTOCOL_CCFF_PROG_CLOCK_NODE_NAME = + "programming_clock"; constexpr const char* XML_CONFIG_PROTOCOL_CCFF_PROG_CLOCK_PORT_ATTR = "port"; -constexpr const char* XML_CONFIG_PROTOCOL_CCFF_PROG_CLOCK_INDICES_ATTR = "ccff_head_indices"; +constexpr const char* XML_CONFIG_PROTOCOL_CCFF_PROG_CLOCK_INDICES_ATTR = + "ccff_head_indices"; #endif diff --git a/libs/libarchopenfpga/src/read_xml_config_protocol.cpp b/libs/libarchopenfpga/src/read_xml_config_protocol.cpp index 7dc47c1ee..29580d123 100644 --- a/libs/libarchopenfpga/src/read_xml_config_protocol.cpp +++ b/libs/libarchopenfpga/src/read_xml_config_protocol.cpp @@ -15,8 +15,8 @@ /* Headers from libarchfpga */ #include "arch_error.h" #include "config_protocol_xml_constants.h" -#include "read_xml_config_protocol.h" #include "openfpga_port_parser.h" +#include "read_xml_config_protocol.h" #include "read_xml_util.h" /******************************************************************** @@ -48,21 +48,27 @@ static e_blwl_protocol_type string_to_blwl_protocol_type( } /******************************************************************** - * Parse XML codes of a to an object of configuration protocol + * Parse XML codes of a to an object of configuration + *protocol *******************************************************************/ static void read_xml_ccff_prog_clock(pugi::xml_node& xml_progclk, const pugiutil::loc_data& loc_data, ConfigProtocol& config_protocol) { /* Find the type of configuration protocol */ std::string port_attr = - get_attribute(xml_progclk, XML_CONFIG_PROTOCOL_CCFF_PROG_CLOCK_PORT_ATTR, loc_data).as_string(); + get_attribute(xml_progclk, XML_CONFIG_PROTOCOL_CCFF_PROG_CLOCK_PORT_ATTR, + loc_data) + .as_string(); std::string indices_attr = - get_attribute(xml_progclk, XML_CONFIG_PROTOCOL_CCFF_PROG_CLOCK_INDICES_ATTR, loc_data).as_string(); + get_attribute(xml_progclk, XML_CONFIG_PROTOCOL_CCFF_PROG_CLOCK_INDICES_ATTR, + loc_data) + .as_string(); - openfpga::BasicPort port = openfpga::PortParser(port_attr).port(); + openfpga::BasicPort port = openfpga::PortParser(port_attr).port(); - config_protocol.set_prog_clock_port_ccff_head_indices_pair(port, indices_attr); + config_protocol.set_prog_clock_port_ccff_head_indices_pair(port, + indices_attr); } /******************************************************************** @@ -162,10 +168,10 @@ static void read_xml_config_organization(pugi::xml_node& xml_config_orgz, /* Parse the number of configurable regions * At least 1 region should be defined, otherwise error out */ - config_protocol.set_num_regions(get_attribute(xml_config_orgz, XML_CONFIG_PROTOCOL_NUM_REGIONS_ATTR, - loc_data, - pugiutil::ReqOpt::OPTIONAL) - .as_int(1)); + config_protocol.set_num_regions( + get_attribute(xml_config_orgz, XML_CONFIG_PROTOCOL_NUM_REGIONS_ATTR, + loc_data, pugiutil::ReqOpt::OPTIONAL) + .as_int(1)); if (1 > config_protocol.num_regions()) { archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_config_orgz), "Invalid 'num_region=%d' definition. At least 1 region " @@ -177,7 +183,8 @@ static void read_xml_config_organization(pugi::xml_node& xml_config_orgz, if (config_protocol.type() == CONFIG_MEM_SCAN_CHAIN) { for (pugi::xml_node xml_progclk : xml_config_orgz.children()) { /* Error out if the XML child has an invalid name! */ - if (xml_progclk.name() != std::string(XML_CONFIG_PROTOCOL_CCFF_PROG_CLOCK_NODE_NAME)) { + if (xml_progclk.name() != + std::string(XML_CONFIG_PROTOCOL_CCFF_PROG_CLOCK_NODE_NAME)) { bad_tag(xml_progclk, loc_data, xml_config_orgz, {"programming_clock"}); } read_xml_ccff_prog_clock(xml_progclk, loc_data, config_protocol); diff --git a/libs/libarchopenfpga/src/write_xml_config_protocol.cpp b/libs/libarchopenfpga/src/write_xml_config_protocol.cpp index 212614ff6..9690c629f 100644 --- a/libs/libarchopenfpga/src/write_xml_config_protocol.cpp +++ b/libs/libarchopenfpga/src/write_xml_config_protocol.cpp @@ -32,20 +32,18 @@ static void write_xml_config_organization(std::fstream& fp, const char* fname, write_xml_attribute( fp, "circuit_model_name", circuit_lib.model_name(config_protocol.memory_model()).c_str()); - write_xml_attribute( - fp, XML_CONFIG_PROTOCOL_NUM_REGIONS_ATTR, - config_protocol.num_regions()); + write_xml_attribute(fp, XML_CONFIG_PROTOCOL_NUM_REGIONS_ATTR, + config_protocol.num_regions()); fp << "/>" << "\n"; /* CCFF protocol details */ - if (config_protocol.type() == CONFIG_MEM_SCAN_CHAIN) { + if (config_protocol.type() == CONFIG_MEM_SCAN_CHAIN) { for (openfpga::BasicPort port : config_protocol.prog_clock_ports()) { fp << "\t\t\t" << "<" << XML_CONFIG_PROTOCOL_CCFF_PROG_CLOCK_NODE_NAME; - write_xml_attribute( - fp, XML_CONFIG_PROTOCOL_CCFF_PROG_CLOCK_PORT_ATTR, - port.to_verilog_string().c_str()); + write_xml_attribute(fp, XML_CONFIG_PROTOCOL_CCFF_PROG_CLOCK_PORT_ATTR, + port.to_verilog_string().c_str()); write_xml_attribute( fp, XML_CONFIG_PROTOCOL_CCFF_PROG_CLOCK_INDICES_ATTR, config_protocol.prog_clock_port_ccff_head_indices_str(port).c_str()); @@ -55,7 +53,7 @@ static void write_xml_config_organization(std::fstream& fp, const char* fname, } /* BL/WL protocol details */ - if (config_protocol.type() == CONFIG_MEM_QL_MEMORY_BANK) { + if (config_protocol.type() == CONFIG_MEM_QL_MEMORY_BANK) { fp << "\t\t\t" << "" << "\n"; - + fp << "\t\t\t" << " ccff_models = circuit_lib.models_by_type(CIRCUIT_MODEL_CCFF); + std::vector ccff_models = + circuit_lib.models_by_type(CIRCUIT_MODEL_CCFF); if (ccff_models.empty()) { - VTR_LOG_ERROR("Expect at least one CCFF model to be defined in circuit library!\n"); + VTR_LOG_ERROR( + "Expect at least one CCFF model to be defined in circuit library!\n"); num_err++; } /* Try to match the programming clock port name with the CCFF port name */ for (BasicPort prog_clk_port : config_protocol.prog_clock_ports()) { bool port_match = false; - for (CircuitModelId ccff_model : ccff_models) { - CircuitPortId circuit_port = circuit_lib.model_port(ccff_model, prog_clk_port.get_name()); + for (CircuitModelId ccff_model : ccff_models) { + CircuitPortId circuit_port = + circuit_lib.model_port(ccff_model, prog_clk_port.get_name()); if (circuit_port) { port_match = true; /* Ensure this is a programming clock and a global port */ if (!circuit_lib.port_is_global(circuit_port)) { - VTR_LOG_ERROR("Expect the programming clock '%s' to be a global port but not!\n", prog_clk_port.get_name().c_str()); + VTR_LOG_ERROR( + "Expect the programming clock '%s' to be a global port but not!\n", + prog_clk_port.get_name().c_str()); num_err++; } if (circuit_lib.port_type(circuit_port) != CIRCUIT_MODEL_PORT_CLOCK) { - VTR_LOG_ERROR("Expect the programming clock '%s' to be a clock port but not!\n", prog_clk_port.get_name().c_str()); + VTR_LOG_ERROR( + "Expect the programming clock '%s' to be a clock port but not!\n", + prog_clk_port.get_name().c_str()); num_err++; } if (!circuit_lib.port_is_prog(circuit_port)) { - VTR_LOG_ERROR("Expect the programming clock '%s' to be a programming port but not!\n", prog_clk_port.get_name().c_str()); + VTR_LOG_ERROR( + "Expect the programming clock '%s' to be a programming port but " + "not!\n", + prog_clk_port.get_name().c_str()); num_err++; } } } if (!port_match) { - VTR_LOG_ERROR("Fail to find a port of any CCFF model that matches the programming clock definition (Expect port name: '%s')!\n", prog_clk_port.get_name().c_str()); + VTR_LOG_ERROR( + "Fail to find a port of any CCFF model that matches the programming " + "clock definition (Expect port name: '%s')!\n", + prog_clk_port.get_name().c_str()); num_err++; } } @@ -64,22 +79,20 @@ static int check_config_protocol_programming_clock( * Check if the configuration protocol is valid without any conflict with * circuit library content. *******************************************************************/ -bool check_config_protocol( - const ConfigProtocol& config_protocol, const CircuitLibrary& circuit_lib) { +bool check_config_protocol(const ConfigProtocol& config_protocol, + const CircuitLibrary& circuit_lib) { int num_err = 0; if (!config_protocol.validate()) { num_err++; } - if (!check_configurable_memory_circuit_model( - config_protocol, - circuit_lib)) { + if (!check_configurable_memory_circuit_model(config_protocol, circuit_lib)) { num_err++; } - num_err += check_config_protocol_programming_clock( - config_protocol, circuit_lib); + num_err += + check_config_protocol_programming_clock(config_protocol, circuit_lib); VTR_LOG("Found %ld errors when checking configuration protocol!\n", num_err); return (0 == num_err); diff --git a/openfpga/src/utils/check_config_protocol.h b/openfpga/src/utils/check_config_protocol.h index 8b4b47ba1..6c6aa63e3 100644 --- a/openfpga/src/utils/check_config_protocol.h +++ b/openfpga/src/utils/check_config_protocol.h @@ -4,8 +4,8 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include "config_protocol.h" #include "circuit_library.h" +#include "config_protocol.h" /******************************************************************** * Function declaration @@ -14,8 +14,8 @@ /* begin namespace openfpga */ namespace openfpga { -bool check_config_protocol( - const ConfigProtocol& config_protocol, const CircuitLibrary& circuit_lib); +bool check_config_protocol(const ConfigProtocol& config_protocol, + const CircuitLibrary& circuit_lib); } /* end namespace openfpga */ From 02e964b16f7f46b9a02b3153c20dfc7fb4480ddf Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 22 Apr 2023 15:41:19 +0800 Subject: [PATCH 148/166] [test] add a new test case for ccffv2 --- openfpga_flow/openfpga_arch/README.md | 2 +- ...4_N4_40nm_multi_region_cc2clk_openfpga.xml | 194 ++++++++++++++++++ .../regression_test_scripts/basic_reg_test.sh | 1 + .../config/task.conf | 45 ++++ 4 files changed, 241 insertions(+), 1 deletion(-) create mode 100644 openfpga_flow/openfpga_arch/k4_N4_40nm_multi_region_cc2clk_openfpga.xml create mode 100644 openfpga_flow/tasks/basic_tests/full_testbench/multi_region_configuration_chain_2clk/config/task.conf diff --git a/openfpga_flow/openfpga_arch/README.md b/openfpga_flow/openfpga_arch/README.md index 0960d3f2d..cdd8db5f3 100644 --- a/openfpga_flow/openfpga_arch/README.md +++ b/openfpga_flow/openfpga_arch/README.md @@ -18,7 +18,7 @@ Note that an OpenFPGA architecture can be applied to multiple VPR architecture f - aib: If the Advanced Interface Bus (AIB) is used in place of some I/Os. - : specify the type of configuration protocol used in the architecture. - `bank` refers to the memory bank - - `cc` refers to the configuration chain + - `cc` refers to the configuration chain. Note that a postfix `clk` may be applied when the configuration chain is controlled by more than 1 clocks - `frame` refers to the frame-based organization - `standalone` referes to the vanilla organization - fixed\_sim: fixed clock frequencies in simulation settings. If auto clock frequencies are used, there is no need to appear in the naming diff --git a/openfpga_flow/openfpga_arch/k4_N4_40nm_multi_region_cc2clk_openfpga.xml b/openfpga_flow/openfpga_arch/k4_N4_40nm_multi_region_cc2clk_openfpga.xml new file mode 100644 index 000000000..8f546cca2 --- /dev/null +++ b/openfpga_flow/openfpga_arch/k4_N4_40nm_multi_region_cc2clk_openfpga.xml @@ -0,0 +1,194 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + + + + + 10e-12 5e-12 5e-12 + + + 10e-12 5e-12 5e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/openfpga_flow/regression_test_scripts/basic_reg_test.sh b/openfpga_flow/regression_test_scripts/basic_reg_test.sh index 490cab089..bc437ec0b 100755 --- a/openfpga_flow/regression_test_scripts/basic_reg_test.sh +++ b/openfpga_flow/regression_test_scripts/basic_reg_test.sh @@ -25,6 +25,7 @@ run-task basic_tests/full_testbench/configuration_chain_use_setb $@ run-task basic_tests/full_testbench/configuration_chain_use_set_reset $@ run-task basic_tests/full_testbench/configuration_chain_config_enable_scff $@ run-task basic_tests/full_testbench/multi_region_configuration_chain $@ +run-task basic_tests/full_testbench/multi_region_configuration_chain_2clk $@ run-task basic_tests/full_testbench/fast_configuration_chain $@ run-task basic_tests/full_testbench/fast_configuration_chain_use_set $@ run-task basic_tests/full_testbench/smart_fast_configuration_chain $@ diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/multi_region_configuration_chain_2clk/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/multi_region_configuration_chain_2clk/config/task.conf new file mode 100644 index 000000000..74264971d --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/full_testbench/multi_region_configuration_chain_2clk/config/task.conf @@ -0,0 +1,45 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = true +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=yosys_vpr + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_multi_region_cc2clk_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout=--device 2x2 +openfpga_fast_configuration= + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v +bench1=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/or2/or2.v +bench2=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2_latch/and2_latch.v + +[SYNTHESIS_PARAM] +bench_read_verilog_options_common = -nolatches +bench0_top = and2 +bench0_chan_width = 300 + +bench1_top = or2 +bench1_chan_width = 300 + +bench2_top = and2_latch +bench2_chan_width = 300 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= From 5500b9a289da6f334c794b158f9fd662d928c961 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 22 Apr 2023 16:27:27 +0800 Subject: [PATCH 149/166] [core] upgrading netlist generator --- libs/libarchopenfpga/src/config_protocol.h | 22 ++++++++++++--------- openfpga/src/fabric/build_top_module.cpp | 14 ++++++++++++- openfpga/src/utils/module_manager_utils.cpp | 15 +++++++++----- openfpga/src/utils/module_manager_utils.h | 6 ++++-- 4 files changed, 40 insertions(+), 17 deletions(-) diff --git a/libs/libarchopenfpga/src/config_protocol.h b/libs/libarchopenfpga/src/config_protocol.h index 954600f65..4e345bb1f 100644 --- a/libs/libarchopenfpga/src/config_protocol.h +++ b/libs/libarchopenfpga/src/config_protocol.h @@ -31,12 +31,14 @@ class ConfigProtocol { CircuitModelId memory_model() const; int num_regions() const; + /* Get information of the programming clock port: name and width */ + openfpga::BasicPort prog_clock_port_info() const; + /* Get a list of programming clock pins, flatten from the programming clock port */ + std::vector prog_clock_pins() const; /* Get a list of programming clock ports */ - std::vector prog_clock_ports() const; - /* Get a list of programming clock ports */ - std::string prog_clock_port_ccff_head_indices_str( + std::string prog_clock_pin_ccff_head_indices_str( const openfpga::BasicPort& port) const; - std::vector prog_clock_port_ccff_head_indices( + std::vector prog_clock_pin_ccff_head_indices( const openfpga::BasicPort& port) const; e_blwl_protocol_type bl_protocol_type() const; @@ -54,10 +56,12 @@ class ConfigProtocol { void set_memory_model(const CircuitModelId& memory_model); void set_num_regions(const int& num_regions); - /* Add a pair of programming clock port and ccff head indices. This API will + /* Add the programming clock port */ + void set_prog_clock_port(const openfpga::BasicPort& port); + /* Add a pair of programming clock pin and ccff head indices. This API will * parse the index list, e.g., "0,1" to a vector of integers [0 1] */ - void set_prog_clock_port_ccff_head_indices_pair( - const openfpga::BasicPort& port, const std::string& indices_str); + void set_prog_clock_pin_ccff_head_indices_pair( + const openfpga::BasicPort& pin, const std::string& indices_str); void set_bl_protocol_type(const e_blwl_protocol_type& type); void set_bl_memory_model_name(const std::string& memory_model_name); @@ -99,8 +103,8 @@ class ConfigProtocol { /* Programming clock managment: This is only applicable to configuration chain * protocols */ - std::map> - prog_clk_ccff_head_indices_; + BasicPort prog_clk_port_; + std::vector> prog_clk_ccff_head_indices_; char INDICE_STRING_DELIM_; /* BL & WL protocol: This is only applicable to memory-bank configuration diff --git a/openfpga/src/fabric/build_top_module.cpp b/openfpga/src/fabric/build_top_module.cpp index 7d5b168ce..11187c068 100644 --- a/openfpga/src/fabric/build_top_module.cpp +++ b/openfpga/src/fabric/build_top_module.cpp @@ -595,6 +595,18 @@ int build_top_module( } } + /* For configuration chains, we avoid adding nets for programmable clocks if there are a few */ + std::vector global_port_blacklist; + if (config_protocol.num_prog_clocks() > 1) { + BasicPort prog_clk_port = config_protocol.prog_clock_port_info(); + global_port_blacklist.push_back(prog_clk_port.get_name()); + /* Add port */ + ModulePortId port_id = module_manager.add_port( + module_id, prog_clk_port, ModuleManager::MODULE_GLOBAL_PORT); + /* Add nets by following configurable children under different regions */ + add_top_module_nets_prog_clock(module_manager, top_module, port_id, config_protocol); + } + /* Add global ports to the top module: * This is a much easier job after adding sub modules (instances), * we just need to find all the global ports from the child modules and build @@ -602,7 +614,7 @@ int build_top_module( * @note This function is called after the * add_top_module_nets_memory_config_bus() because it may add some sub modules */ - add_module_global_ports_from_child_modules(module_manager, top_module); + add_module_global_ports_from_child_modules(module_manager, top_module, global_port_blacklist); return status; } diff --git a/openfpga/src/utils/module_manager_utils.cpp b/openfpga/src/utils/module_manager_utils.cpp index ac625af02..334eef4a5 100644 --- a/openfpga/src/utils/module_manager_utils.cpp +++ b/openfpga/src/utils/module_manager_utils.cpp @@ -2185,7 +2185,7 @@ void add_module_gpio_ports_from_child_modules(ModuleManager& module_manager, * Otherwise, some global ports of the sub modules may be missed! *******************************************************************/ void add_module_global_input_ports_from_child_modules( - ModuleManager& module_manager, const ModuleId& module_id) { + ModuleManager& module_manager, const ModuleId& module_id, const std::vector& port_name_to_ignore) { std::vector global_ports_to_add; /* Iterate over the child modules */ @@ -2202,8 +2202,12 @@ void add_module_global_input_ports_from_child_modules( if (it != global_ports_to_add.end()) { continue; } - /* Reach here, this is an unique global port, update the list */ - global_ports_to_add.push_back(global_port); + /* Reach here, this is an unique global port, update the list + * Final check: ignore those in the blacklist + */ + if (std::find(port_name_to_ignore.begin(), port_name_to_ignore.end(), global_port.get_name()) == port_name_to_ignore.end()) { + global_ports_to_add.push_back(global_port); + } } } } @@ -2304,9 +2308,10 @@ void add_module_global_input_ports_from_child_modules( * Otherwise, some global ports of the sub modules may be missed! *******************************************************************/ void add_module_global_ports_from_child_modules(ModuleManager& module_manager, - const ModuleId& module_id) { + const ModuleId& module_id, + const std::vector& port_name_to_ignore) { /* Input ports */ - add_module_global_input_ports_from_child_modules(module_manager, module_id); + add_module_global_input_ports_from_child_modules(module_manager, module_id, port_name_to_ignore); } /******************************************************************** diff --git a/openfpga/src/utils/module_manager_utils.h b/openfpga/src/utils/module_manager_utils.h index f6ec40b0c..cff5cc966 100644 --- a/openfpga/src/utils/module_manager_utils.h +++ b/openfpga/src/utils/module_manager_utils.h @@ -147,13 +147,15 @@ size_t find_module_num_config_bits( const e_config_protocol_type& sram_orgz_type); void add_module_global_input_ports_from_child_modules( - ModuleManager& module_manager, const ModuleId& module_id); + ModuleManager& module_manager, const ModuleId& module_id, + const std::vector& port_name_to_ignore = std::vector()); void add_module_global_output_ports_from_child_modules( ModuleManager& module_manager, const ModuleId& module_id); void add_module_global_ports_from_child_modules(ModuleManager& module_manager, - const ModuleId& module_id); + const ModuleId& module_id, + const std::vector& port_name_to_ignore = std::vector()); void add_module_gpio_ports_from_child_modules(ModuleManager& module_manager, const ModuleId& module_id); From 592765af48ef170c8eddf807e6d3ad648266996f Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 23 Apr 2023 13:57:37 +0800 Subject: [PATCH 150/166] [core] code complete for upgrading netlist generator w.r.t. ccff v2 --- libs/libarchopenfpga/src/config_protocol.cpp | 40 ++++++++++++---- .../src/read_xml_config_protocol.cpp | 30 +++++++++++- .../fabric/build_top_module_connection.cpp | 46 +++++++++++++++++++ .../src/fabric/build_top_module_connection.h | 2 + 4 files changed, 107 insertions(+), 11 deletions(-) diff --git a/libs/libarchopenfpga/src/config_protocol.cpp b/libs/libarchopenfpga/src/config_protocol.cpp index 7a3d59cf4..cc6031b0f 100644 --- a/libs/libarchopenfpga/src/config_protocol.cpp +++ b/libs/libarchopenfpga/src/config_protocol.cpp @@ -26,10 +26,14 @@ CircuitModelId ConfigProtocol::memory_model() const { return memory_model_; } int ConfigProtocol::num_regions() const { return num_regions_; } -std::vector ConfigProtocol::prog_clock_ports() const { +std::vector ConfigProtocol::prog_clock_port_info() const { + return prog_clk_port_; +} + +std::vector ConfigProtocol::prog_clock_pins() const { std::vector keys; - for (const auto& [k, v] : prog_clk_ccff_head_indices_) { - keys.push_back(k); + for (auto pin : prog_clk_port_.pins()) { + keys.push_back(openfpga::BasicPort(prog_clk_port_.get_name(), pin, pin)); } return keys; } @@ -52,11 +56,15 @@ std::string ConfigProtocol::prog_clock_port_ccff_head_indices_str( std::vector ConfigProtocol::prog_clock_port_ccff_head_indices( const openfpga::BasicPort& port) const { std::vector ret; - auto result = prog_clk_ccff_head_indices_.find(port); - if (result != prog_clk_ccff_head_indices_.end()) { - return result->second; + if (port.get_width() != 1) { + VTR_LOG_ERROR("The programming clock pin must have a width of 1 while the width specified is %ld!\n", port.get_width()); } - return ret; + VTR_ASSERT(port.get_width == 1); + if (!prog_clk_port_.contained(port)) { + VTR_LOG_ERROR("The programming clock pin '%s[%ld]' is not out of the range [%ld, %ld]!\n", port.get_name().c_str(), port.get_lsb(), prog_clk_port_.get_lsb(), prog_clk_port_.get_msb()); + } + VTR_ASSERT(prog_clk_port_.contained(port)); + return prog_clk_ccff_head_indices_[port.get_lsb()]; } e_blwl_protocol_type ConfigProtocol::bl_protocol_type() const { @@ -107,6 +115,11 @@ void ConfigProtocol::set_num_regions(const int& num_regions) { num_regions_ = num_regions; } +void ConfigProtocol::set_prog_clock(const openfpga::BasicPort& port) { + prog_clk_port_ = port; + prog_clk_ccff_head_indices_.resize(prog_clk_port_.get_width()); +} + void ConfigProtocol::set_prog_clock_port_ccff_head_indices_pair( const openfpga::BasicPort& port, const std::string& indices_str) { openfpga::StringToken tokenizer(indices_str); @@ -115,15 +128,22 @@ void ConfigProtocol::set_prog_clock_port_ccff_head_indices_pair( for (std::string token : tokenizer.split(INDICE_STRING_DELIM_)) { token_int.push_back(std::stoi(token)); } - auto result = prog_clk_ccff_head_indices_.find(port); - if (result != prog_clk_ccff_head_indices_.end()) { + if (port.get_width() != 1) { + VTR_LOG_ERROR("The programming clock pin must have a width of 1 while the width specified is %ld!\n", port.get_width()); + } + VTR_ASSERT(port.get_width == 1); + if (!prog_clk_port_.contained(port)) { + VTR_LOG_ERROR("The programming clock pin '%s[%ld]' is not out of the range [%ld, %ld]!\n", port.get_name().c_str(), port.get_lsb(), prog_clk_port_.get_lsb(), prog_clk_port_.get_msb()); + } + VTR_ASSERT(prog_clk_port_.contained(port)); + if (!prog_clk_ccff_head_indices_[port.get_lsb()].empty()) { VTR_LOG_WARN( "Overwrite the pair between programming clock port '%s[%d:%d]' and ccff " "head indices (previous: '%s', current: '%s')!\n", port.get_name().c_str(), port.get_lsb(), port.get_msb(), prog_clock_port_ccff_head_indices_str(port).c_str(), indices_str.c_str()); } - prog_clk_ccff_head_indices_[port] = token_int; + prog_clk_ccff_head_indices_[port.get_lsb()] = token_int; } void ConfigProtocol::set_bl_protocol_type(const e_blwl_protocol_type& type) { diff --git a/libs/libarchopenfpga/src/read_xml_config_protocol.cpp b/libs/libarchopenfpga/src/read_xml_config_protocol.cpp index 29580d123..3ac930bad 100644 --- a/libs/libarchopenfpga/src/read_xml_config_protocol.cpp +++ b/libs/libarchopenfpga/src/read_xml_config_protocol.cpp @@ -181,11 +181,39 @@ static void read_xml_config_organization(pugi::xml_node& xml_config_orgz, /* Parse Configuration chain protocols */ if (config_protocol.type() == CONFIG_MEM_SCAN_CHAIN) { + /* First pass: Get the programming clock port size */ + openfpga::BasicPort prog_clk_port; for (pugi::xml_node xml_progclk : xml_config_orgz.children()) { /* Error out if the XML child has an invalid name! */ if (xml_progclk.name() != std::string(XML_CONFIG_PROTOCOL_CCFF_PROG_CLOCK_NODE_NAME)) { - bad_tag(xml_progclk, loc_data, xml_config_orgz, {"programming_clock"}); + bad_tag(xml_progclk, loc_data, xml_config_orgz, {XML_CONFIG_PROTOCOL_CCFF_PROG_CLOCK_NODE_NAME}); + } + std::string port_attr = + get_attribute(xml_progclk, XML_CONFIG_PROTOCOL_CCFF_PROG_CLOCK_PORT_ATTR, + loc_data) + .as_string(); + openfpga::BasicPort port = openfpga::PortParser(port_attr).port(); + if (prog_clk_port.get_name().empty()) { + prog_clk_port.set_name(port.get_name()); + prog_clk_port.set_width(port.get_lsb(), port.get_msb()); + } else { + if (prog_clk_port.get_name() != port.get_name()) { + archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_progclk), + "Expect same name for all the programming clocks (This: %s, Others: %s)!\n", port.get_name().c_str(), prog_clk_port.get_name().c_str()); + } + if (prog_clk_port.get_msb() < port.get_msb()) { + prog_clk_port.set_msb(port.get_msb()); + } + } + } + + /* Second pass: fill the clock detailed connections */ + for (pugi::xml_node xml_progclk : xml_config_orgz.children()) { + /* Error out if the XML child has an invalid name! */ + if (xml_progclk.name() != + std::string(XML_CONFIG_PROTOCOL_CCFF_PROG_CLOCK_NODE_NAME)) { + bad_tag(xml_progclk, loc_data, xml_config_orgz, {XML_CONFIG_PROTOCOL_CCFF_PROG_CLOCK_NODE_NAME}); } read_xml_ccff_prog_clock(xml_progclk, loc_data, config_protocol); } diff --git a/openfpga/src/fabric/build_top_module_connection.cpp b/openfpga/src/fabric/build_top_module_connection.cpp index 18b4f2ee9..0b51e7f06 100644 --- a/openfpga/src/fabric/build_top_module_connection.cpp +++ b/openfpga/src/fabric/build_top_module_connection.cpp @@ -1269,4 +1269,50 @@ int add_top_module_global_ports_from_grid_modules( return status; } +/******************************************************************** + * Build the connection between the programming clock port at the top module and each configurable children + * Note that each programming clock pin drive one or more configuration regions + * For example: + * - pin[0] -> region 0, 1 + * - pin[1] -> region 2, 3 + *******************************************************************/ +void add_top_module_nets_prog_clock(ModuleManager& module_manager, + const ModuleId& top_module, + const ModulePortId& src_port, + const ConfigProtocol& config_protocol) { + BasicPort src_port_info = module_manager.module_port(top_module, src_port); + for (size_t pin : src_port_info.pins()) { + /* Create the net */ + ModuleNetId net = create_module_source_pin_net( + module_manager, top_module, top_module, 0, + src_port, src_port_info.pins()[pin_id]); + /* Find all the sink nodes and build the connection one by one */ + for (size_t iregion : config_protocol.prog_clock_port_ccff_head_indices(BasicPort(src_port_info.get_name(), pin, pin))) { + ConfigRegionId config_region = ConfigRegionId(iregion); + for (size_t mem_index = 0; mem_index < module_manager + .region_configurable_children( + top_module, config_region) + .size(); + ++mem_index) { + ModuleId net_sink_module_id = module_manager.region_configurable_children( + top_module, config_region)[mem_index]; + size_t net_sink_instance_id = + module_manager.region_configurable_child_instances( + top_module, config_region)[mem_index]; + ModulePortId net_sink_port_id = + module_manager.find_module_port(net_sink_module_id, src_port_info.get_name()); + BasicPort net_sink_port = + module_manager.module_port(net_sink_module_id, net_sink_port_id); + VTR_ASSERT(1 == net_sink_port.get_width()); + for (size_t net_sink_pin_id : net_sink_port.pins()) { + /* Add net sink */ + module_manager.add_module_net_sink(top_module, net, net_sink_module_id, + net_sink_instance_id, net_sink_port_id, + net_sink_port.pins()[net_sink_pin_id]) + } + } + } + } +} + } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/build_top_module_connection.h b/openfpga/src/fabric/build_top_module_connection.h index 908e6cfdc..66b96abab 100644 --- a/openfpga/src/fabric/build_top_module_connection.h +++ b/openfpga/src/fabric/build_top_module_connection.h @@ -41,6 +41,8 @@ int add_top_module_global_ports_from_grid_modules( const vtr::Matrix& grid_instance_ids, const ClockNetwork& clk_ntwk, const RRClockSpatialLookup& rr_clock_lookup); +void add_top_module_nets_prog_clock(ModuleManager& module_manager, const ModuleId& top_module, const ModulePortId& src_port, const ConfigProtocol& config_protocol); + } /* end namespace openfpga */ #endif From bd511ba51521bc3b7a1f18cc843f7194a2928b18 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 23 Apr 2023 14:26:08 +0800 Subject: [PATCH 151/166] [core] fixed syntax errors --- libs/libarchopenfpga/src/config_protocol.cpp | 35 ++++++++++++------- libs/libarchopenfpga/src/config_protocol.h | 4 ++- .../src/read_xml_config_protocol.cpp | 3 +- .../src/write_xml_config_protocol.cpp | 4 +-- openfpga/src/fabric/build_top_module.cpp | 2 +- .../fabric/build_top_module_connection.cpp | 8 ++--- .../src/fabric/build_top_module_connection.h | 6 +++- openfpga/src/utils/check_config_protocol.cpp | 2 +- 8 files changed, 40 insertions(+), 24 deletions(-) diff --git a/libs/libarchopenfpga/src/config_protocol.cpp b/libs/libarchopenfpga/src/config_protocol.cpp index cc6031b0f..3a399d021 100644 --- a/libs/libarchopenfpga/src/config_protocol.cpp +++ b/libs/libarchopenfpga/src/config_protocol.cpp @@ -26,11 +26,18 @@ CircuitModelId ConfigProtocol::memory_model() const { return memory_model_; } int ConfigProtocol::num_regions() const { return num_regions_; } -std::vector ConfigProtocol::prog_clock_port_info() const { +size_t ConfigProtocol::num_prog_clocks() const { + VTR_ASSERT(type_ == CONFIG_MEM_SCAN_CHAIN); + return prog_clk_port_.get_width(); +} + +openfpga::BasicPort ConfigProtocol::prog_clock_port_info() const { + VTR_ASSERT(type_ == CONFIG_MEM_SCAN_CHAIN); return prog_clk_port_; } std::vector ConfigProtocol::prog_clock_pins() const { + VTR_ASSERT(type_ == CONFIG_MEM_SCAN_CHAIN); std::vector keys; for (auto pin : prog_clk_port_.pins()) { keys.push_back(openfpga::BasicPort(prog_clk_port_.get_name(), pin, pin)); @@ -38,10 +45,11 @@ std::vector ConfigProtocol::prog_clock_pins() const { return keys; } -std::string ConfigProtocol::prog_clock_port_ccff_head_indices_str( +std::string ConfigProtocol::prog_clock_pin_ccff_head_indices_str( const openfpga::BasicPort& port) const { + VTR_ASSERT(type_ == CONFIG_MEM_SCAN_CHAIN); std::string ret(""); - std::vector raw = prog_clock_port_ccff_head_indices(port); + std::vector raw = prog_clock_pin_ccff_head_indices(port); if (!raw.empty()) { for (size_t idx : raw) { /* TODO: We need a join function */ @@ -53,13 +61,14 @@ std::string ConfigProtocol::prog_clock_port_ccff_head_indices_str( return ret; } -std::vector ConfigProtocol::prog_clock_port_ccff_head_indices( +std::vector ConfigProtocol::prog_clock_pin_ccff_head_indices( const openfpga::BasicPort& port) const { + VTR_ASSERT(type_ == CONFIG_MEM_SCAN_CHAIN); std::vector ret; if (port.get_width() != 1) { VTR_LOG_ERROR("The programming clock pin must have a width of 1 while the width specified is %ld!\n", port.get_width()); } - VTR_ASSERT(port.get_width == 1); + VTR_ASSERT(port.get_width() == 1); if (!prog_clk_port_.contained(port)) { VTR_LOG_ERROR("The programming clock pin '%s[%ld]' is not out of the range [%ld, %ld]!\n", port.get_name().c_str(), port.get_lsb(), prog_clk_port_.get_lsb(), prog_clk_port_.get_msb()); } @@ -115,12 +124,12 @@ void ConfigProtocol::set_num_regions(const int& num_regions) { num_regions_ = num_regions; } -void ConfigProtocol::set_prog_clock(const openfpga::BasicPort& port) { +void ConfigProtocol::set_prog_clock_port(const openfpga::BasicPort& port) { prog_clk_port_ = port; prog_clk_ccff_head_indices_.resize(prog_clk_port_.get_width()); } -void ConfigProtocol::set_prog_clock_port_ccff_head_indices_pair( +void ConfigProtocol::set_prog_clock_pin_ccff_head_indices_pair( const openfpga::BasicPort& port, const std::string& indices_str) { openfpga::StringToken tokenizer(indices_str); std::vector token_int; @@ -131,7 +140,7 @@ void ConfigProtocol::set_prog_clock_port_ccff_head_indices_pair( if (port.get_width() != 1) { VTR_LOG_ERROR("The programming clock pin must have a width of 1 while the width specified is %ld!\n", port.get_width()); } - VTR_ASSERT(port.get_width == 1); + VTR_ASSERT(port.get_width() == 1); if (!prog_clk_port_.contained(port)) { VTR_LOG_ERROR("The programming clock pin '%s[%ld]' is not out of the range [%ld, %ld]!\n", port.get_name().c_str(), port.get_lsb(), prog_clk_port_.get_lsb(), prog_clk_port_.get_msb()); } @@ -141,7 +150,7 @@ void ConfigProtocol::set_prog_clock_port_ccff_head_indices_pair( "Overwrite the pair between programming clock port '%s[%d:%d]' and ccff " "head indices (previous: '%s', current: '%s')!\n", port.get_name().c_str(), port.get_lsb(), port.get_msb(), - prog_clock_port_ccff_head_indices_str(port).c_str(), indices_str.c_str()); + prog_clock_pin_ccff_head_indices_str(port).c_str(), indices_str.c_str()); } prog_clk_ccff_head_indices_[port.get_lsb()] = token_int; } @@ -235,7 +244,7 @@ int ConfigProtocol::validate_ccff_prog_clocks() const { int num_err = 0; /* Initialize scoreboard */ std::vector ccff_head_scoreboard(num_regions(), 0); - for (openfpga::BasicPort port : prog_clock_ports()) { + for (openfpga::BasicPort port : prog_clock_pins()) { /* Must be valid first */ if (port.is_valid()) { VTR_LOG_ERROR("Programming clock '%s[%d:%d]' is not a valid port!\n", @@ -251,7 +260,7 @@ int ConfigProtocol::validate_ccff_prog_clocks() const { num_err++; } /* Fill scoreboard */ - for (size_t ccff_head_idx : prog_clock_port_ccff_head_indices(port)) { + for (size_t ccff_head_idx : prog_clock_pin_ccff_head_indices(port)) { if (ccff_head_idx >= ccff_head_scoreboard.size()) { VTR_LOG_ERROR( "Programming clock '%s[%d:%d]' controlls an invalid ccff head '%ld' " @@ -263,11 +272,11 @@ int ConfigProtocol::validate_ccff_prog_clocks() const { ccff_head_scoreboard[ccff_head_idx]++; } } - if (prog_clock_ports().size() != (size_t)num_regions()) { + if (prog_clock_pins().size() != (size_t)num_regions()) { VTR_LOG_ERROR( "Number of programming clocks '%ld' does not match the number of " "configuration regions '%ld'!\n", - prog_clock_ports().size(), num_regions()); + prog_clock_pins().size(), num_regions()); num_err++; } for (size_t iregion = 0; iregion < ccff_head_scoreboard.size(); iregion++) { diff --git a/libs/libarchopenfpga/src/config_protocol.h b/libs/libarchopenfpga/src/config_protocol.h index 4e345bb1f..d80135eb3 100644 --- a/libs/libarchopenfpga/src/config_protocol.h +++ b/libs/libarchopenfpga/src/config_protocol.h @@ -31,6 +31,8 @@ class ConfigProtocol { CircuitModelId memory_model() const; int num_regions() const; + /* Find the number of programming clocks, only valid for configuration chain type! */ + size_t num_prog_clocks() const; /* Get information of the programming clock port: name and width */ openfpga::BasicPort prog_clock_port_info() const; /* Get a list of programming clock pins, flatten from the programming clock port */ @@ -103,7 +105,7 @@ class ConfigProtocol { /* Programming clock managment: This is only applicable to configuration chain * protocols */ - BasicPort prog_clk_port_; + openfpga::BasicPort prog_clk_port_; std::vector> prog_clk_ccff_head_indices_; char INDICE_STRING_DELIM_; diff --git a/libs/libarchopenfpga/src/read_xml_config_protocol.cpp b/libs/libarchopenfpga/src/read_xml_config_protocol.cpp index 3ac930bad..b1d9acd76 100644 --- a/libs/libarchopenfpga/src/read_xml_config_protocol.cpp +++ b/libs/libarchopenfpga/src/read_xml_config_protocol.cpp @@ -67,7 +67,7 @@ static void read_xml_ccff_prog_clock(pugi::xml_node& xml_progclk, openfpga::BasicPort port = openfpga::PortParser(port_attr).port(); - config_protocol.set_prog_clock_port_ccff_head_indices_pair(port, + config_protocol.set_prog_clock_pin_ccff_head_indices_pair(port, indices_attr); } @@ -207,6 +207,7 @@ static void read_xml_config_organization(pugi::xml_node& xml_config_orgz, } } } + config_protocol.set_prog_clock_port(prog_clk_port); /* Second pass: fill the clock detailed connections */ for (pugi::xml_node xml_progclk : xml_config_orgz.children()) { diff --git a/libs/libarchopenfpga/src/write_xml_config_protocol.cpp b/libs/libarchopenfpga/src/write_xml_config_protocol.cpp index 9690c629f..f721e6885 100644 --- a/libs/libarchopenfpga/src/write_xml_config_protocol.cpp +++ b/libs/libarchopenfpga/src/write_xml_config_protocol.cpp @@ -39,14 +39,14 @@ static void write_xml_config_organization(std::fstream& fp, const char* fname, /* CCFF protocol details */ if (config_protocol.type() == CONFIG_MEM_SCAN_CHAIN) { - for (openfpga::BasicPort port : config_protocol.prog_clock_ports()) { + for (openfpga::BasicPort port : config_protocol.prog_clock_pins()) { fp << "\t\t\t" << "<" << XML_CONFIG_PROTOCOL_CCFF_PROG_CLOCK_NODE_NAME; write_xml_attribute(fp, XML_CONFIG_PROTOCOL_CCFF_PROG_CLOCK_PORT_ATTR, port.to_verilog_string().c_str()); write_xml_attribute( fp, XML_CONFIG_PROTOCOL_CCFF_PROG_CLOCK_INDICES_ATTR, - config_protocol.prog_clock_port_ccff_head_indices_str(port).c_str()); + config_protocol.prog_clock_pin_ccff_head_indices_str(port).c_str()); fp << "/>" << "\n"; } diff --git a/openfpga/src/fabric/build_top_module.cpp b/openfpga/src/fabric/build_top_module.cpp index 11187c068..b333a8010 100644 --- a/openfpga/src/fabric/build_top_module.cpp +++ b/openfpga/src/fabric/build_top_module.cpp @@ -602,7 +602,7 @@ int build_top_module( global_port_blacklist.push_back(prog_clk_port.get_name()); /* Add port */ ModulePortId port_id = module_manager.add_port( - module_id, prog_clk_port, ModuleManager::MODULE_GLOBAL_PORT); + top_module, prog_clk_port, ModuleManager::MODULE_GLOBAL_PORT); /* Add nets by following configurable children under different regions */ add_top_module_nets_prog_clock(module_manager, top_module, port_id, config_protocol); } diff --git a/openfpga/src/fabric/build_top_module_connection.cpp b/openfpga/src/fabric/build_top_module_connection.cpp index 0b51e7f06..f25db810d 100644 --- a/openfpga/src/fabric/build_top_module_connection.cpp +++ b/openfpga/src/fabric/build_top_module_connection.cpp @@ -1281,13 +1281,13 @@ void add_top_module_nets_prog_clock(ModuleManager& module_manager, const ModulePortId& src_port, const ConfigProtocol& config_protocol) { BasicPort src_port_info = module_manager.module_port(top_module, src_port); - for (size_t pin : src_port_info.pins()) { + for (size_t net_src_pin_id : src_port_info.pins()) { /* Create the net */ ModuleNetId net = create_module_source_pin_net( module_manager, top_module, top_module, 0, - src_port, src_port_info.pins()[pin_id]); + src_port, src_port_info.pins()[net_src_pin_id]); /* Find all the sink nodes and build the connection one by one */ - for (size_t iregion : config_protocol.prog_clock_port_ccff_head_indices(BasicPort(src_port_info.get_name(), pin, pin))) { + for (size_t iregion : config_protocol.prog_clock_pin_ccff_head_indices(BasicPort(src_port_info.get_name(), net_src_pin_id, net_src_pin_id))) { ConfigRegionId config_region = ConfigRegionId(iregion); for (size_t mem_index = 0; mem_index < module_manager .region_configurable_children( @@ -1308,7 +1308,7 @@ void add_top_module_nets_prog_clock(ModuleManager& module_manager, /* Add net sink */ module_manager.add_module_net_sink(top_module, net, net_sink_module_id, net_sink_instance_id, net_sink_port_id, - net_sink_port.pins()[net_sink_pin_id]) + net_sink_port.pins()[net_sink_pin_id]); } } } diff --git a/openfpga/src/fabric/build_top_module_connection.h b/openfpga/src/fabric/build_top_module_connection.h index 66b96abab..0fcb99668 100644 --- a/openfpga/src/fabric/build_top_module_connection.h +++ b/openfpga/src/fabric/build_top_module_connection.h @@ -6,6 +6,7 @@ *******************************************************************/ #include +#include "config_protocol.h" #include "clock_network.h" #include "device_grid.h" #include "device_rr_gsb.h" @@ -41,7 +42,10 @@ int add_top_module_global_ports_from_grid_modules( const vtr::Matrix& grid_instance_ids, const ClockNetwork& clk_ntwk, const RRClockSpatialLookup& rr_clock_lookup); -void add_top_module_nets_prog_clock(ModuleManager& module_manager, const ModuleId& top_module, const ModulePortId& src_port, const ConfigProtocol& config_protocol); +void add_top_module_nets_prog_clock(ModuleManager& module_manager, + const ModuleId& top_module, + const ModulePortId& src_port, + const ConfigProtocol& config_protocol); } /* end namespace openfpga */ diff --git a/openfpga/src/utils/check_config_protocol.cpp b/openfpga/src/utils/check_config_protocol.cpp index 247bb5a48..42dc99c51 100644 --- a/openfpga/src/utils/check_config_protocol.cpp +++ b/openfpga/src/utils/check_config_protocol.cpp @@ -34,7 +34,7 @@ static int check_config_protocol_programming_clock( num_err++; } /* Try to match the programming clock port name with the CCFF port name */ - for (BasicPort prog_clk_port : config_protocol.prog_clock_ports()) { + for (BasicPort prog_clk_port : config_protocol.prog_clock_pins()) { bool port_match = false; for (CircuitModelId ccff_model : ccff_models) { CircuitPortId circuit_port = From 28b7a12f68401f1cd100008c82564fcf55a2beca Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 23 Apr 2023 14:31:35 +0800 Subject: [PATCH 152/166] [core] code format --- libs/libarchopenfpga/src/config_protocol.cpp | 22 +++++++++++--- libs/libarchopenfpga/src/config_protocol.h | 6 ++-- .../src/read_xml_config_protocol.cpp | 18 +++++++----- openfpga/src/fabric/build_top_module.cpp | 9 ++++-- .../fabric/build_top_module_connection.cpp | 29 ++++++++++--------- .../src/fabric/build_top_module_connection.h | 2 +- openfpga/src/utils/module_manager_utils.cpp | 15 ++++++---- openfpga/src/utils/module_manager_utils.h | 10 ++++--- 8 files changed, 71 insertions(+), 40 deletions(-) diff --git a/libs/libarchopenfpga/src/config_protocol.cpp b/libs/libarchopenfpga/src/config_protocol.cpp index 3a399d021..167f8745c 100644 --- a/libs/libarchopenfpga/src/config_protocol.cpp +++ b/libs/libarchopenfpga/src/config_protocol.cpp @@ -66,11 +66,18 @@ std::vector ConfigProtocol::prog_clock_pin_ccff_head_indices( VTR_ASSERT(type_ == CONFIG_MEM_SCAN_CHAIN); std::vector ret; if (port.get_width() != 1) { - VTR_LOG_ERROR("The programming clock pin must have a width of 1 while the width specified is %ld!\n", port.get_width()); + VTR_LOG_ERROR( + "The programming clock pin must have a width of 1 while the width " + "specified is %ld!\n", + port.get_width()); } VTR_ASSERT(port.get_width() == 1); if (!prog_clk_port_.contained(port)) { - VTR_LOG_ERROR("The programming clock pin '%s[%ld]' is not out of the range [%ld, %ld]!\n", port.get_name().c_str(), port.get_lsb(), prog_clk_port_.get_lsb(), prog_clk_port_.get_msb()); + VTR_LOG_ERROR( + "The programming clock pin '%s[%ld]' is not out of the range [%ld, " + "%ld]!\n", + port.get_name().c_str(), port.get_lsb(), prog_clk_port_.get_lsb(), + prog_clk_port_.get_msb()); } VTR_ASSERT(prog_clk_port_.contained(port)); return prog_clk_ccff_head_indices_[port.get_lsb()]; @@ -138,11 +145,18 @@ void ConfigProtocol::set_prog_clock_pin_ccff_head_indices_pair( token_int.push_back(std::stoi(token)); } if (port.get_width() != 1) { - VTR_LOG_ERROR("The programming clock pin must have a width of 1 while the width specified is %ld!\n", port.get_width()); + VTR_LOG_ERROR( + "The programming clock pin must have a width of 1 while the width " + "specified is %ld!\n", + port.get_width()); } VTR_ASSERT(port.get_width() == 1); if (!prog_clk_port_.contained(port)) { - VTR_LOG_ERROR("The programming clock pin '%s[%ld]' is not out of the range [%ld, %ld]!\n", port.get_name().c_str(), port.get_lsb(), prog_clk_port_.get_lsb(), prog_clk_port_.get_msb()); + VTR_LOG_ERROR( + "The programming clock pin '%s[%ld]' is not out of the range [%ld, " + "%ld]!\n", + port.get_name().c_str(), port.get_lsb(), prog_clk_port_.get_lsb(), + prog_clk_port_.get_msb()); } VTR_ASSERT(prog_clk_port_.contained(port)); if (!prog_clk_ccff_head_indices_[port.get_lsb()].empty()) { diff --git a/libs/libarchopenfpga/src/config_protocol.h b/libs/libarchopenfpga/src/config_protocol.h index d80135eb3..42ca982c4 100644 --- a/libs/libarchopenfpga/src/config_protocol.h +++ b/libs/libarchopenfpga/src/config_protocol.h @@ -31,11 +31,13 @@ class ConfigProtocol { CircuitModelId memory_model() const; int num_regions() const; - /* Find the number of programming clocks, only valid for configuration chain type! */ + /* Find the number of programming clocks, only valid for configuration chain + * type! */ size_t num_prog_clocks() const; /* Get information of the programming clock port: name and width */ openfpga::BasicPort prog_clock_port_info() const; - /* Get a list of programming clock pins, flatten from the programming clock port */ + /* Get a list of programming clock pins, flatten from the programming clock + * port */ std::vector prog_clock_pins() const; /* Get a list of programming clock ports */ std::string prog_clock_pin_ccff_head_indices_str( diff --git a/libs/libarchopenfpga/src/read_xml_config_protocol.cpp b/libs/libarchopenfpga/src/read_xml_config_protocol.cpp index b1d9acd76..b51d9f237 100644 --- a/libs/libarchopenfpga/src/read_xml_config_protocol.cpp +++ b/libs/libarchopenfpga/src/read_xml_config_protocol.cpp @@ -67,8 +67,7 @@ static void read_xml_ccff_prog_clock(pugi::xml_node& xml_progclk, openfpga::BasicPort port = openfpga::PortParser(port_attr).port(); - config_protocol.set_prog_clock_pin_ccff_head_indices_pair(port, - indices_attr); + config_protocol.set_prog_clock_pin_ccff_head_indices_pair(port, indices_attr); } /******************************************************************** @@ -187,11 +186,12 @@ static void read_xml_config_organization(pugi::xml_node& xml_config_orgz, /* Error out if the XML child has an invalid name! */ if (xml_progclk.name() != std::string(XML_CONFIG_PROTOCOL_CCFF_PROG_CLOCK_NODE_NAME)) { - bad_tag(xml_progclk, loc_data, xml_config_orgz, {XML_CONFIG_PROTOCOL_CCFF_PROG_CLOCK_NODE_NAME}); + bad_tag(xml_progclk, loc_data, xml_config_orgz, + {XML_CONFIG_PROTOCOL_CCFF_PROG_CLOCK_NODE_NAME}); } std::string port_attr = - get_attribute(xml_progclk, XML_CONFIG_PROTOCOL_CCFF_PROG_CLOCK_PORT_ATTR, - loc_data) + get_attribute(xml_progclk, + XML_CONFIG_PROTOCOL_CCFF_PROG_CLOCK_PORT_ATTR, loc_data) .as_string(); openfpga::BasicPort port = openfpga::PortParser(port_attr).port(); if (prog_clk_port.get_name().empty()) { @@ -200,7 +200,10 @@ static void read_xml_config_organization(pugi::xml_node& xml_config_orgz, } else { if (prog_clk_port.get_name() != port.get_name()) { archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_progclk), - "Expect same name for all the programming clocks (This: %s, Others: %s)!\n", port.get_name().c_str(), prog_clk_port.get_name().c_str()); + "Expect same name for all the programming clocks " + "(This: %s, Others: %s)!\n", + port.get_name().c_str(), + prog_clk_port.get_name().c_str()); } if (prog_clk_port.get_msb() < port.get_msb()) { prog_clk_port.set_msb(port.get_msb()); @@ -214,7 +217,8 @@ static void read_xml_config_organization(pugi::xml_node& xml_config_orgz, /* Error out if the XML child has an invalid name! */ if (xml_progclk.name() != std::string(XML_CONFIG_PROTOCOL_CCFF_PROG_CLOCK_NODE_NAME)) { - bad_tag(xml_progclk, loc_data, xml_config_orgz, {XML_CONFIG_PROTOCOL_CCFF_PROG_CLOCK_NODE_NAME}); + bad_tag(xml_progclk, loc_data, xml_config_orgz, + {XML_CONFIG_PROTOCOL_CCFF_PROG_CLOCK_NODE_NAME}); } read_xml_ccff_prog_clock(xml_progclk, loc_data, config_protocol); } diff --git a/openfpga/src/fabric/build_top_module.cpp b/openfpga/src/fabric/build_top_module.cpp index b333a8010..3de1dc176 100644 --- a/openfpga/src/fabric/build_top_module.cpp +++ b/openfpga/src/fabric/build_top_module.cpp @@ -595,7 +595,8 @@ int build_top_module( } } - /* For configuration chains, we avoid adding nets for programmable clocks if there are a few */ + /* For configuration chains, we avoid adding nets for programmable clocks if + * there are a few */ std::vector global_port_blacklist; if (config_protocol.num_prog_clocks() > 1) { BasicPort prog_clk_port = config_protocol.prog_clock_port_info(); @@ -604,7 +605,8 @@ int build_top_module( ModulePortId port_id = module_manager.add_port( top_module, prog_clk_port, ModuleManager::MODULE_GLOBAL_PORT); /* Add nets by following configurable children under different regions */ - add_top_module_nets_prog_clock(module_manager, top_module, port_id, config_protocol); + add_top_module_nets_prog_clock(module_manager, top_module, port_id, + config_protocol); } /* Add global ports to the top module: @@ -614,7 +616,8 @@ int build_top_module( * @note This function is called after the * add_top_module_nets_memory_config_bus() because it may add some sub modules */ - add_module_global_ports_from_child_modules(module_manager, top_module, global_port_blacklist); + add_module_global_ports_from_child_modules(module_manager, top_module, + global_port_blacklist); return status; } diff --git a/openfpga/src/fabric/build_top_module_connection.cpp b/openfpga/src/fabric/build_top_module_connection.cpp index f25db810d..d2284d318 100644 --- a/openfpga/src/fabric/build_top_module_connection.cpp +++ b/openfpga/src/fabric/build_top_module_connection.cpp @@ -1270,9 +1270,9 @@ int add_top_module_global_ports_from_grid_modules( } /******************************************************************** - * Build the connection between the programming clock port at the top module and each configurable children - * Note that each programming clock pin drive one or more configuration regions - * For example: + * Build the connection between the programming clock port at the top module and + *each configurable children Note that each programming clock pin drive one or + *more configuration regions For example: * - pin[0] -> region 0, 1 * - pin[1] -> region 2, 3 *******************************************************************/ @@ -1284,31 +1284,34 @@ void add_top_module_nets_prog_clock(ModuleManager& module_manager, for (size_t net_src_pin_id : src_port_info.pins()) { /* Create the net */ ModuleNetId net = create_module_source_pin_net( - module_manager, top_module, top_module, 0, - src_port, src_port_info.pins()[net_src_pin_id]); + module_manager, top_module, top_module, 0, src_port, + src_port_info.pins()[net_src_pin_id]); /* Find all the sink nodes and build the connection one by one */ - for (size_t iregion : config_protocol.prog_clock_pin_ccff_head_indices(BasicPort(src_port_info.get_name(), net_src_pin_id, net_src_pin_id))) { + for (size_t iregion : + config_protocol.prog_clock_pin_ccff_head_indices(BasicPort( + src_port_info.get_name(), net_src_pin_id, net_src_pin_id))) { ConfigRegionId config_region = ConfigRegionId(iregion); for (size_t mem_index = 0; mem_index < module_manager .region_configurable_children( top_module, config_region) .size(); ++mem_index) { - ModuleId net_sink_module_id = module_manager.region_configurable_children( - top_module, config_region)[mem_index]; + ModuleId net_sink_module_id = + module_manager.region_configurable_children(top_module, + config_region)[mem_index]; size_t net_sink_instance_id = module_manager.region_configurable_child_instances( top_module, config_region)[mem_index]; - ModulePortId net_sink_port_id = - module_manager.find_module_port(net_sink_module_id, src_port_info.get_name()); + ModulePortId net_sink_port_id = module_manager.find_module_port( + net_sink_module_id, src_port_info.get_name()); BasicPort net_sink_port = module_manager.module_port(net_sink_module_id, net_sink_port_id); VTR_ASSERT(1 == net_sink_port.get_width()); for (size_t net_sink_pin_id : net_sink_port.pins()) { /* Add net sink */ - module_manager.add_module_net_sink(top_module, net, net_sink_module_id, - net_sink_instance_id, net_sink_port_id, - net_sink_port.pins()[net_sink_pin_id]); + module_manager.add_module_net_sink( + top_module, net, net_sink_module_id, net_sink_instance_id, + net_sink_port_id, net_sink_port.pins()[net_sink_pin_id]); } } } diff --git a/openfpga/src/fabric/build_top_module_connection.h b/openfpga/src/fabric/build_top_module_connection.h index 0fcb99668..a155d6a7d 100644 --- a/openfpga/src/fabric/build_top_module_connection.h +++ b/openfpga/src/fabric/build_top_module_connection.h @@ -6,8 +6,8 @@ *******************************************************************/ #include -#include "config_protocol.h" #include "clock_network.h" +#include "config_protocol.h" #include "device_grid.h" #include "device_rr_gsb.h" #include "module_manager.h" diff --git a/openfpga/src/utils/module_manager_utils.cpp b/openfpga/src/utils/module_manager_utils.cpp index 334eef4a5..8e7361c9b 100644 --- a/openfpga/src/utils/module_manager_utils.cpp +++ b/openfpga/src/utils/module_manager_utils.cpp @@ -2185,7 +2185,8 @@ void add_module_gpio_ports_from_child_modules(ModuleManager& module_manager, * Otherwise, some global ports of the sub modules may be missed! *******************************************************************/ void add_module_global_input_ports_from_child_modules( - ModuleManager& module_manager, const ModuleId& module_id, const std::vector& port_name_to_ignore) { + ModuleManager& module_manager, const ModuleId& module_id, + const std::vector& port_name_to_ignore) { std::vector global_ports_to_add; /* Iterate over the child modules */ @@ -2205,7 +2206,8 @@ void add_module_global_input_ports_from_child_modules( /* Reach here, this is an unique global port, update the list * Final check: ignore those in the blacklist */ - if (std::find(port_name_to_ignore.begin(), port_name_to_ignore.end(), global_port.get_name()) == port_name_to_ignore.end()) { + if (std::find(port_name_to_ignore.begin(), port_name_to_ignore.end(), + global_port.get_name()) == port_name_to_ignore.end()) { global_ports_to_add.push_back(global_port); } } @@ -2307,11 +2309,12 @@ void add_module_global_input_ports_from_child_modules( * have been added to the pb_module! * Otherwise, some global ports of the sub modules may be missed! *******************************************************************/ -void add_module_global_ports_from_child_modules(ModuleManager& module_manager, - const ModuleId& module_id, - const std::vector& port_name_to_ignore) { +void add_module_global_ports_from_child_modules( + ModuleManager& module_manager, const ModuleId& module_id, + const std::vector& port_name_to_ignore) { /* Input ports */ - add_module_global_input_ports_from_child_modules(module_manager, module_id, port_name_to_ignore); + add_module_global_input_ports_from_child_modules(module_manager, module_id, + port_name_to_ignore); } /******************************************************************** diff --git a/openfpga/src/utils/module_manager_utils.h b/openfpga/src/utils/module_manager_utils.h index cff5cc966..bd4e43130 100644 --- a/openfpga/src/utils/module_manager_utils.h +++ b/openfpga/src/utils/module_manager_utils.h @@ -148,14 +148,16 @@ size_t find_module_num_config_bits( void add_module_global_input_ports_from_child_modules( ModuleManager& module_manager, const ModuleId& module_id, - const std::vector& port_name_to_ignore = std::vector()); + const std::vector& port_name_to_ignore = + std::vector()); void add_module_global_output_ports_from_child_modules( ModuleManager& module_manager, const ModuleId& module_id); -void add_module_global_ports_from_child_modules(ModuleManager& module_manager, - const ModuleId& module_id, - const std::vector& port_name_to_ignore = std::vector()); +void add_module_global_ports_from_child_modules( + ModuleManager& module_manager, const ModuleId& module_id, + const std::vector& port_name_to_ignore = + std::vector()); void add_module_gpio_ports_from_child_modules(ModuleManager& module_manager, const ModuleId& module_id); From ba90f5020b5d4549f145bb822bbd785d8a392da4 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 23 Apr 2023 16:48:14 +0800 Subject: [PATCH 153/166] [core] fixed some bugs which cause netlist generation failed --- libs/libarchopenfpga/src/config_protocol.cpp | 6 +++--- openfpga/src/utils/check_config_protocol.cpp | 2 +- openfpga/src/utils/module_manager_utils.cpp | 13 ++++++++++++- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/libs/libarchopenfpga/src/config_protocol.cpp b/libs/libarchopenfpga/src/config_protocol.cpp index 167f8745c..2ab7974dc 100644 --- a/libs/libarchopenfpga/src/config_protocol.cpp +++ b/libs/libarchopenfpga/src/config_protocol.cpp @@ -260,7 +260,7 @@ int ConfigProtocol::validate_ccff_prog_clocks() const { std::vector ccff_head_scoreboard(num_regions(), 0); for (openfpga::BasicPort port : prog_clock_pins()) { /* Must be valid first */ - if (port.is_valid()) { + if (!port.is_valid()) { VTR_LOG_ERROR("Programming clock '%s[%d:%d]' is not a valid port!\n", port.get_name().c_str(), port.get_lsb(), port.get_msb()); num_err++; @@ -286,9 +286,9 @@ int ConfigProtocol::validate_ccff_prog_clocks() const { ccff_head_scoreboard[ccff_head_idx]++; } } - if (prog_clock_pins().size() != (size_t)num_regions()) { + if (prog_clock_pins().size() > (size_t)num_regions()) { VTR_LOG_ERROR( - "Number of programming clocks '%ld' does not match the number of " + "Number of programming clocks '%ld' is more than the number of " "configuration regions '%ld'!\n", prog_clock_pins().size(), num_regions()); num_err++; diff --git a/openfpga/src/utils/check_config_protocol.cpp b/openfpga/src/utils/check_config_protocol.cpp index 42dc99c51..aba9a58d5 100644 --- a/openfpga/src/utils/check_config_protocol.cpp +++ b/openfpga/src/utils/check_config_protocol.cpp @@ -83,7 +83,7 @@ bool check_config_protocol(const ConfigProtocol& config_protocol, const CircuitLibrary& circuit_lib) { int num_err = 0; - if (!config_protocol.validate()) { + if (0 < config_protocol.validate()) { num_err++; } diff --git a/openfpga/src/utils/module_manager_utils.cpp b/openfpga/src/utils/module_manager_utils.cpp index 8e7361c9b..4438a877d 100644 --- a/openfpga/src/utils/module_manager_utils.cpp +++ b/openfpga/src/utils/module_manager_utils.cpp @@ -2232,8 +2232,13 @@ void add_module_global_input_ports_from_child_modules( child, ModuleManager::MODULE_GLOBAL_PORT)) { BasicPort child_global_port = module_manager.module_port(child, child_global_port_id); + /* Skip if it is in the ignore list */ + if (std::find(port_name_to_ignore.begin(), port_name_to_ignore.end(), + child_global_port.get_name()) != port_name_to_ignore.end()) { + continue; + } + /* Search in the global port list to be added, find the port id */ - std::vector::iterator it = std::find(global_ports_to_add.begin(), global_ports_to_add.end(), child_global_port); @@ -2259,6 +2264,12 @@ void add_module_global_input_ports_from_child_modules( child, ModuleManager::MODULE_GLOBAL_PORT)) { BasicPort child_global_port = module_manager.module_port(child, child_global_port_id); + /* Skip if it is in the ignore list */ + if (std::find(port_name_to_ignore.begin(), port_name_to_ignore.end(), + child_global_port.get_name()) != port_name_to_ignore.end()) { + continue; + } + /* Search in the global port list to be added, find the port id */ std::vector::iterator it = std::find(global_ports_to_add.begin(), global_ports_to_add.end(), From 1ba3c56cf395116e0bc614f031f572dda589ec43 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 23 Apr 2023 16:49:19 +0800 Subject: [PATCH 154/166] [core] code format --- openfpga/src/utils/module_manager_utils.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/openfpga/src/utils/module_manager_utils.cpp b/openfpga/src/utils/module_manager_utils.cpp index 4438a877d..90dbc2b41 100644 --- a/openfpga/src/utils/module_manager_utils.cpp +++ b/openfpga/src/utils/module_manager_utils.cpp @@ -2234,10 +2234,11 @@ void add_module_global_input_ports_from_child_modules( module_manager.module_port(child, child_global_port_id); /* Skip if it is in the ignore list */ if (std::find(port_name_to_ignore.begin(), port_name_to_ignore.end(), - child_global_port.get_name()) != port_name_to_ignore.end()) { + child_global_port.get_name()) != + port_name_to_ignore.end()) { continue; } - + /* Search in the global port list to be added, find the port id */ std::vector::iterator it = std::find(global_ports_to_add.begin(), global_ports_to_add.end(), @@ -2266,7 +2267,8 @@ void add_module_global_input_ports_from_child_modules( module_manager.module_port(child, child_global_port_id); /* Skip if it is in the ignore list */ if (std::find(port_name_to_ignore.begin(), port_name_to_ignore.end(), - child_global_port.get_name()) != port_name_to_ignore.end()) { + child_global_port.get_name()) != + port_name_to_ignore.end()) { continue; } From 667d9df028da882bbc469422755cd5e6a67dfa9f Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 24 Apr 2023 11:36:21 +0800 Subject: [PATCH 155/166] [core] developing testbench generator for ccff v2 --- libs/libarchopenfpga/src/config_protocol.cpp | 5 +- .../fpga_verilog/verilog_testbench_utils.cpp | 2 +- .../fpga_verilog/verilog_top_testbench.cpp | 119 ++++++++++++++---- .../verilog_top_testbench_constants.h | 1 + openfpga/src/utils/fabric_bitstream_utils.cpp | 13 +- openfpga/src/utils/fabric_bitstream_utils.h | 4 +- 6 files changed, 113 insertions(+), 31 deletions(-) diff --git a/libs/libarchopenfpga/src/config_protocol.cpp b/libs/libarchopenfpga/src/config_protocol.cpp index 2ab7974dc..fc3a43d95 100644 --- a/libs/libarchopenfpga/src/config_protocol.cpp +++ b/libs/libarchopenfpga/src/config_protocol.cpp @@ -28,7 +28,10 @@ int ConfigProtocol::num_regions() const { return num_regions_; } size_t ConfigProtocol::num_prog_clocks() const { VTR_ASSERT(type_ == CONFIG_MEM_SCAN_CHAIN); - return prog_clk_port_.get_width(); + if (prog_clk_port_.is_valid()) { + return prog_clk_port_.get_width(); + } + return 1; } openfpga::BasicPort ConfigProtocol::prog_clock_port_info() const { diff --git a/openfpga/src/fpga_verilog/verilog_testbench_utils.cpp b/openfpga/src/fpga_verilog/verilog_testbench_utils.cpp index 6e70f8008..8c91e50d0 100644 --- a/openfpga/src/fpga_verilog/verilog_testbench_utils.cpp +++ b/openfpga/src/fpga_verilog/verilog_testbench_utils.cpp @@ -619,7 +619,7 @@ void print_verilog_testbench_check( /* If there is a config done signal specified, consider it as a trigger on * checking */ if (!config_done_name.empty()) { - fp << "if (1'b1 == " << config_done_name << ") "; + fp << "\t\t\tif (1'b1 == " << config_done_name << ") "; } fp << "begin" << std::endl; diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp index 720f166e3..47f5c69e4 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp @@ -44,6 +44,20 @@ static std::string generate_top_testbench_clock_name( return prefix + port_name; } +/******************************************************************** + * In most cases we should have only one programming clock and hence a config done signals + * But there is one exception: + * When there are more than 1 programming clocks defined in CCFF chains, the port width of + * config done port should be the same as the programming clocks + *******************************************************************/ +static size_t find_config_protocol_num_prog_clocks(const ConfigProtocol& config_protocol) { + size_t num_config_done_signals = 1; + if (config_protocol.type() == CONFIG_MEM_SCAN_CHAIN) { + num_config_done_signals = config_protocol.num_prog_clocks(); + } + return num_config_done_signals; +} + /******************************************************************** * Print local wires for flatten memory (standalone) configuration protocols *******************************************************************/ @@ -270,6 +284,7 @@ static void print_verilog_top_testbench_config_protocol_port( static void print_verilog_top_testbench_global_clock_ports_stimuli( std::fstream& fp, const ModuleManager& module_manager, const ModuleId& top_module, + const ConfigProtocol& config_protocol, const FabricGlobalPortInfo& fabric_global_port_info, const SimulationSetting& simulation_parameters) { /* Validate the file stream */ @@ -304,7 +319,8 @@ static void print_verilog_top_testbench_global_clock_ports_stimuli( if (true == fabric_global_port_info.global_port_is_prog(fabric_global_port)) { stimuli_clock_port.set_name(std::string(TOP_TB_PROG_CLOCK_PORT_NAME)); - stimuli_clock_port.set_width(1); + size_t num_prog_clocks = find_config_protocol_num_prog_clocks(config_protocol); + stimuli_clock_port.set_width(num_prog_clocks); } else { VTR_ASSERT_SAFE(false == fabric_global_port_info.global_port_is_prog( fabric_global_port)); @@ -332,9 +348,17 @@ static void print_verilog_top_testbench_global_clock_ports_stimuli( simulation_parameters.clock_name(sim_clock))); } } + /* For programming clocks, they are connected pin by pin. For example, + * prog_clock[0] <= __prog_clock__[0] + * prog_clock[1] <= __prog_clock__[1] + */ + BasicPort stimuli_clock_pin(stimuli_clock_port); + if (stimuli_clock_port.get_name() == std::string(TOP_TB_PROG_CLOCK_PORT_NAME)) { + stimuli_clock_pin.set_width(stimuli_clock_pin.pins()[pin], stimuli_clock_pin.pins()[pin]); + } print_verilog_wire_connection( - fp, global_port_to_connect, stimuli_clock_port, + fp, global_port_to_connect, stimuli_clock_pin, 1 == fabric_global_port_info.global_port_default_value( fabric_global_port)); } @@ -641,6 +665,7 @@ static void print_verilog_top_testbench_regular_global_ports_stimuli( static void print_verilog_top_testbench_global_ports_stimuli( std::fstream& fp, const ModuleManager& module_manager, const ModuleId& top_module, const PinConstraints& pin_constraints, + const ConfigProtocol& config_protocol, const FabricGlobalPortInfo& fabric_global_port_info, const SimulationSetting& simulation_parameters, const bool& active_global_prog_reset, const bool& active_global_prog_set) { @@ -653,7 +678,7 @@ static void print_verilog_top_testbench_global_ports_stimuli( "----- Begin connecting global ports of FPGA fabric to stimuli -----")); print_verilog_top_testbench_global_clock_ports_stimuli( - fp, module_manager, top_module, fabric_global_port_info, + fp, module_manager, top_module, config_protocol, fabric_global_port_info, simulation_parameters); print_verilog_top_testbench_global_shift_register_clock_ports_stimuli( @@ -838,12 +863,18 @@ static void print_verilog_top_testbench_ports( * and then wire them to the ports of FPGA fabric depending on their usage */ /* Configuration done port */ - BasicPort config_done_port(std::string(TOP_TB_CONFIG_DONE_PORT_NAME), 1); + size_t num_config_done_signals = find_config_protocol_num_prog_clocks(config_protocol); + BasicPort config_done_port(std::string(TOP_TB_CONFIG_DONE_PORT_NAME), num_config_done_signals); fp << generate_verilog_port(VERILOG_PORT_REG, config_done_port) << ";" << std::endl; - /* Programming clock */ - BasicPort prog_clock_port(std::string(TOP_TB_PROG_CLOCK_PORT_NAME), 1); + /* Configuration all done port: pull up when all the config done ports are pulled up */ + BasicPort config_all_done_port(std::string(TOP_TB_CONFIG_ALL_DONE_PORT_NAME), 1); + fp << generate_verilog_port(VERILOG_PORT_REG, config_all_done_port) << ";" + << std::endl; + + /* Programming clock: same rule applied as the configuration done ports */ + BasicPort prog_clock_port(std::string(TOP_TB_PROG_CLOCK_PORT_NAME), num_config_done_signals); fp << generate_verilog_port(VERILOG_PORT_WIRE, prog_clock_port) << ";" << std::endl; BasicPort prog_clock_register_port( @@ -946,6 +977,17 @@ static size_t calculate_num_config_clock_cycles( size_t regional_bitstream_max_size = find_fabric_regional_bitstream_max_size(fabric_bitstream); + /* For configuration chain that require multiple programming clocks. Need a different calculation */ + if (config_protocol.type() == CONFIG_MEM_SCAN_CHAIN) { + if (config_protocol.num_prog_clocks() > 1) { + regional_bitstream_max_size = 0; + for (BasicPort prog_clk_pin : config_protocol.prog_clock_pins()) { + std::vector ccff_head_indices = config_protocol.prog_clock_pin_ccff_head_indices(prog_clk_pin); + regional_bitstream_max_size += find_fabric_regional_bitstream_max_size(fabric_bitstream, ccff_head_indices); + } + } + } + size_t num_config_clock_cycles = 1 + regional_bitstream_max_size; /* Branch on the type of configuration protocol */ @@ -1120,7 +1162,9 @@ static void print_verilog_top_testbench_generic_stimulus( fp, std::string("----- Number of clock cycles in configuration phase: " + std::to_string(num_config_clock_cycles) + " -----")); - BasicPort config_done_port(std::string(TOP_TB_CONFIG_DONE_PORT_NAME), 1); + size_t num_config_done_signals = find_config_protocol_num_prog_clocks(config_protocol); + BasicPort config_done_port(std::string(TOP_TB_CONFIG_DONE_PORT_NAME), num_config_done_signals); + BasicPort config_all_done_port(std::string(TOP_TB_CONFIG_ALL_DONE_PORT_NAME), 1); BasicPort op_clock_port(std::string(TOP_TB_OP_CLOCK_PORT_NAME), 1); BasicPort op_clock_register_port( @@ -1128,7 +1172,7 @@ static void print_verilog_top_testbench_generic_stimulus( std::string(TOP_TB_CLOCK_REG_POSTFIX)), 1); - BasicPort prog_clock_port(std::string(TOP_TB_PROG_CLOCK_PORT_NAME), 1); + BasicPort prog_clock_port(std::string(TOP_TB_PROG_CLOCK_PORT_NAME), num_config_done_signals); BasicPort prog_clock_register_port( std::string(std::string(TOP_TB_PROG_CLOCK_PORT_NAME) + std::string(TOP_TB_CLOCK_REG_POSTFIX)), @@ -1168,18 +1212,41 @@ static void print_verilog_top_testbench_generic_stimulus( fp, std::string("----- Actual programming clock is triggered only when " + config_done_port.get_name() + " and " + prog_reset_port.get_name() + " are disabled -----")); - fp << "\tassign " - << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port); - fp << " = " - << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_register_port); - fp << " & (~" << generate_verilog_port(VERILOG_PORT_CONKT, config_done_port) - << ")"; - fp << " & (~" << generate_verilog_port(VERILOG_PORT_CONKT, prog_reset_port) - << ")"; - fp << ";" << std::endl; + VTR_ASSERT(prog_clock_port.get_width() == config_done_port.get_width()); + for (size_t pin : prog_clock_port.pins()) { + BasicPort curr_clk_pin(prog_clock_port.get_name(), prog_clock_port.pins()[pin], prog_clock_port.pins()[pin]); + BasicPort curr_cfg_pin(config_done_port.get_name(), config_done_port.pins()[pin], config_done_port.pins()[pin]); + fp << "\tassign " + << generate_verilog_port(VERILOG_PORT_CONKT, curr_clk_pin); + fp << " = " + << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_register_port); + if (pin > 0) { + BasicPort prev_cfg_pin(config_done_port.get_name(), config_done_port.pins()[pin - 1], config_done_port.pins()[pin - 1]); + fp << " & (" << generate_verilog_port(VERILOG_PORT_CONKT, prev_cfg_pin) + << ")"; + } + fp << " & (~" << generate_verilog_port(VERILOG_PORT_CONKT, curr_cfg_pin) + << ")"; + fp << " & (~" << generate_verilog_port(VERILOG_PORT_CONKT, prog_reset_port) + << ")"; + fp << ";" << std::endl; + } fp << std::endl; + /* Config all done signal is triggered when all the config done signals are pulled up */ + fp << "\tassign " + << generate_verilog_port(VERILOG_PORT_CONKT, config_all_done_port); + << " = "; + for (size_t pin : config_done_port.pins()) { + BasicPort curr_cfg_pin(config_done_port.get_name(), config_done_port.pins()[pin], config_done_port.pins()[pin]); + if (pin > 1) { + fp << " & "; + } + fp << generate_verilog_port(VERILOG_PORT_CONKT, curr_cfg_pin); + } + fp << ";"; + /* Generate stimuli waveform for multiple user-defined operating clock signals */ for (const SimulationClockId& sim_clock : @@ -1210,12 +1277,12 @@ static void print_verilog_top_testbench_generic_stimulus( */ print_verilog_comment( fp, std::string("----- Actual operating clock is triggered only when " + - config_done_port.get_name() + " is enabled -----")); + config_all_done_port.get_name() + " is enabled -----")); fp << "\tassign " << generate_verilog_port(VERILOG_PORT_CONKT, sim_clock_port); fp << " = " << generate_verilog_port(VERILOG_PORT_CONKT, sim_clock_register_port); - fp << " & " << generate_verilog_port(VERILOG_PORT_CONKT, config_done_port); + fp << " & " << generate_verilog_port(VERILOG_PORT_CONKT, config_all_done_port); fp << ";" << std::endl; fp << std::endl; @@ -1231,16 +1298,16 @@ static void print_verilog_top_testbench_generic_stimulus( fp, "----- End raw operating clock signal generation -----"); /* Operation clock should be enabled after programming phase finishes. - * Before configuration is done (config_done is enabled), operation clock + * Before configuration is done (config_all_done is enabled), operation clock * should be always zero. */ print_verilog_comment( fp, std::string("----- Actual operating clock is triggered only when " + - config_done_port.get_name() + " is enabled -----")); + config_all_done_port.get_name() + " is enabled -----")); fp << "\tassign " << generate_verilog_port(VERILOG_PORT_CONKT, op_clock_port); fp << " = " << generate_verilog_port(VERILOG_PORT_CONKT, op_clock_register_port); - fp << " & " << generate_verilog_port(VERILOG_PORT_CONKT, config_done_port); + fp << " & " << generate_verilog_port(VERILOG_PORT_CONKT, config_all_done_port); fp << ";" << std::endl; fp << std::endl; @@ -1283,7 +1350,7 @@ static void print_verilog_top_testbench_generic_stimulus( "----- Reset signal is enabled until the first clock " "cycle in operation phase -----"); print_verilog_pulse_stimuli(fp, reset_port, 1, reset_pulse_widths, - reset_flip_values, config_done_port.get_name()); + reset_flip_values, config_all_done_port.get_name()); print_verilog_comment(fp, "----- End operating reset signal generation -----"); @@ -2276,7 +2343,7 @@ int print_verilog_full_testbench( /* Generate stimuli for global ports or connect them to existed signals */ print_verilog_top_testbench_global_ports_stimuli( - fp, module_manager, top_module, pin_constraints, global_ports, + fp, module_manager, top_module, pin_constraints, config_protocol, global_ports, simulation_parameters, active_global_prog_reset, active_global_prog_set); /* Instanciate FPGA top-level module */ @@ -2337,13 +2404,13 @@ int print_verilog_full_testbench( std::string(TOP_TESTBENCH_REFERENCE_OUTPUT_POSTFIX), std::string(TOP_TESTBENCH_FPGA_OUTPUT_POSTFIX), std::string(TOP_TESTBENCH_CHECKFLAG_PORT_POSTFIX), - std::string(TOP_TB_CONFIG_DONE_PORT_NAME), + std::string(TOP_TB_CONFIG_ALL_DONE_PORT_NAME), std::string(TOP_TESTBENCH_ERROR_COUNTER), atom_ctx, netlist_annotation, clock_port_names, std::string(TOP_TB_OP_CLOCK_PORT_NAME)); /* Add autocheck for configuration phase */ print_verilog_top_testbench_check(fp, - std::string(TOP_TB_CONFIG_DONE_PORT_NAME), + std::string(TOP_TB_CONFIG_ALL_DONE_PORT_NAME), std::string(TOP_TESTBENCH_ERROR_COUNTER)); } diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench_constants.h b/openfpga/src/fpga_verilog/verilog_top_testbench_constants.h index 1d1640d0c..8cf93135c 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench_constants.h +++ b/openfpga/src/fpga_verilog/verilog_top_testbench_constants.h @@ -23,6 +23,7 @@ constexpr const char* TOP_TB_SET_PORT_NAME = "__gset__"; constexpr const char* TOP_TB_PROG_RESET_PORT_NAME = "__prog_reset__"; constexpr const char* TOP_TB_PROG_SET_PORT_NAME = "__prog_set_"; constexpr const char* TOP_TB_CONFIG_DONE_PORT_NAME = "__config_done__"; +constexpr const char* TOP_TB_CONFIG_ALL_DONE_PORT_NAME = "__config_all_done__"; constexpr const char* TOP_TB_OP_CLOCK_PORT_NAME = "__op_clock__"; constexpr const char* TOP_TB_OP_CLOCK_PORT_PREFIX = "__operating_clk_"; constexpr const char* TOP_TB_PROG_CLOCK_PORT_NAME = "__prog_clock__"; diff --git a/openfpga/src/utils/fabric_bitstream_utils.cpp b/openfpga/src/utils/fabric_bitstream_utils.cpp index 00afc6e55..fdefac87e 100644 --- a/openfpga/src/utils/fabric_bitstream_utils.cpp +++ b/openfpga/src/utils/fabric_bitstream_utils.cpp @@ -22,12 +22,17 @@ namespace openfpga { /******************************************************************** * Find the longest bitstream size of a fabric bitstream + * Only care the region in whitelist. If the whitelist is empty, consider all the regions *******************************************************************/ size_t find_fabric_regional_bitstream_max_size( - const FabricBitstream& fabric_bitstream) { + const FabricBitstream& fabric_bitstream, + const std::vector& region_whitelist) { size_t regional_bitstream_max_size = 0; /* Find the longest regional bitstream */ for (const auto& region : fabric_bitstream.regions()) { + if (!region_whitelist.empty() && (std::find(region_whitelist.begin(), region_whitelist.end(), size_t(region)) != region_whitelist.end())) { + continue; + } if (regional_bitstream_max_size < fabric_bitstream.region_bits(region).size()) { regional_bitstream_max_size = fabric_bitstream.region_bits(region).size(); @@ -48,12 +53,16 @@ size_t find_fabric_regional_bitstream_max_size( *******************************************************************/ size_t find_configuration_chain_fabric_bitstream_size_to_be_skipped( const FabricBitstream& fabric_bitstream, + const std::vector& region_whitelist, const BitstreamManager& bitstream_manager, const bool& bit_value_to_skip) { size_t regional_bitstream_max_size = - find_fabric_regional_bitstream_max_size(fabric_bitstream); + find_fabric_regional_bitstream_max_size(fabric_bitstream, region_whitelist); size_t num_bits_to_skip = size_t(-1); for (const auto& region : fabric_bitstream.regions()) { + if (!region_whitelist.empty() && (std::find(region_whitelist.begin(), region_whitelist.end(), size_t(region)) != region_whitelist.end())) { + continue; + } size_t curr_region_num_bits_to_skip = 0; for (const FabricBitId& bit_id : fabric_bitstream.region_bits(region)) { if (bit_value_to_skip != diff --git a/openfpga/src/utils/fabric_bitstream_utils.h b/openfpga/src/utils/fabric_bitstream_utils.h index fe8b0b9e6..1fee62fad 100644 --- a/openfpga/src/utils/fabric_bitstream_utils.h +++ b/openfpga/src/utils/fabric_bitstream_utils.h @@ -25,10 +25,12 @@ namespace openfpga { size_t find_fabric_regional_bitstream_max_size( - const FabricBitstream& fabric_bitstream); + const FabricBitstream& fabric_bitstream, + const std::vector& region_whitelist = std::vector{}); size_t find_configuration_chain_fabric_bitstream_size_to_be_skipped( const FabricBitstream& fabric_bitstream, + const std::vector& region_whitelist = std::vector{}, const BitstreamManager& bitstream_manager, const bool& bit_value_to_skip); /* Alias to a specific organization of bitstreams for frame-based configuration From 715765d81b08f5178e942e0333cb57e2eeebdd2e Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 24 Apr 2023 13:34:44 +0800 Subject: [PATCH 156/166] [core] code complete for top testbench generator on ccffv2 upgrades --- .../fpga_verilog/verilog_top_testbench.cpp | 376 +++++++++++++----- openfpga/src/utils/fabric_bitstream_utils.cpp | 4 +- openfpga/src/utils/fabric_bitstream_utils.h | 4 +- 3 files changed, 280 insertions(+), 104 deletions(-) diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp index 47f5c69e4..aa3256beb 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp @@ -1014,6 +1014,15 @@ static size_t calculate_num_config_clock_cycles( find_configuration_chain_fabric_bitstream_size_to_be_skipped( fabric_bitstream, bitstream_manager, bit_value_to_skip); + if (config_protocol.num_prog_clocks() > 1) { + num_bits_to_skip = 0; + for (BasicPort prog_clk_pin : config_protocol.prog_clock_pins()) { + std::vector ccff_head_indices = config_protocol.prog_clock_pin_ccff_head_indices(prog_clk_pin); + num_bits_to_skip += find_configuration_chain_fabric_bitstream_size_to_be_skipped( + fabric_bitstream, bitstream_manager, bit_value_to_skip, ccff_head_indices); + } + } + num_config_clock_cycles = 1 + regional_bitstream_max_size - num_bits_to_skip; @@ -1152,7 +1161,7 @@ static void print_verilog_top_testbench_benchmark_instance( * 7. set signal *******************************************************************/ static void print_verilog_top_testbench_generic_stimulus( - std::fstream& fp, const SimulationSetting& simulation_parameters, + std::fstream& fp, const ConfigProtocol& config_protocol, const SimulationSetting& simulation_parameters, const size_t& num_config_clock_cycles, const float& prog_clock_period, const float& op_clock_period, const float& timescale) { /* Validate the file stream */ @@ -1236,7 +1245,7 @@ static void print_verilog_top_testbench_generic_stimulus( /* Config all done signal is triggered when all the config done signals are pulled up */ fp << "\tassign " - << generate_verilog_port(VERILOG_PORT_CONKT, config_all_done_port); + << generate_verilog_port(VERILOG_PORT_CONKT, config_all_done_port) << " = "; for (size_t pin : config_done_port.pins()) { BasicPort curr_cfg_pin(config_done_port.get_name(), config_done_port.pins()[pin], config_done_port.pins()[pin]); @@ -1546,7 +1555,8 @@ static void print_verilog_full_testbench_configuration_chain_bitstream( const bool& fast_configuration, const bool& bit_value_to_skip, const ModuleManager& module_manager, const ModuleId& top_module, const BitstreamManager& bitstream_manager, - const FabricBitstream& fabric_bitstream) { + const FabricBitstream& fabric_bitstream, + const ConfigProtocol& config_protocol) { /* Validate the file stream */ valid_file_stream(fp); @@ -1566,12 +1576,29 @@ static void print_verilog_full_testbench_configuration_chain_bitstream( } VTR_ASSERT(num_bits_to_skip < regional_bitstream_max_size); + size_t num_prog_clocks = find_config_protocol_num_prog_clocks(config_protocol); + /* Define a constant for the bitstream length */ print_verilog_define_flag(fp, std::string(TOP_TB_BITSTREAM_LENGTH_VARIABLE), regional_bitstream_max_size - num_bits_to_skip); print_verilog_define_flag(fp, std::string(TOP_TB_BITSTREAM_WIDTH_VARIABLE), fabric_bitstream.num_regions()); + /* Additional constants for multiple programming clock */ + if (num_prog_clocks > 1) { + for (size_t iclk = 0; iclk < num_prog_clocks; ++iclk) { + std::vector ccff_head_indices = config_protocol.prog_clock_pin_ccff_head_indices(config_protocol.prog_clock_pins()[iclk]); + size_t curr_regional_bitstream_max_size = + find_fabric_regional_bitstream_max_size(fabric_bitstream, ccff_head_indices); + size_t curr_num_bits_to_skip = + find_configuration_chain_fabric_bitstream_size_to_be_skipped( + fabric_bitstream, bitstream_manager, bit_value_to_skip, ccff_head_indices); + + print_verilog_define_flag(fp, std::string(TOP_TB_BITSTREAM_LENGTH_VARIABLE) + std::to_string(iclk), + curr_regional_bitstream_max_size - curr_num_bits_to_skip); + } + } + /* Initial value should be the first configuration bits * In the rest of programming cycles, * configuration bits are fed at the falling edge of programming clock. @@ -1592,10 +1619,18 @@ static void print_verilog_full_testbench_configuration_chain_bitstream( << TOP_TB_BITSTREAM_LENGTH_VARIABLE << " - 1];"; fp << std::endl; - fp << "reg [$clog2(`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE << "):0] " - << TOP_TB_BITSTREAM_INDEX_REG_NAME << ";" << std::endl; + if (num_prog_clocks == 1) { + fp << "reg [$clog2(`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE << "):0] " + << TOP_TB_BITSTREAM_INDEX_REG_NAME << ";" << std::endl; + } else { + VTR_ASSERT(num_prog_clocks > 1); + for (size_t iclk = 0; iclk < num_prog_clocks; ++iclk) { + fp << "reg [$clog2(`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE << iclk << "):0] " + << TOP_TB_BITSTREAM_INDEX_REG_NAME << iclk << ";" << std::endl; + } + } - BasicPort bit_skip_reg(TOP_TB_BITSTREAM_SKIP_FLAG_REG_NAME, 1); + BasicPort bit_skip_reg(TOP_TB_BITSTREAM_SKIP_FLAG_REG_NAME, num_prog_clocks); print_verilog_comment( fp, "----- Registers used for fast configuration logic -----"); fp << "reg [$clog2(`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE << "):0] " @@ -1631,64 +1666,139 @@ static void print_verilog_full_testbench_configuration_chain_bitstream( fp << ";"; fp << std::endl; - fp << "\t"; - fp << "for (" << TOP_TB_BITSTREAM_ITERATOR_REG_NAME << " = 0; "; - fp << TOP_TB_BITSTREAM_ITERATOR_REG_NAME << " < `" - << TOP_TB_BITSTREAM_LENGTH_VARIABLE << " + 1; "; - fp << TOP_TB_BITSTREAM_ITERATOR_REG_NAME << " = " - << TOP_TB_BITSTREAM_ITERATOR_REG_NAME << " + 1)"; - fp << " begin"; - fp << std::endl; + if (num_prog_clocks == 1) { + fp << "\t"; + fp << "for (" << TOP_TB_BITSTREAM_ITERATOR_REG_NAME << " = 0; "; + fp << TOP_TB_BITSTREAM_ITERATOR_REG_NAME << " < `" + << TOP_TB_BITSTREAM_LENGTH_VARIABLE << " + 1; "; + fp << TOP_TB_BITSTREAM_ITERATOR_REG_NAME << " = " + << TOP_TB_BITSTREAM_ITERATOR_REG_NAME << " + 1)"; + fp << " begin"; + fp << std::endl; - fp << "\t\t"; - fp << "if ("; - fp << generate_verilog_constant_values( - std::vector(fabric_bitstream.num_regions(), bit_value_to_skip)); - fp << " == "; - fp << TOP_TB_BITSTREAM_MEM_REG_NAME << "[" - << TOP_TB_BITSTREAM_ITERATOR_REG_NAME << "]"; - fp << ")"; - fp << " begin"; - fp << std::endl; + fp << "\t\t"; + fp << "if ("; + fp << generate_verilog_constant_values( + std::vector(fabric_bitstream.num_regions(), bit_value_to_skip)); + fp << " == "; + fp << TOP_TB_BITSTREAM_MEM_REG_NAME << "[" + << TOP_TB_BITSTREAM_ITERATOR_REG_NAME << "]"; + fp << ")"; + fp << " begin"; + fp << std::endl; - fp << "\t\t\t"; - fp << "if ("; - fp << generate_verilog_constant_values( - std::vector(bit_skip_reg.get_width(), 1)); - fp << " == "; - fp << generate_verilog_port(VERILOG_PORT_CONKT, bit_skip_reg) << ")"; - fp << " begin"; - fp << std::endl; + fp << "\t\t\t"; + fp << "if ("; + fp << generate_verilog_constant_values( + std::vector(bit_skip_reg.get_width(), 1)); + fp << " == "; + fp << generate_verilog_port(VERILOG_PORT_CONKT, bit_skip_reg) << ")"; + fp << " begin"; + fp << std::endl; - fp << "\t\t\t\t"; - fp << TOP_TB_BITSTREAM_INDEX_REG_NAME; - fp << " <= "; - fp << TOP_TB_BITSTREAM_INDEX_REG_NAME << " + 1"; - fp << ";" << std::endl; + fp << "\t\t\t\t"; + fp << TOP_TB_BITSTREAM_INDEX_REG_NAME; + fp << " <= "; + fp << TOP_TB_BITSTREAM_INDEX_REG_NAME << " + 1"; + fp << ";" << std::endl; - fp << "\t\t\t"; - fp << "end"; - fp << std::endl; + fp << "\t\t\t"; + fp << "end"; + fp << std::endl; - fp << "\t\t"; - fp << "end else begin"; - fp << std::endl; + fp << "\t\t"; + fp << "end else begin"; + fp << std::endl; - fp << "\t\t\t"; - fp << generate_verilog_port_constant_values( - bit_skip_reg, std::vector(bit_skip_reg.get_width(), 0), true); - fp << ";" << std::endl; + fp << "\t\t\t"; + fp << generate_verilog_port_constant_values( + bit_skip_reg, std::vector(bit_skip_reg.get_width(), 0), true); + fp << ";" << std::endl; - fp << "\t\t"; - fp << "end"; - fp << std::endl; + fp << "\t\t"; + fp << "end"; + fp << std::endl; - fp << "\t"; - fp << "end"; - fp << std::endl; + fp << "\t"; + fp << "end"; + fp << std::endl; - fp << "end"; - fp << std::endl; + fp << "end"; + fp << std::endl; + } else { + VTR_ASSERT(num_prog_clocks > 1); + for (size_t iclk = 0; iclk < num_prog_clocks; ++iclk) { + fp << "\t"; + fp << "for (" << TOP_TB_BITSTREAM_ITERATOR_REG_NAME << " = 0; "; + fp << TOP_TB_BITSTREAM_ITERATOR_REG_NAME << " < `" + << TOP_TB_BITSTREAM_LENGTH_VARIABLE << iclk << " + 1; "; + fp << TOP_TB_BITSTREAM_ITERATOR_REG_NAME << " = " + << TOP_TB_BITSTREAM_ITERATOR_REG_NAME << " + 1)"; + fp << " begin"; + fp << std::endl; + + std::vector ccff_head_indices = config_protocol.prog_clock_pin_ccff_head_indices(config_protocol.prog_clock_pins()[iclk]); + fp << "\t\t"; + fp << "if ("; + bool first_pin = false; + for (size_t ccff_head_idx : ccff_head_indices) { + if (!first_pin) { + fp << " & "; + } + fp << generate_verilog_constant_values( + std::vector(1, bit_value_to_skip)); + fp << " == "; + fp << TOP_TB_BITSTREAM_MEM_REG_NAME << "[" + << TOP_TB_BITSTREAM_ITERATOR_REG_NAME << "][" + << ccff_head_idx + << "]"; + } + fp << ")"; + fp << " begin"; + fp << std::endl; + + BasicPort curr_bit_skip_reg(bit_skip_reg); + curr_bit_skip_reg.set_width(iclk, iclk); + fp << "\t\t\t"; + fp << "if ("; + fp << generate_verilog_constant_values( + std::vector(curr_bit_skip_reg.get_width(), 1)); + fp << " == "; + fp << generate_verilog_port(VERILOG_PORT_CONKT, curr_bit_skip_reg) << ")"; + fp << " begin"; + fp << std::endl; + + fp << "\t\t\t\t"; + fp << TOP_TB_BITSTREAM_INDEX_REG_NAME << iclk; + fp << " <= "; + fp << TOP_TB_BITSTREAM_INDEX_REG_NAME << iclk << " + 1"; + fp << ";" << std::endl; + + fp << "\t\t\t"; + fp << "end"; + fp << std::endl; + + fp << "\t\t"; + fp << "end else begin"; + fp << std::endl; + + fp << "\t\t\t"; + fp << generate_verilog_port_constant_values( + curr_bit_skip_reg, std::vector(curr_bit_skip_reg.get_width(), 0), true); + fp << ";" << std::endl; + + fp << "\t\t"; + fp << "end"; + fp << std::endl; + + fp << "\t"; + fp << "end"; + fp << std::endl; + + fp << "end"; + fp << std::endl; + } + } BasicPort prog_clock_port(std::string(TOP_TB_PROG_CLOCK_PORT_NAME) + std::string(TOP_TB_CLOCK_REG_POSTFIX), @@ -1696,56 +1806,122 @@ static void print_verilog_full_testbench_configuration_chain_bitstream( print_verilog_comment(fp, "----- 'else if' condition is required by Modelsim to " "synthesis the Verilog correctly -----"); - fp << "always"; - fp << " @(negedge " - << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ")"; - fp << " begin"; - fp << std::endl; - fp << "\t"; - fp << "if ("; - fp << TOP_TB_BITSTREAM_INDEX_REG_NAME; - fp << " >= "; - fp << "`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE; - fp << ") begin"; - fp << std::endl; + if (num_prog_clocks == 1) { + fp << "always"; + fp << " @(negedge " + << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ")"; + fp << " begin"; + fp << std::endl; - BasicPort config_done_port(std::string(TOP_TB_CONFIG_DONE_PORT_NAME), 1); - fp << "\t\t"; - std::vector config_done_final_values(config_done_port.get_width(), 1); - fp << generate_verilog_port_constant_values(config_done_port, - config_done_final_values, true); - fp << ";" << std::endl; + fp << "\t"; + fp << "if ("; + fp << TOP_TB_BITSTREAM_INDEX_REG_NAME; + fp << " >= "; + fp << "`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE; + fp << ") begin"; + fp << std::endl; - fp << "\t"; - fp << "end else if ("; - fp << TOP_TB_BITSTREAM_INDEX_REG_NAME; - fp << " >= 0 && "; - fp << TOP_TB_BITSTREAM_INDEX_REG_NAME; - fp << " < "; - fp << "`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE; - fp << ") begin"; - fp << std::endl; + BasicPort config_done_port(std::string(TOP_TB_CONFIG_DONE_PORT_NAME), 1); + fp << "\t\t"; + std::vector config_done_final_values(config_done_port.get_width(), 1); + fp << generate_verilog_port_constant_values(config_done_port, + config_done_final_values, true); + fp << ";" << std::endl; - fp << "\t\t"; - fp << generate_verilog_port(VERILOG_PORT_CONKT, config_chain_head_port); - fp << " <= "; - fp << TOP_TB_BITSTREAM_MEM_REG_NAME << "[" << TOP_TB_BITSTREAM_INDEX_REG_NAME - << "]"; - fp << ";" << std::endl; + fp << "\t"; + fp << "end else if ("; + fp << TOP_TB_BITSTREAM_INDEX_REG_NAME; + fp << " >= 0 && "; + fp << TOP_TB_BITSTREAM_INDEX_REG_NAME; + fp << " < "; + fp << "`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE; + fp << ") begin"; + fp << std::endl; - fp << "\t\t"; - fp << TOP_TB_BITSTREAM_INDEX_REG_NAME; - fp << " <= "; - fp << TOP_TB_BITSTREAM_INDEX_REG_NAME << " + 1"; - fp << ";" << std::endl; + fp << "\t\t"; + fp << generate_verilog_port(VERILOG_PORT_CONKT, config_chain_head_port); + fp << " <= "; + fp << TOP_TB_BITSTREAM_MEM_REG_NAME << "[" << TOP_TB_BITSTREAM_INDEX_REG_NAME + << "]"; + fp << ";" << std::endl; - fp << "\t"; - fp << "end"; - fp << std::endl; + fp << "\t\t"; + fp << TOP_TB_BITSTREAM_INDEX_REG_NAME; + fp << " <= "; + fp << TOP_TB_BITSTREAM_INDEX_REG_NAME << " + 1"; + fp << ";" << std::endl; - fp << "end"; - fp << std::endl; + fp << "\t"; + fp << "end"; + fp << std::endl; + + fp << "end"; + fp << std::endl; + } else { + VTR_ASSERT(num_prog_clocks > 1); + for (size_t iclk = 0; iclk < num_prog_clocks; ++iclk) { + fp << "always"; + fp << " @(negedge " + << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ")"; + fp << " begin"; + fp << std::endl; + + fp << "\t"; + fp << "if ("; + fp << TOP_TB_BITSTREAM_INDEX_REG_NAME << iclk; + fp << " >= "; + fp << "`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE << iclk; + fp << ") begin"; + fp << std::endl; + + BasicPort config_done_port(std::string(TOP_TB_CONFIG_DONE_PORT_NAME), iclk, iclk); + fp << "\t\t"; + std::vector config_done_final_values(config_done_port.get_width(), 1); + fp << generate_verilog_port_constant_values(config_done_port, + config_done_final_values, true); + fp << ";" << std::endl; + + fp << "\t"; + fp << "end else if ("; + /* Wait for previous configuration chain finished */ + if (iclk > 0) { + BasicPort prev_config_done_port(std::string(TOP_TB_CONFIG_DONE_PORT_NAME), iclk - 1, iclk - 1); + std::vector prev_config_done_final_values(prev_config_done_port.get_width(), 1); + fp << generate_verilog_port(VERILOG_PORT_CONKT, prev_config_done_port); + fp << " == "; + fp << generate_verilog_constant_values(prev_config_done_final_values); + fp << " && "; + } + fp << TOP_TB_BITSTREAM_INDEX_REG_NAME << iclk; + fp << " >= 0 && "; + fp << TOP_TB_BITSTREAM_INDEX_REG_NAME << iclk; + fp << " < "; + fp << "`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE << iclk; + fp << ") begin"; + fp << std::endl; + + fp << "\t\t"; + fp << generate_verilog_port(VERILOG_PORT_CONKT, config_chain_head_port); + fp << " <= "; + fp << TOP_TB_BITSTREAM_MEM_REG_NAME << "[" << TOP_TB_BITSTREAM_INDEX_REG_NAME << iclk + << "]"; + fp << ";" << std::endl; + + fp << "\t\t"; + fp << TOP_TB_BITSTREAM_INDEX_REG_NAME << iclk; + fp << " <= "; + fp << TOP_TB_BITSTREAM_INDEX_REG_NAME << iclk << " + 1"; + fp << ";" << std::endl; + + fp << "\t"; + fp << "end"; + fp << std::endl; + + fp << "end"; + fp << std::endl; + } + } print_verilog_comment( fp, "----- End bitstream loading during configuration phase -----"); @@ -2078,7 +2254,7 @@ static void print_verilog_full_testbench_bitstream( case CONFIG_MEM_SCAN_CHAIN: print_verilog_full_testbench_configuration_chain_bitstream( fp, bitstream_file, fast_configuration, bit_value_to_skip, - module_manager, top_module, bitstream_manager, fabric_bitstream); + module_manager, top_module, bitstream_manager, fabric_bitstream, config_protocol); break; case CONFIG_MEM_MEMORY_BANK: print_verilog_full_testbench_memory_bank_bitstream( @@ -2302,7 +2478,7 @@ int print_verilog_full_testbench( /* Generate stimuli for general control signals */ print_verilog_top_testbench_generic_stimulus( - fp, simulation_parameters, num_config_clock_cycles, prog_clock_period, + fp, config_protocol, simulation_parameters, num_config_clock_cycles, prog_clock_period, default_op_clock_period, VERILOG_SIM_TIMESCALE); /* Generate stimuli for programming interface */ diff --git a/openfpga/src/utils/fabric_bitstream_utils.cpp b/openfpga/src/utils/fabric_bitstream_utils.cpp index fdefac87e..a8b5d6d82 100644 --- a/openfpga/src/utils/fabric_bitstream_utils.cpp +++ b/openfpga/src/utils/fabric_bitstream_utils.cpp @@ -53,8 +53,8 @@ size_t find_fabric_regional_bitstream_max_size( *******************************************************************/ size_t find_configuration_chain_fabric_bitstream_size_to_be_skipped( const FabricBitstream& fabric_bitstream, - const std::vector& region_whitelist, - const BitstreamManager& bitstream_manager, const bool& bit_value_to_skip) { + const BitstreamManager& bitstream_manager, const bool& bit_value_to_skip, + const std::vector& region_whitelist) { size_t regional_bitstream_max_size = find_fabric_regional_bitstream_max_size(fabric_bitstream, region_whitelist); diff --git a/openfpga/src/utils/fabric_bitstream_utils.h b/openfpga/src/utils/fabric_bitstream_utils.h index 1fee62fad..5c179ee50 100644 --- a/openfpga/src/utils/fabric_bitstream_utils.h +++ b/openfpga/src/utils/fabric_bitstream_utils.h @@ -30,8 +30,8 @@ size_t find_fabric_regional_bitstream_max_size( size_t find_configuration_chain_fabric_bitstream_size_to_be_skipped( const FabricBitstream& fabric_bitstream, - const std::vector& region_whitelist = std::vector{}, - const BitstreamManager& bitstream_manager, const bool& bit_value_to_skip); + const BitstreamManager& bitstream_manager, const bool& bit_value_to_skip, + const std::vector& region_whitelist = std::vector{}); /* Alias to a specific organization of bitstreams for frame-based configuration * protocol */ From 3c6a4d34d8e0ef49e0726593167ec17c83661f02 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 24 Apr 2023 13:36:59 +0800 Subject: [PATCH 157/166] [core] code format --- .../fpga_verilog/verilog_top_testbench.cpp | 200 +++++++++++------- openfpga/src/utils/fabric_bitstream_utils.cpp | 11 +- 2 files changed, 132 insertions(+), 79 deletions(-) diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp index aa3256beb..559277839 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp @@ -45,12 +45,13 @@ static std::string generate_top_testbench_clock_name( } /******************************************************************** - * In most cases we should have only one programming clock and hence a config done signals - * But there is one exception: - * When there are more than 1 programming clocks defined in CCFF chains, the port width of - * config done port should be the same as the programming clocks + * In most cases we should have only one programming clock and hence a config + *done signals But there is one exception: When there are more than 1 + *programming clocks defined in CCFF chains, the port width of config done port + *should be the same as the programming clocks *******************************************************************/ -static size_t find_config_protocol_num_prog_clocks(const ConfigProtocol& config_protocol) { +static size_t find_config_protocol_num_prog_clocks( + const ConfigProtocol& config_protocol) { size_t num_config_done_signals = 1; if (config_protocol.type() == CONFIG_MEM_SCAN_CHAIN) { num_config_done_signals = config_protocol.num_prog_clocks(); @@ -283,8 +284,7 @@ static void print_verilog_top_testbench_config_protocol_port( *******************************************************************/ static void print_verilog_top_testbench_global_clock_ports_stimuli( std::fstream& fp, const ModuleManager& module_manager, - const ModuleId& top_module, - const ConfigProtocol& config_protocol, + const ModuleId& top_module, const ConfigProtocol& config_protocol, const FabricGlobalPortInfo& fabric_global_port_info, const SimulationSetting& simulation_parameters) { /* Validate the file stream */ @@ -319,7 +319,8 @@ static void print_verilog_top_testbench_global_clock_ports_stimuli( if (true == fabric_global_port_info.global_port_is_prog(fabric_global_port)) { stimuli_clock_port.set_name(std::string(TOP_TB_PROG_CLOCK_PORT_NAME)); - size_t num_prog_clocks = find_config_protocol_num_prog_clocks(config_protocol); + size_t num_prog_clocks = + find_config_protocol_num_prog_clocks(config_protocol); stimuli_clock_port.set_width(num_prog_clocks); } else { VTR_ASSERT_SAFE(false == fabric_global_port_info.global_port_is_prog( @@ -353,8 +354,10 @@ static void print_verilog_top_testbench_global_clock_ports_stimuli( * prog_clock[1] <= __prog_clock__[1] */ BasicPort stimuli_clock_pin(stimuli_clock_port); - if (stimuli_clock_port.get_name() == std::string(TOP_TB_PROG_CLOCK_PORT_NAME)) { - stimuli_clock_pin.set_width(stimuli_clock_pin.pins()[pin], stimuli_clock_pin.pins()[pin]); + if (stimuli_clock_port.get_name() == + std::string(TOP_TB_PROG_CLOCK_PORT_NAME)) { + stimuli_clock_pin.set_width(stimuli_clock_pin.pins()[pin], + stimuli_clock_pin.pins()[pin]); } print_verilog_wire_connection( @@ -863,18 +866,23 @@ static void print_verilog_top_testbench_ports( * and then wire them to the ports of FPGA fabric depending on their usage */ /* Configuration done port */ - size_t num_config_done_signals = find_config_protocol_num_prog_clocks(config_protocol); - BasicPort config_done_port(std::string(TOP_TB_CONFIG_DONE_PORT_NAME), num_config_done_signals); + size_t num_config_done_signals = + find_config_protocol_num_prog_clocks(config_protocol); + BasicPort config_done_port(std::string(TOP_TB_CONFIG_DONE_PORT_NAME), + num_config_done_signals); fp << generate_verilog_port(VERILOG_PORT_REG, config_done_port) << ";" << std::endl; - /* Configuration all done port: pull up when all the config done ports are pulled up */ - BasicPort config_all_done_port(std::string(TOP_TB_CONFIG_ALL_DONE_PORT_NAME), 1); + /* Configuration all done port: pull up when all the config done ports are + * pulled up */ + BasicPort config_all_done_port(std::string(TOP_TB_CONFIG_ALL_DONE_PORT_NAME), + 1); fp << generate_verilog_port(VERILOG_PORT_REG, config_all_done_port) << ";" << std::endl; /* Programming clock: same rule applied as the configuration done ports */ - BasicPort prog_clock_port(std::string(TOP_TB_PROG_CLOCK_PORT_NAME), num_config_done_signals); + BasicPort prog_clock_port(std::string(TOP_TB_PROG_CLOCK_PORT_NAME), + num_config_done_signals); fp << generate_verilog_port(VERILOG_PORT_WIRE, prog_clock_port) << ";" << std::endl; BasicPort prog_clock_register_port( @@ -977,15 +985,18 @@ static size_t calculate_num_config_clock_cycles( size_t regional_bitstream_max_size = find_fabric_regional_bitstream_max_size(fabric_bitstream); - /* For configuration chain that require multiple programming clocks. Need a different calculation */ + /* For configuration chain that require multiple programming clocks. Need a + * different calculation */ if (config_protocol.type() == CONFIG_MEM_SCAN_CHAIN) { if (config_protocol.num_prog_clocks() > 1) { regional_bitstream_max_size = 0; for (BasicPort prog_clk_pin : config_protocol.prog_clock_pins()) { - std::vector ccff_head_indices = config_protocol.prog_clock_pin_ccff_head_indices(prog_clk_pin); - regional_bitstream_max_size += find_fabric_regional_bitstream_max_size(fabric_bitstream, ccff_head_indices); - } - } + std::vector ccff_head_indices = + config_protocol.prog_clock_pin_ccff_head_indices(prog_clk_pin); + regional_bitstream_max_size += find_fabric_regional_bitstream_max_size( + fabric_bitstream, ccff_head_indices); + } + } } size_t num_config_clock_cycles = 1 + regional_bitstream_max_size; @@ -1017,9 +1028,12 @@ static size_t calculate_num_config_clock_cycles( if (config_protocol.num_prog_clocks() > 1) { num_bits_to_skip = 0; for (BasicPort prog_clk_pin : config_protocol.prog_clock_pins()) { - std::vector ccff_head_indices = config_protocol.prog_clock_pin_ccff_head_indices(prog_clk_pin); - num_bits_to_skip += find_configuration_chain_fabric_bitstream_size_to_be_skipped( - fabric_bitstream, bitstream_manager, bit_value_to_skip, ccff_head_indices); + std::vector ccff_head_indices = + config_protocol.prog_clock_pin_ccff_head_indices(prog_clk_pin); + num_bits_to_skip += + find_configuration_chain_fabric_bitstream_size_to_be_skipped( + fabric_bitstream, bitstream_manager, bit_value_to_skip, + ccff_head_indices); } } @@ -1161,7 +1175,8 @@ static void print_verilog_top_testbench_benchmark_instance( * 7. set signal *******************************************************************/ static void print_verilog_top_testbench_generic_stimulus( - std::fstream& fp, const ConfigProtocol& config_protocol, const SimulationSetting& simulation_parameters, + std::fstream& fp, const ConfigProtocol& config_protocol, + const SimulationSetting& simulation_parameters, const size_t& num_config_clock_cycles, const float& prog_clock_period, const float& op_clock_period, const float& timescale) { /* Validate the file stream */ @@ -1171,9 +1186,12 @@ static void print_verilog_top_testbench_generic_stimulus( fp, std::string("----- Number of clock cycles in configuration phase: " + std::to_string(num_config_clock_cycles) + " -----")); - size_t num_config_done_signals = find_config_protocol_num_prog_clocks(config_protocol); - BasicPort config_done_port(std::string(TOP_TB_CONFIG_DONE_PORT_NAME), num_config_done_signals); - BasicPort config_all_done_port(std::string(TOP_TB_CONFIG_ALL_DONE_PORT_NAME), 1); + size_t num_config_done_signals = + find_config_protocol_num_prog_clocks(config_protocol); + BasicPort config_done_port(std::string(TOP_TB_CONFIG_DONE_PORT_NAME), + num_config_done_signals); + BasicPort config_all_done_port(std::string(TOP_TB_CONFIG_ALL_DONE_PORT_NAME), + 1); BasicPort op_clock_port(std::string(TOP_TB_OP_CLOCK_PORT_NAME), 1); BasicPort op_clock_register_port( @@ -1181,7 +1199,8 @@ static void print_verilog_top_testbench_generic_stimulus( std::string(TOP_TB_CLOCK_REG_POSTFIX)), 1); - BasicPort prog_clock_port(std::string(TOP_TB_PROG_CLOCK_PORT_NAME), num_config_done_signals); + BasicPort prog_clock_port(std::string(TOP_TB_PROG_CLOCK_PORT_NAME), + num_config_done_signals); BasicPort prog_clock_register_port( std::string(std::string(TOP_TB_PROG_CLOCK_PORT_NAME) + std::string(TOP_TB_CLOCK_REG_POSTFIX)), @@ -1223,14 +1242,20 @@ static void print_verilog_top_testbench_generic_stimulus( prog_reset_port.get_name() + " are disabled -----")); VTR_ASSERT(prog_clock_port.get_width() == config_done_port.get_width()); for (size_t pin : prog_clock_port.pins()) { - BasicPort curr_clk_pin(prog_clock_port.get_name(), prog_clock_port.pins()[pin], prog_clock_port.pins()[pin]); - BasicPort curr_cfg_pin(config_done_port.get_name(), config_done_port.pins()[pin], config_done_port.pins()[pin]); + BasicPort curr_clk_pin(prog_clock_port.get_name(), + prog_clock_port.pins()[pin], + prog_clock_port.pins()[pin]); + BasicPort curr_cfg_pin(config_done_port.get_name(), + config_done_port.pins()[pin], + config_done_port.pins()[pin]); fp << "\tassign " << generate_verilog_port(VERILOG_PORT_CONKT, curr_clk_pin); fp << " = " << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_register_port); if (pin > 0) { - BasicPort prev_cfg_pin(config_done_port.get_name(), config_done_port.pins()[pin - 1], config_done_port.pins()[pin - 1]); + BasicPort prev_cfg_pin(config_done_port.get_name(), + config_done_port.pins()[pin - 1], + config_done_port.pins()[pin - 1]); fp << " & (" << generate_verilog_port(VERILOG_PORT_CONKT, prev_cfg_pin) << ")"; } @@ -1243,12 +1268,15 @@ static void print_verilog_top_testbench_generic_stimulus( fp << std::endl; - /* Config all done signal is triggered when all the config done signals are pulled up */ + /* Config all done signal is triggered when all the config done signals are + * pulled up */ fp << "\tassign " << generate_verilog_port(VERILOG_PORT_CONKT, config_all_done_port) << " = "; for (size_t pin : config_done_port.pins()) { - BasicPort curr_cfg_pin(config_done_port.get_name(), config_done_port.pins()[pin], config_done_port.pins()[pin]); + BasicPort curr_cfg_pin(config_done_port.get_name(), + config_done_port.pins()[pin], + config_done_port.pins()[pin]); if (pin > 1) { fp << " & "; } @@ -1291,7 +1319,8 @@ static void print_verilog_top_testbench_generic_stimulus( << generate_verilog_port(VERILOG_PORT_CONKT, sim_clock_port); fp << " = " << generate_verilog_port(VERILOG_PORT_CONKT, sim_clock_register_port); - fp << " & " << generate_verilog_port(VERILOG_PORT_CONKT, config_all_done_port); + fp << " & " + << generate_verilog_port(VERILOG_PORT_CONKT, config_all_done_port); fp << ";" << std::endl; fp << std::endl; @@ -1316,7 +1345,8 @@ static void print_verilog_top_testbench_generic_stimulus( fp << "\tassign " << generate_verilog_port(VERILOG_PORT_CONKT, op_clock_port); fp << " = " << generate_verilog_port(VERILOG_PORT_CONKT, op_clock_register_port); - fp << " & " << generate_verilog_port(VERILOG_PORT_CONKT, config_all_done_port); + fp << " & " + << generate_verilog_port(VERILOG_PORT_CONKT, config_all_done_port); fp << ";" << std::endl; fp << std::endl; @@ -1359,7 +1389,8 @@ static void print_verilog_top_testbench_generic_stimulus( "----- Reset signal is enabled until the first clock " "cycle in operation phase -----"); print_verilog_pulse_stimuli(fp, reset_port, 1, reset_pulse_widths, - reset_flip_values, config_all_done_port.get_name()); + reset_flip_values, + config_all_done_port.get_name()); print_verilog_comment(fp, "----- End operating reset signal generation -----"); @@ -1576,7 +1607,8 @@ static void print_verilog_full_testbench_configuration_chain_bitstream( } VTR_ASSERT(num_bits_to_skip < regional_bitstream_max_size); - size_t num_prog_clocks = find_config_protocol_num_prog_clocks(config_protocol); + size_t num_prog_clocks = + find_config_protocol_num_prog_clocks(config_protocol); /* Define a constant for the bitstream length */ print_verilog_define_flag(fp, std::string(TOP_TB_BITSTREAM_LENGTH_VARIABLE), @@ -1587,15 +1619,21 @@ static void print_verilog_full_testbench_configuration_chain_bitstream( /* Additional constants for multiple programming clock */ if (num_prog_clocks > 1) { for (size_t iclk = 0; iclk < num_prog_clocks; ++iclk) { - std::vector ccff_head_indices = config_protocol.prog_clock_pin_ccff_head_indices(config_protocol.prog_clock_pins()[iclk]); + std::vector ccff_head_indices = + config_protocol.prog_clock_pin_ccff_head_indices( + config_protocol.prog_clock_pins()[iclk]); size_t curr_regional_bitstream_max_size = - find_fabric_regional_bitstream_max_size(fabric_bitstream, ccff_head_indices); + find_fabric_regional_bitstream_max_size(fabric_bitstream, + ccff_head_indices); size_t curr_num_bits_to_skip = find_configuration_chain_fabric_bitstream_size_to_be_skipped( - fabric_bitstream, bitstream_manager, bit_value_to_skip, ccff_head_indices); + fabric_bitstream, bitstream_manager, bit_value_to_skip, + ccff_head_indices); - print_verilog_define_flag(fp, std::string(TOP_TB_BITSTREAM_LENGTH_VARIABLE) + std::to_string(iclk), - curr_regional_bitstream_max_size - curr_num_bits_to_skip); + print_verilog_define_flag( + fp, + std::string(TOP_TB_BITSTREAM_LENGTH_VARIABLE) + std::to_string(iclk), + curr_regional_bitstream_max_size - curr_num_bits_to_skip); } } @@ -1625,8 +1663,9 @@ static void print_verilog_full_testbench_configuration_chain_bitstream( } else { VTR_ASSERT(num_prog_clocks > 1); for (size_t iclk = 0; iclk < num_prog_clocks; ++iclk) { - fp << "reg [$clog2(`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE << iclk << "):0] " - << TOP_TB_BITSTREAM_INDEX_REG_NAME << iclk << ";" << std::endl; + fp << "reg [$clog2(`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE << iclk + << "):0] " << TOP_TB_BITSTREAM_INDEX_REG_NAME << iclk << ";" + << std::endl; } } @@ -1736,8 +1775,10 @@ static void print_verilog_full_testbench_configuration_chain_bitstream( << TOP_TB_BITSTREAM_ITERATOR_REG_NAME << " + 1)"; fp << " begin"; fp << std::endl; - - std::vector ccff_head_indices = config_protocol.prog_clock_pin_ccff_head_indices(config_protocol.prog_clock_pins()[iclk]); + + std::vector ccff_head_indices = + config_protocol.prog_clock_pin_ccff_head_indices( + config_protocol.prog_clock_pins()[iclk]); fp << "\t\t"; fp << "if ("; bool first_pin = false; @@ -1749,14 +1790,13 @@ static void print_verilog_full_testbench_configuration_chain_bitstream( std::vector(1, bit_value_to_skip)); fp << " == "; fp << TOP_TB_BITSTREAM_MEM_REG_NAME << "[" - << TOP_TB_BITSTREAM_ITERATOR_REG_NAME << "][" - << ccff_head_idx + << TOP_TB_BITSTREAM_ITERATOR_REG_NAME << "][" << ccff_head_idx << "]"; } fp << ")"; fp << " begin"; fp << std::endl; - + BasicPort curr_bit_skip_reg(bit_skip_reg); curr_bit_skip_reg.set_width(iclk, iclk); fp << "\t\t\t"; @@ -1767,34 +1807,35 @@ static void print_verilog_full_testbench_configuration_chain_bitstream( fp << generate_verilog_port(VERILOG_PORT_CONKT, curr_bit_skip_reg) << ")"; fp << " begin"; fp << std::endl; - + fp << "\t\t\t\t"; fp << TOP_TB_BITSTREAM_INDEX_REG_NAME << iclk; fp << " <= "; fp << TOP_TB_BITSTREAM_INDEX_REG_NAME << iclk << " + 1"; fp << ";" << std::endl; - + fp << "\t\t\t"; fp << "end"; fp << std::endl; - + fp << "\t\t"; fp << "end else begin"; fp << std::endl; - + fp << "\t\t\t"; fp << generate_verilog_port_constant_values( - curr_bit_skip_reg, std::vector(curr_bit_skip_reg.get_width(), 0), true); + curr_bit_skip_reg, + std::vector(curr_bit_skip_reg.get_width(), 0), true); fp << ";" << std::endl; - + fp << "\t\t"; fp << "end"; fp << std::endl; - + fp << "\t"; fp << "end"; fp << std::endl; - + fp << "end"; fp << std::endl; } @@ -1824,7 +1865,8 @@ static void print_verilog_full_testbench_configuration_chain_bitstream( BasicPort config_done_port(std::string(TOP_TB_CONFIG_DONE_PORT_NAME), 1); fp << "\t\t"; - std::vector config_done_final_values(config_done_port.get_width(), 1); + std::vector config_done_final_values(config_done_port.get_width(), + 1); fp << generate_verilog_port_constant_values(config_done_port, config_done_final_values, true); fp << ";" << std::endl; @@ -1842,8 +1884,8 @@ static void print_verilog_full_testbench_configuration_chain_bitstream( fp << "\t\t"; fp << generate_verilog_port(VERILOG_PORT_CONKT, config_chain_head_port); fp << " <= "; - fp << TOP_TB_BITSTREAM_MEM_REG_NAME << "[" << TOP_TB_BITSTREAM_INDEX_REG_NAME - << "]"; + fp << TOP_TB_BITSTREAM_MEM_REG_NAME << "[" + << TOP_TB_BITSTREAM_INDEX_REG_NAME << "]"; fp << ";" << std::endl; fp << "\t\t"; @@ -1875,19 +1917,23 @@ static void print_verilog_full_testbench_configuration_chain_bitstream( fp << ") begin"; fp << std::endl; - BasicPort config_done_port(std::string(TOP_TB_CONFIG_DONE_PORT_NAME), iclk, iclk); + BasicPort config_done_port(std::string(TOP_TB_CONFIG_DONE_PORT_NAME), + iclk, iclk); fp << "\t\t"; - std::vector config_done_final_values(config_done_port.get_width(), 1); - fp << generate_verilog_port_constant_values(config_done_port, - config_done_final_values, true); + std::vector config_done_final_values(config_done_port.get_width(), + 1); + fp << generate_verilog_port_constant_values( + config_done_port, config_done_final_values, true); fp << ";" << std::endl; fp << "\t"; fp << "end else if ("; /* Wait for previous configuration chain finished */ if (iclk > 0) { - BasicPort prev_config_done_port(std::string(TOP_TB_CONFIG_DONE_PORT_NAME), iclk - 1, iclk - 1); - std::vector prev_config_done_final_values(prev_config_done_port.get_width(), 1); + BasicPort prev_config_done_port( + std::string(TOP_TB_CONFIG_DONE_PORT_NAME), iclk - 1, iclk - 1); + std::vector prev_config_done_final_values( + prev_config_done_port.get_width(), 1); fp << generate_verilog_port(VERILOG_PORT_CONKT, prev_config_done_port); fp << " == "; fp << generate_verilog_constant_values(prev_config_done_final_values); @@ -1904,8 +1950,8 @@ static void print_verilog_full_testbench_configuration_chain_bitstream( fp << "\t\t"; fp << generate_verilog_port(VERILOG_PORT_CONKT, config_chain_head_port); fp << " <= "; - fp << TOP_TB_BITSTREAM_MEM_REG_NAME << "[" << TOP_TB_BITSTREAM_INDEX_REG_NAME << iclk - << "]"; + fp << TOP_TB_BITSTREAM_MEM_REG_NAME << "[" + << TOP_TB_BITSTREAM_INDEX_REG_NAME << iclk << "]"; fp << ";" << std::endl; fp << "\t\t"; @@ -2254,7 +2300,8 @@ static void print_verilog_full_testbench_bitstream( case CONFIG_MEM_SCAN_CHAIN: print_verilog_full_testbench_configuration_chain_bitstream( fp, bitstream_file, fast_configuration, bit_value_to_skip, - module_manager, top_module, bitstream_manager, fabric_bitstream, config_protocol); + module_manager, top_module, bitstream_manager, fabric_bitstream, + config_protocol); break; case CONFIG_MEM_MEMORY_BANK: print_verilog_full_testbench_memory_bank_bitstream( @@ -2478,8 +2525,8 @@ int print_verilog_full_testbench( /* Generate stimuli for general control signals */ print_verilog_top_testbench_generic_stimulus( - fp, config_protocol, simulation_parameters, num_config_clock_cycles, prog_clock_period, - default_op_clock_period, VERILOG_SIM_TIMESCALE); + fp, config_protocol, simulation_parameters, num_config_clock_cycles, + prog_clock_period, default_op_clock_period, VERILOG_SIM_TIMESCALE); /* Generate stimuli for programming interface */ int status = CMD_EXEC_SUCCESS; @@ -2519,8 +2566,9 @@ int print_verilog_full_testbench( /* Generate stimuli for global ports or connect them to existed signals */ print_verilog_top_testbench_global_ports_stimuli( - fp, module_manager, top_module, pin_constraints, config_protocol, global_ports, - simulation_parameters, active_global_prog_reset, active_global_prog_set); + fp, module_manager, top_module, pin_constraints, config_protocol, + global_ports, simulation_parameters, active_global_prog_reset, + active_global_prog_set); /* Instanciate FPGA top-level module */ print_verilog_testbench_fpga_instance( @@ -2585,9 +2633,9 @@ int print_verilog_full_testbench( clock_port_names, std::string(TOP_TB_OP_CLOCK_PORT_NAME)); /* Add autocheck for configuration phase */ - print_verilog_top_testbench_check(fp, - std::string(TOP_TB_CONFIG_ALL_DONE_PORT_NAME), - std::string(TOP_TESTBENCH_ERROR_COUNTER)); + print_verilog_top_testbench_check( + fp, std::string(TOP_TB_CONFIG_ALL_DONE_PORT_NAME), + std::string(TOP_TESTBENCH_ERROR_COUNTER)); } /* Find simulation time */ diff --git a/openfpga/src/utils/fabric_bitstream_utils.cpp b/openfpga/src/utils/fabric_bitstream_utils.cpp index a8b5d6d82..d26eff686 100644 --- a/openfpga/src/utils/fabric_bitstream_utils.cpp +++ b/openfpga/src/utils/fabric_bitstream_utils.cpp @@ -22,7 +22,8 @@ namespace openfpga { /******************************************************************** * Find the longest bitstream size of a fabric bitstream - * Only care the region in whitelist. If the whitelist is empty, consider all the regions + * Only care the region in whitelist. If the whitelist is empty, consider all + *the regions *******************************************************************/ size_t find_fabric_regional_bitstream_max_size( const FabricBitstream& fabric_bitstream, @@ -30,7 +31,9 @@ size_t find_fabric_regional_bitstream_max_size( size_t regional_bitstream_max_size = 0; /* Find the longest regional bitstream */ for (const auto& region : fabric_bitstream.regions()) { - if (!region_whitelist.empty() && (std::find(region_whitelist.begin(), region_whitelist.end(), size_t(region)) != region_whitelist.end())) { + if (!region_whitelist.empty() && + (std::find(region_whitelist.begin(), region_whitelist.end(), + size_t(region)) != region_whitelist.end())) { continue; } if (regional_bitstream_max_size < @@ -60,7 +63,9 @@ size_t find_configuration_chain_fabric_bitstream_size_to_be_skipped( size_t num_bits_to_skip = size_t(-1); for (const auto& region : fabric_bitstream.regions()) { - if (!region_whitelist.empty() && (std::find(region_whitelist.begin(), region_whitelist.end(), size_t(region)) != region_whitelist.end())) { + if (!region_whitelist.empty() && + (std::find(region_whitelist.begin(), region_whitelist.end(), + size_t(region)) != region_whitelist.end())) { continue; } size_t curr_region_num_bits_to_skip = 0; From 679c6e9b4330025a382a08359ff04bab20e06a7a Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 24 Apr 2023 14:05:51 +0800 Subject: [PATCH 158/166] [core] debugging --- .../fpga_verilog/verilog_top_testbench.cpp | 37 +++++++++++-------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp index 559277839..9b23b6d37 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp @@ -877,7 +877,7 @@ static void print_verilog_top_testbench_ports( * pulled up */ BasicPort config_all_done_port(std::string(TOP_TB_CONFIG_ALL_DONE_PORT_NAME), 1); - fp << generate_verilog_port(VERILOG_PORT_REG, config_all_done_port) << ";" + fp << generate_verilog_port(VERILOG_PORT_WIRE, config_all_done_port) << ";" << std::endl; /* Programming clock: same rule applied as the configuration done ports */ @@ -1277,12 +1277,12 @@ static void print_verilog_top_testbench_generic_stimulus( BasicPort curr_cfg_pin(config_done_port.get_name(), config_done_port.pins()[pin], config_done_port.pins()[pin]); - if (pin > 1) { + if (pin > 0) { fp << " & "; } fp << generate_verilog_port(VERILOG_PORT_CONKT, curr_cfg_pin); } - fp << ";"; + fp << ";" << std::endl; /* Generate stimuli waveform for multiple user-defined operating clock signals */ @@ -1692,10 +1692,20 @@ static void print_verilog_full_testbench_configuration_chain_bitstream( fp << ";"; fp << std::endl; - fp << "\t"; - fp << TOP_TB_BITSTREAM_INDEX_REG_NAME << " <= 0"; - fp << ";"; - fp << std::endl; + if (num_prog_clocks == 1) { + fp << "\t"; + fp << TOP_TB_BITSTREAM_INDEX_REG_NAME << " <= 0"; + fp << ";"; + fp << std::endl; + } else { + VTR_ASSERT(num_prog_clocks > 1); + for (size_t iclk = 0; iclk < num_prog_clocks; ++iclk) { + fp << "\t"; + fp << TOP_TB_BITSTREAM_INDEX_REG_NAME << iclk << " <= 0"; + fp << ";"; + fp << std::endl; + } + } std::vector bit_skip_values(bit_skip_reg.get_width(), fast_configuration ? 1 : 0); @@ -1761,9 +1771,6 @@ static void print_verilog_full_testbench_configuration_chain_bitstream( fp << "\t"; fp << "end"; fp << std::endl; - - fp << "end"; - fp << std::endl; } else { VTR_ASSERT(num_prog_clocks > 1); for (size_t iclk = 0; iclk < num_prog_clocks; ++iclk) { @@ -1781,10 +1788,10 @@ static void print_verilog_full_testbench_configuration_chain_bitstream( config_protocol.prog_clock_pins()[iclk]); fp << "\t\t"; fp << "if ("; - bool first_pin = false; + bool first_pin = true; for (size_t ccff_head_idx : ccff_head_indices) { if (!first_pin) { - fp << " & "; + fp << " && "; } fp << generate_verilog_constant_values( std::vector(1, bit_value_to_skip)); @@ -1792,6 +1799,7 @@ static void print_verilog_full_testbench_configuration_chain_bitstream( fp << TOP_TB_BITSTREAM_MEM_REG_NAME << "[" << TOP_TB_BITSTREAM_ITERATOR_REG_NAME << "][" << ccff_head_idx << "]"; + first_pin = false; } fp << ")"; fp << " begin"; @@ -1835,11 +1843,10 @@ static void print_verilog_full_testbench_configuration_chain_bitstream( fp << "\t"; fp << "end"; fp << std::endl; - - fp << "end"; - fp << std::endl; } } + fp << "end"; + fp << std::endl; BasicPort prog_clock_port(std::string(TOP_TB_PROG_CLOCK_PORT_NAME) + std::string(TOP_TB_CLOCK_REG_POSTFIX), From d9af8dd722bb79d6d8949f031d65c20868b049a7 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 24 Apr 2023 14:50:42 +0800 Subject: [PATCH 159/166] [core] did some dirty fix but now dv should pass. Not sure why usig a shorter bitstream does not work --- .../fpga_verilog/verilog_top_testbench.cpp | 36 +++++-------------- 1 file changed, 8 insertions(+), 28 deletions(-) diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp index 9b23b6d37..cc405f94e 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp @@ -989,13 +989,9 @@ static size_t calculate_num_config_clock_cycles( * different calculation */ if (config_protocol.type() == CONFIG_MEM_SCAN_CHAIN) { if (config_protocol.num_prog_clocks() > 1) { - regional_bitstream_max_size = 0; - for (BasicPort prog_clk_pin : config_protocol.prog_clock_pins()) { - std::vector ccff_head_indices = - config_protocol.prog_clock_pin_ccff_head_indices(prog_clk_pin); - regional_bitstream_max_size += find_fabric_regional_bitstream_max_size( - fabric_bitstream, ccff_head_indices); - } + regional_bitstream_max_size = + config_protocol.num_prog_clocks() * + find_fabric_regional_bitstream_max_size(fabric_bitstream); } } @@ -1026,15 +1022,10 @@ static size_t calculate_num_config_clock_cycles( fabric_bitstream, bitstream_manager, bit_value_to_skip); if (config_protocol.num_prog_clocks() > 1) { - num_bits_to_skip = 0; - for (BasicPort prog_clk_pin : config_protocol.prog_clock_pins()) { - std::vector ccff_head_indices = - config_protocol.prog_clock_pin_ccff_head_indices(prog_clk_pin); - num_bits_to_skip += - find_configuration_chain_fabric_bitstream_size_to_be_skipped( - fabric_bitstream, bitstream_manager, bit_value_to_skip, - ccff_head_indices); - } + num_bits_to_skip = + config_protocol.num_prog_clocks() * + find_configuration_chain_fabric_bitstream_size_to_be_skipped( + fabric_bitstream, bitstream_manager, bit_value_to_skip); } num_config_clock_cycles = @@ -1619,21 +1610,10 @@ static void print_verilog_full_testbench_configuration_chain_bitstream( /* Additional constants for multiple programming clock */ if (num_prog_clocks > 1) { for (size_t iclk = 0; iclk < num_prog_clocks; ++iclk) { - std::vector ccff_head_indices = - config_protocol.prog_clock_pin_ccff_head_indices( - config_protocol.prog_clock_pins()[iclk]); - size_t curr_regional_bitstream_max_size = - find_fabric_regional_bitstream_max_size(fabric_bitstream, - ccff_head_indices); - size_t curr_num_bits_to_skip = - find_configuration_chain_fabric_bitstream_size_to_be_skipped( - fabric_bitstream, bitstream_manager, bit_value_to_skip, - ccff_head_indices); - print_verilog_define_flag( fp, std::string(TOP_TB_BITSTREAM_LENGTH_VARIABLE) + std::to_string(iclk), - curr_regional_bitstream_max_size - curr_num_bits_to_skip); + regional_bitstream_max_size - num_bits_to_skip); } } From f06248a1b00364885a0f5a9f1e4fea0a99a3ccd7 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 24 Apr 2023 14:55:22 +0800 Subject: [PATCH 160/166] [test] add a new testcase to validate the ccff v2 --- ...4_N4_40nm_multi_region_cc3clk_openfpga.xml | 195 ++++++++++++++++++ .../regression_test_scripts/basic_reg_test.sh | 1 + .../config/task.conf | 45 ++++ 3 files changed, 241 insertions(+) create mode 100644 openfpga_flow/openfpga_arch/k4_N4_40nm_multi_region_cc3clk_openfpga.xml create mode 100644 openfpga_flow/tasks/basic_tests/full_testbench/multi_region_configuration_chain_3clk/config/task.conf diff --git a/openfpga_flow/openfpga_arch/k4_N4_40nm_multi_region_cc3clk_openfpga.xml b/openfpga_flow/openfpga_arch/k4_N4_40nm_multi_region_cc3clk_openfpga.xml new file mode 100644 index 000000000..d68a4cc3e --- /dev/null +++ b/openfpga_flow/openfpga_arch/k4_N4_40nm_multi_region_cc3clk_openfpga.xml @@ -0,0 +1,195 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + + + + + 10e-12 5e-12 5e-12 + + + 10e-12 5e-12 5e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/openfpga_flow/regression_test_scripts/basic_reg_test.sh b/openfpga_flow/regression_test_scripts/basic_reg_test.sh index bc437ec0b..dd9e64a56 100755 --- a/openfpga_flow/regression_test_scripts/basic_reg_test.sh +++ b/openfpga_flow/regression_test_scripts/basic_reg_test.sh @@ -26,6 +26,7 @@ run-task basic_tests/full_testbench/configuration_chain_use_set_reset $@ run-task basic_tests/full_testbench/configuration_chain_config_enable_scff $@ run-task basic_tests/full_testbench/multi_region_configuration_chain $@ run-task basic_tests/full_testbench/multi_region_configuration_chain_2clk $@ +run-task basic_tests/full_testbench/multi_region_configuration_chain_3clk $@ run-task basic_tests/full_testbench/fast_configuration_chain $@ run-task basic_tests/full_testbench/fast_configuration_chain_use_set $@ run-task basic_tests/full_testbench/smart_fast_configuration_chain $@ diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/multi_region_configuration_chain_3clk/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/multi_region_configuration_chain_3clk/config/task.conf new file mode 100644 index 000000000..26bd594e5 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/full_testbench/multi_region_configuration_chain_3clk/config/task.conf @@ -0,0 +1,45 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = true +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=yosys_vpr + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_multi_region_cc3clk_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout=--device 2x2 +openfpga_fast_configuration= + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v +bench1=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/or2/or2.v +bench2=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2_latch/and2_latch.v + +[SYNTHESIS_PARAM] +bench_read_verilog_options_common = -nolatches +bench0_top = and2 +bench0_chan_width = 300 + +bench1_top = or2 +bench1_chan_width = 300 + +bench2_top = and2_latch +bench2_chan_width = 300 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= From e11e4dc3f43daeed16c72c2efb06f2bdbd113417 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 24 Apr 2023 14:59:43 +0800 Subject: [PATCH 161/166] [core] comment on current limitations --- openfpga/src/fpga_verilog/verilog_top_testbench.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp index cc405f94e..b98a44007 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp @@ -989,6 +989,8 @@ static size_t calculate_num_config_clock_cycles( * different calculation */ if (config_protocol.type() == CONFIG_MEM_SCAN_CHAIN) { if (config_protocol.num_prog_clocks() > 1) { + /* TODO: Try to apply different length as the bitstream size for ccffs are + * different driven by differnt clocks! Tried but no luck yet. */ regional_bitstream_max_size = config_protocol.num_prog_clocks() * find_fabric_regional_bitstream_max_size(fabric_bitstream); @@ -1610,6 +1612,8 @@ static void print_verilog_full_testbench_configuration_chain_bitstream( /* Additional constants for multiple programming clock */ if (num_prog_clocks > 1) { for (size_t iclk = 0; iclk < num_prog_clocks; ++iclk) { + /* TODO: Try to apply different length as the bitstream size for ccffs are + * different driven by differnt clocks! Tried but no luck yet. */ print_verilog_define_flag( fp, std::string(TOP_TB_BITSTREAM_LENGTH_VARIABLE) + std::to_string(iclk), From 13bb4bf88a6360774a22c6e40687e74d79981fb5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Apr 2023 07:01:45 +0000 Subject: [PATCH 162/166] Bump yosys from `a9c792d` to `51dd029` Bumps [yosys](https://github.com/YosysHQ/yosys) from `a9c792d` to `51dd029`. - [Release notes](https://github.com/YosysHQ/yosys/releases) - [Commits](https://github.com/YosysHQ/yosys/compare/a9c792dceef4be21059ff4732d1aff62e67d96bc...51dd0290241c521f5498f71f4fd4fb0598d83a76) --- updated-dependencies: - dependency-name: yosys dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- yosys | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yosys b/yosys index a9c792dce..51dd02902 160000 --- a/yosys +++ b/yosys @@ -1 +1 @@ -Subproject commit a9c792dceef4be21059ff4732d1aff62e67d96bc +Subproject commit 51dd0290241c521f5498f71f4fd4fb0598d83a76 From a721ee2025d6d1b5e365b950a03c169ff232f302 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Apr 2023 07:01:50 +0000 Subject: [PATCH 163/166] Bump yosys-plugins from `137606e` to `6b69bc5` Bumps [yosys-plugins](https://github.com/SymbiFlow/yosys-symbiflow-plugins) from `137606e` to `6b69bc5`. - [Release notes](https://github.com/SymbiFlow/yosys-symbiflow-plugins/releases) - [Commits](https://github.com/SymbiFlow/yosys-symbiflow-plugins/compare/137606ebfad8de60aa44d37c11a20c540bbdba98...6b69bc5ed8eafbaca6f143062dbe0c486a8a37b3) --- updated-dependencies: - dependency-name: yosys-plugins dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- yosys-plugins | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yosys-plugins b/yosys-plugins index 137606ebf..6b69bc5ed 160000 --- a/yosys-plugins +++ b/yosys-plugins @@ -1 +1 @@ -Subproject commit 137606ebfad8de60aa44d37c11a20c540bbdba98 +Subproject commit 6b69bc5ed8eafbaca6f143062dbe0c486a8a37b3 From 18b078d1d5afadbd463f48caa5b6871424ce37a5 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 24 Apr 2023 21:20:07 +0800 Subject: [PATCH 164/166] [core] fixed bugs which cause ci failed --- libs/libarchopenfpga/src/config_protocol.cpp | 3 +++ openfpga/src/utils/check_config_protocol.cpp | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/libs/libarchopenfpga/src/config_protocol.cpp b/libs/libarchopenfpga/src/config_protocol.cpp index fc3a43d95..848bc9011 100644 --- a/libs/libarchopenfpga/src/config_protocol.cpp +++ b/libs/libarchopenfpga/src/config_protocol.cpp @@ -259,6 +259,9 @@ void ConfigProtocol::set_wl_num_banks(const size_t& num_banks) { ***********************************************************************/ int ConfigProtocol::validate_ccff_prog_clocks() const { int num_err = 0; + if (prog_clock_pins().empty()) { + return num_err; + } /* Initialize scoreboard */ std::vector ccff_head_scoreboard(num_regions(), 0); for (openfpga::BasicPort port : prog_clock_pins()) { diff --git a/openfpga/src/utils/check_config_protocol.cpp b/openfpga/src/utils/check_config_protocol.cpp index aba9a58d5..ebeec23bd 100644 --- a/openfpga/src/utils/check_config_protocol.cpp +++ b/openfpga/src/utils/check_config_protocol.cpp @@ -22,7 +22,7 @@ static int check_config_protocol_programming_clock( const ConfigProtocol& config_protocol, const CircuitLibrary& circuit_lib) { int num_err = 0; /* Programming clock is only available for CCFF */ - if (config_protocol.type() == CONFIG_MEM_SCAN_CHAIN) { + if (config_protocol.type() != CONFIG_MEM_SCAN_CHAIN) { return num_err; } /* Must find a CCFF model */ From e20ac5f27232314870e7328ab5098efde43f4f79 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 24 Apr 2023 22:46:46 +0800 Subject: [PATCH 165/166] [core] fixed a bug which cause configuration protocols other than ccff failed --- libs/libarchopenfpga/src/config_protocol.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libs/libarchopenfpga/src/config_protocol.cpp b/libs/libarchopenfpga/src/config_protocol.cpp index 848bc9011..00de87a41 100644 --- a/libs/libarchopenfpga/src/config_protocol.cpp +++ b/libs/libarchopenfpga/src/config_protocol.cpp @@ -27,7 +27,9 @@ CircuitModelId ConfigProtocol::memory_model() const { return memory_model_; } int ConfigProtocol::num_regions() const { return num_regions_; } size_t ConfigProtocol::num_prog_clocks() const { - VTR_ASSERT(type_ == CONFIG_MEM_SCAN_CHAIN); + if (type_ != CONFIG_MEM_SCAN_CHAIN) { + return 1; + } if (prog_clk_port_.is_valid()) { return prog_clk_port_.get_width(); } From b866d2757ab9f8cac38fdbdd805bf26a6736da56 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 25 Apr 2023 00:51:28 +0000 Subject: [PATCH 166/166] Updated Patch Count --- VERSION.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION.md b/VERSION.md index 2b92ea739..24b435dac 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -1.2.935 +1.2.971